Removed some redundancies between imap and pop3
[monky] / src / conky.c
index 945df07..7d00d4b 100644 (file)
@@ -7,7 +7,7 @@
  * Please see COPYING for details
  *
  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
- * Copyright (c) 2005-2007 Brenden Matthews, Philip Kovacs, et. al.
+ * Copyright (c) 2005-2008 Brenden Matthews, Philip Kovacs, et. al.
  *     (see AUTHORS)
  * All rights reserved.
  *
@@ -26,8 +26,8 @@
  * $Id$ */
 
 #include "conky.h"
-#include <stdio.h>
-#include <stdlib.h>
+#include <stdarg.h>
+#include <math.h>
 #include <ctype.h>
 #include <time.h>
 #include <locale.h>
@@ -35,7 +35,6 @@
 #include <unistd.h>
 #include <errno.h>
 #include <termios.h>
-#include <string.h>
 #include <limits.h>
 #if HAVE_DIRENT_H
 #include <dirent.h>
 #define CONFIG_FILE "$HOME/.conkyrc"
 #define MAIL_FILE "$MAIL"
 #define MAX_IF_BLOCK_DEPTH 5
+#define MAX_TAIL_LINES 100
 
 /* #define SIGNAL_BLOCKING */
 #undef SIGNAL_BLOCKING
 
-static void print_version()
+static void print_version(void) __attribute__((noreturn));
+
+static void print_version(void)
 {
        printf("Conky %s compiled %s for %s\n", VERSION, BUILD_DATE, BUILD_ARCH);
 
@@ -121,13 +123,16 @@ static void print_version()
 #ifdef SMAPI
        "  * smapi\n"
 #endif /* SMAPI */
+#ifdef NVIDIA
+       "  * nvidia\n"
+#endif
        "", SYSTEM_CONFIG_FILE
        );
 
        exit(0);
 }
 
-static char *suffixes[] = { "B", "kiB", "MiB", "GiB", "TiB", "PiB", "" };
+static const char *suffixes[] = { "B", "kiB", "MiB", "GiB", "TiB", "PiB", "" };
 
 #ifdef X11
 
@@ -188,7 +193,7 @@ struct font_list *fonts = NULL;
 
 #define MAX_FONTS 64 // hmm, no particular reason, just makes sense.
 
-static void set_font();
+static void set_font(void);
 
 int addfont(const char *data_in)
 {
@@ -234,14 +239,14 @@ void set_first_font(const char *data_in)
                font_count++;
        }
        if (strlen(data_in) > 1) {
-               strncpy(fonts[0].name, data_in, DEFAULT_TEXT_BUFFER_SIZE - 1);
+               strncpy(fonts[0].name, data_in, DEFAULT_TEXT_BUFFER_SIZE);
 #ifdef XFT
                fonts[0].font_alpha = 0xffff;
 #endif
        }
 }
 
-void free_fonts()
+void free_fonts(void)
 {
        int i;
 
@@ -263,7 +268,7 @@ void free_fonts()
        selected_font = 0;
 }
 
-static void load_fonts()
+static void load_fonts(void)
 {
        int i;
 
@@ -331,6 +336,8 @@ static int cpu_avg_samples, net_avg_samples;
 
 #ifdef X11
 
+static int show_graph_scale;
+
 /* Position on the screen */
 static int text_alignment;
 static int gap_x, gap_y;
@@ -387,11 +394,7 @@ static iconv_t **iconv_cd = 0;
 
 int register_iconv(iconv_t *new_iconv)
 {
-       if (iconv_cd) {
-               iconv_cd = realloc(iconv, sizeof(iconv_t *) * (iconv_count + 1));
-       } else {
-               iconv_cd = malloc(sizeof(iconv_t *));
-       }
+       iconv_cd = realloc(iconv_cd, sizeof(iconv_t *) * (iconv_count + 1));
        if (!iconv_cd) {
                CRIT_ERR("Out of memory");
        }
@@ -435,8 +438,8 @@ static int pad_percents = 0;
 tcp_port_monitor_args_t tcp_port_monitor_args;
 #endif
 
-static char *text = 0;
-long text_lines;
+static char *global_text = 0;
+long global_text_lines;
 
 static int total_updates;
 
@@ -476,10 +479,10 @@ static inline int calc_text_width(const char *s, int l)
 
                if (utf8_mode) {
                        XftTextExtentsUtf8(display, fonts[selected_font].xftfont,
-                               (FcChar8 *) s, l, &gi);
+                               (const FcChar8 *) s, l, &gi);
                } else {
                        XftTextExtents8(display, fonts[selected_font].xftfont,
-                               (FcChar8 *) s, l, &gi);
+                               (const FcChar8 *) s, l, &gi);
                }
                return gi.xOff;
        } else
@@ -523,6 +526,7 @@ struct special_t {
        long arg;
        double *graph;
        double graph_scale;
+       short show_scale;
        int graph_width;
        int scaled;
        unsigned long first_colour;     // for graph gradient
@@ -676,7 +680,7 @@ static const char *scan_bar(const char *args, int *w, int *h)
 static char *scan_font(const char *args)
 {
        if (args && *args) {
-               return strdup(args);
+               return strndup(args, DEFAULT_TEXT_BUFFER_SIZE);
        }
 
        return NULL;
@@ -704,13 +708,13 @@ static void new_font(char *buf, char *args)
        }
 }
 #endif
-
 inline void graph_append(struct special_t *graph, double f)
 {
+       int i;
+
        if (!graph->scaled && f > graph->graph_scale) {
                f = graph->graph_scale;
        }
-       int i;
 
        if (graph->scaled) {
                graph->graph_scale = 1;
@@ -727,7 +731,7 @@ inline void graph_append(struct special_t *graph, double f)
 }
 
 short colour_depth = 0;
-void set_up_gradient();
+void set_up_gradient(void);
 
 /* precalculated: 31/255, and 63/255 */
 #define CONST_8_TO_5_BITS 0.12156862745098
@@ -782,8 +786,10 @@ static void new_graph(char *buf, int w, int h, unsigned int first_colour,
        } */
        if (s->scaled) {
                s->graph_scale = 1;
+               s->show_scale = 1;
        } else {
                s->graph_scale = scale;
+               s->show_scale = 0;
        }
        if (append) {
                graph_append(s, i);
@@ -795,6 +801,7 @@ static char *scan_graph(const char *args, int *w, int *h,
                unsigned int *scale)
 {
        char buf[64];
+       buf[0] = 0;
 
        /* zero width means all space that is available */
        *w = 0;
@@ -804,7 +811,7 @@ static char *scan_graph(const char *args, int *w, int *h,
        *scale = 0;
        /* graph's argument is either height or height,width */
        if (args) {
-               if (sscanf(args, "%d,%d %x %x %i", h, w, first_colour, last_colour,
+               if (sscanf(args, "%d,%d %x %x %u", h, w, first_colour, last_colour,
                                scale) == 5) {
                        return NULL;
                }
@@ -812,56 +819,56 @@ static char *scan_graph(const char *args, int *w, int *h,
                if (sscanf(args, "%d,%d %x %x", h, w, first_colour, last_colour) == 4) {
                        return NULL;
                }
-               if (sscanf(args, "%63s %d,%d %x %x %i", buf, h, w, first_colour,
+               if (sscanf(args, "%63s %d,%d %x %x %u", buf, h, w, first_colour,
                                last_colour, scale) == 6) {
-                       return strdup(buf);
+                       return strndup(buf, text_buffer_size);
                }
                *scale = 0;
                if (sscanf(args, "%63s %d,%d %x %x", buf, h, w, first_colour,
                                last_colour) == 5) {
-                       return strdup(buf);
+                       return strndup(buf, text_buffer_size);
                }
                buf[0] = '\0';
                *h = 25;
                *w = 0;
-               if (sscanf(args, "%x %x %i", first_colour, last_colour, scale) == 3) {
+               if (sscanf(args, "%x %x %u", first_colour, last_colour, scale) == 3) {
                        return NULL;
                }
                *scale = 0;
                if (sscanf(args, "%x %x", first_colour, last_colour) == 2) {
                        return NULL;
                }
-               if (sscanf(args, "%63s %x %x %i", buf, first_colour, last_colour,
+               if (sscanf(args, "%63s %x %x %u", buf, first_colour, last_colour,
                                scale) == 4) {
-                       return strdup(buf);
+                       return strndup(buf, text_buffer_size);
                }
                *scale = 0;
                if (sscanf(args, "%63s %x %x", buf, first_colour, last_colour) == 3) {
-                       return strdup(buf);
+                       return strndup(buf, text_buffer_size);
                }
                buf[0] = '\0';
                *first_colour = 0;
                *last_colour = 0;
-               if (sscanf(args, "%d,%d %i", h, w, scale) == 3) {
+               if (sscanf(args, "%d,%d %u", h, w, scale) == 3) {
                        return NULL;
                }
                *scale = 0;
                if (sscanf(args, "%d,%d", h, w) == 2) {
                        return NULL;
                }
-               if (sscanf(args, "%63s %d,%d %i", buf, h, w, scale) < 4) {
+               if (sscanf(args, "%63s %d,%d %u", buf, h, w, scale) < 4) {
                        *scale = 0;
                        //TODO: check the return value and throw an error?
                        sscanf(args, "%63s %d,%d", buf, h, w);
                }
 
-               return strdup(buf);
+               return strndup(buf, text_buffer_size);
        }
 
        if (buf[0] == '\0') {
                return NULL;
        } else {
-               return strdup(buf);
+               return strndup(buf, text_buffer_size);
        }
 }
 
@@ -908,6 +915,7 @@ static inline void new_alignr(char *buf, long c)
        new_special(buf, ALIGNR)->arg = c;
 }
 
+// A postive offset pushes the text further left
 static inline void new_alignc(char *buf, long c)
 {
        new_special(buf, ALIGNC)->arg = c;
@@ -969,14 +977,19 @@ static void convert_escapes(char *buf)
 /* Prints anything normally printed with snprintf according to the current value
  * of use_spacer.  Actually slightly more flexible than snprintf, as you can
  * safely specify the destination buffer as one of your inputs.  */
-static int spaced_print(char *buf, int size, char *format, int width,
-               char *func_name, ...) {
+static int spaced_print(char *, int, const char *, int, const char *, ...)
+               __attribute__((format(printf, 3, 6)));
+
+static int spaced_print(char *buf, int size, const char *format, int width,
+               const char *func_name, ...) {
        int len;
        va_list argp;
+       char *tempbuf;
+
        if (size < 1) {
                return 0;
        }
-       char *tempbuf = malloc(size * sizeof(char));
+       tempbuf = malloc(size * sizeof(char));
 
        // Passes the varargs along to vsnprintf
        va_start(argp, func_name);
@@ -1004,9 +1017,9 @@ static int spaced_print(char *buf, int size, char *format, int width,
 }
 
 /* converts from bytes to human readable format (k, M, G, T) */
-static void human_readable(long long num, char *buf, int size, char *func_name)
+static void human_readable(long long num, char *buf, int size, const char *func_name)
 {
-       char **suffix = suffixes;
+       const char **suffix = suffixes;
        float fnum;
        int precision, len;
        static const int WIDTH = 10, SHORT_WIDTH = 8;
@@ -1084,6 +1097,7 @@ enum text_object_type {
        OBJ_cpu,
        OBJ_cpubar,
        OBJ_cpugraph,
+       OBJ_loadgraph,
        OBJ_diskio,
        OBJ_diskio_read,
        OBJ_diskio_write,
@@ -1180,6 +1194,8 @@ enum text_object_type {
        OBJ_memgraph,
        OBJ_memmax,
        OBJ_memperc,
+       OBJ_mem_res,
+       OBJ_mem_vsize,
        OBJ_mixer,
        OBJ_mixerl,
        OBJ_mixerr,
@@ -1189,6 +1205,7 @@ enum text_object_type {
        OBJ_nameserver,
        OBJ_new_mails,
        OBJ_nodename,
+       OBJ_nvidia,
        OBJ_pre_exec,
        OBJ_processes,
        OBJ_running_processes,
@@ -1426,6 +1443,9 @@ struct text_object {
                        char *addr;
                        int port;
                        char *dev;
+                       double update_time;
+                       char *temp;
+                       char unit;
                } hddtemp;              /* 2 */
 #endif
 #ifdef RSS
@@ -1437,6 +1457,10 @@ struct text_object {
                } rss;
 #endif
                struct local_mail_s local_mail;
+#ifdef NVIDIA
+               struct nvidia_s nvidia;
+#endif /* NVIDIA */
+
        } data;
        int type;
        int a, b;
@@ -1451,10 +1475,10 @@ struct text_object_list {
        struct text_object *text_objects;
 };
 
-static unsigned int text_object_count;
-static struct text_object *text_objects;
+static struct text_object_list *global_text_object_list;
+
 static void generate_text_internal(char *p, int p_max_size,
-       struct text_object *objs, unsigned int object_count,
+       struct text_object_list *text_object_list,
        struct information *cur);
 
 #define MAXDATASIZE 1000
@@ -1464,9 +1488,10 @@ static void generate_text_internal(char *p, int p_max_size,
 struct mail_s *parse_mail_args(char type, const char *arg)
 {
        struct mail_s *mail;
+       char *tmp;
+
        mail = malloc(sizeof(struct mail_s));
        memset(mail, 0, sizeof(struct mail_s));
-       char *tmp;
 
        if (sscanf(arg, "%128s %128s %128s", mail->host, mail->user, mail->pass)
                        != 3) {
@@ -1520,8 +1545,8 @@ struct mail_s *parse_mail_args(char type, const char *arg)
        }
        tmp = strstr(arg, "-e ");
        if (tmp) {
-               tmp += 3;
                int len = 1024;
+               tmp += 3;
 
                if (tmp[0] == '\'') {
                        len = strstr(tmp + 1, "'") - tmp - 1;
@@ -1537,7 +1562,7 @@ struct mail_s *parse_mail_args(char type, const char *arg)
        return mail;
 }
 
-void *imap_thread(struct mail_s *mail)
+void *imap_thread(void *arg)
 {
        int sockfd, numbytes;
        char recvbuf[MAXDATASIZE];
@@ -1547,168 +1572,180 @@ void *imap_thread(struct mail_s *mail)
        unsigned int old_unseen = UINT_MAX;
        unsigned int old_messages = UINT_MAX;
        struct stat stat_buf;
-       struct hostent *he;
+       struct hostent he, *he_res = 0;
+       int he_errno;
+       char hostbuff[2048];
        struct sockaddr_in their_addr;  // connector's address information
+       struct mail_s *mail = (struct mail_s *)arg;
 
-       if ((he = gethostbyname(mail->host)) == NULL) { // get the host info
+#ifdef HAVE_GETHOSTBYNAME_R
+       if (gethostbyname_r(mail->host, &he, hostbuff, sizeof(hostbuff), &he_res, &he_errno)) { // get the host info
+               ERR("IMAP gethostbyname_r: %s", hstrerror(h_errno));
+               exit(1);
+       }
+#else /* HAVE_GETHOSTBYNAME_R */
+       if ((he_res = gethostbyname(mail->host)) == NULL) {     // get the host info
                herror("gethostbyname");
                exit(1);
        }
+#endif /* HAVE_GETHOSTBYNAME_R */
        while (fail < 5) {
+               struct timeval timeout;
+               int res;
+               fd_set fdset;
+
                if (fail > 0) {
                        ERR("Trying IMAP connection again for %s@%s (try %i/5)",
-                               mail->user, mail->host, fail + 1);
-               }
-               if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
-                       perror("socket");
-                       fail++;
-                       goto next_iteration;
+                                       mail->user, mail->host, fail + 1);
                }
+               do {
+                       if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
+                               perror("socket");
+                               fail++;
+                               break;
+                       }
 
-               // host byte order
-               their_addr.sin_family = AF_INET;
-               // short, network byte order
-               their_addr.sin_port = htons(mail->port);
-               their_addr.sin_addr = *((struct in_addr *) he->h_addr);
-               // zero the rest of the struct
-               memset(&(their_addr.sin_zero), '\0', 8);
+                       // host byte order
+                       their_addr.sin_family = AF_INET;
+                       // short, network byte order
+                       their_addr.sin_port = htons(mail->port);
+                       their_addr.sin_addr = *((struct in_addr *) he_res->h_addr);
+                       // zero the rest of the struct
+                       memset(&(their_addr.sin_zero), '\0', 8);
 
-               if (connect(sockfd, (struct sockaddr *) &their_addr,
-                               sizeof(struct sockaddr)) == -1) {
-                       perror("connect");
-                       fail++;
-                       goto next_iteration;
-               }
-               struct timeval timeout;
-               int res;
-               fd_set fdset;
+                       if (connect(sockfd, (struct sockaddr *) &their_addr,
+                                               sizeof(struct sockaddr)) == -1) {
+                               perror("connect");
+                               fail++;
+                               break;
+                       }
 
-               timeout.tv_sec = 60;    // 60 second timeout i guess
-               timeout.tv_usec = 0;
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
-               if (res > 0) {
-                       if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
-                               perror("recv");
+                       timeout.tv_sec = 60;    // 60 second timeout i guess
+                       timeout.tv_usec = 0;
+                       FD_ZERO(&fdset);
+                       FD_SET(sockfd, &fdset);
+                       res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
+                       if (res > 0) {
+                               if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
+                                       perror("recv");
+                                       fail++;
+                                       break;
+                               }
+                       } else {
+                               ERR("IMAP connection failed: timeout");
                                fail++;
-                               goto next_iteration;
+                               break;
                        }
-               } else {
-                       ERR("IMAP connection failed: timeout");
-                       fail++;
-                       goto next_iteration;
-               }
-               recvbuf[numbytes] = '\0';
-               if (strstr(recvbuf, "* OK") != recvbuf) {
-                       ERR("IMAP connection failed, probably not an IMAP server");
-                       fail++;
-                       goto next_iteration;
-               }
-               strncpy(sendbuf, "a1 login ", MAXDATASIZE);
-               strncat(sendbuf, mail->user, MAXDATASIZE - strlen(sendbuf) - 1);
-               strncat(sendbuf, " ", MAXDATASIZE - strlen(sendbuf) - 1);
-               strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1);
-               strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
-               if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
-                       perror("send a1");
-                       fail++;
-                       goto next_iteration;
-               }
-               timeout.tv_sec = 60;    // 60 second timeout i guess
-               timeout.tv_usec = 0;
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
-               if (res > 0) {
-                       if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
-                               perror("recv a1");
+                       recvbuf[numbytes] = '\0';
+                       if (strstr(recvbuf, "* OK") != recvbuf) {
+                               ERR("IMAP connection failed, probably not an IMAP server");
                                fail++;
-                               goto next_iteration;
-                       }
-               }
-               recvbuf[numbytes] = '\0';
-               if (strstr(recvbuf, "a1 OK") == NULL) {
-                       ERR("IMAP server login failed: %s", recvbuf);
-                       fail++;
-                       goto next_iteration;
-               }
-               strncpy(sendbuf, "a2 STATUS ", MAXDATASIZE);
-               strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
-               strncat(sendbuf, " (MESSAGES UNSEEN)\r\n",
-                       MAXDATASIZE - strlen(sendbuf) - 1);
-               if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
-                       perror("send a2");
-                       fail++;
-                       goto next_iteration;
-               }
-               timeout.tv_sec = 60;    // 60 second timeout i guess
-               timeout.tv_usec = 0;
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
-               if (res > 0) {
-                       if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
-                               perror("recv a2");
+                               break;
+                       }
+                       strncpy(sendbuf, "a1 login ", MAXDATASIZE);
+                       strncat(sendbuf, mail->user, MAXDATASIZE - strlen(sendbuf) - 1);
+                       strncat(sendbuf, " ", MAXDATASIZE - strlen(sendbuf) - 1);
+                       strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1);
+                       strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
+                       if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
+                               perror("send a1");
                                fail++;
-                               goto next_iteration;
-                       }
-               }
-               recvbuf[numbytes] = '\0';
-               if (strstr(recvbuf, "a2 OK") == NULL) {
-                       ERR("IMAP status failed: %s", recvbuf);
-                       fail++;
-                       goto next_iteration;
-               }
-               // now we get the data
-               reply = strstr(recvbuf, " (MESSAGES ");
-               reply += 2;
-               *strchr(reply, ')') = '\0';
-               if (reply == NULL) {
-                       ERR("Error parsing IMAP response: %s", recvbuf);
-                       fail++;
-                       goto next_iteration;
-               } else {
-                       timed_thread_lock(mail->p_timed_thread);
-                       sscanf(reply, "MESSAGES %lu UNSEEN %lu", &mail->messages,
-                               &mail->unseen);
-                       timed_thread_unlock(mail->p_timed_thread);
-               }
-               strncpy(sendbuf, "a3 logout\r\n", MAXDATASIZE);
-               if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
-                       perror("send a3");
-                       fail++;
-                       goto next_iteration;
-               }
-               timeout.tv_sec = 60;    // 60 second timeout i guess
-               timeout.tv_usec = 0;
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
-               if (res > 0) {
-                       if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
-                               perror("recv a3");
+                               break;
+                       }
+                       timeout.tv_sec = 60;    // 60 second timeout i guess
+                       timeout.tv_usec = 0;
+                       FD_ZERO(&fdset);
+                       FD_SET(sockfd, &fdset);
+                       res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
+                       if (res > 0) {
+                               if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
+                                       perror("recv a1");
+                                       fail++;
+                                       break;
+                               }
+                       }
+                       recvbuf[numbytes] = '\0';
+                       if (strstr(recvbuf, "a1 OK") == NULL) {
+                               ERR("IMAP server login failed: %s", recvbuf);
                                fail++;
-                               goto next_iteration;
+                               break;
                        }
-               }
-               recvbuf[numbytes] = '\0';
-               if (strstr(recvbuf, "a3 OK") == NULL) {
-                       ERR("IMAP logout failed: %s", recvbuf);
-                       fail++;
-                       goto next_iteration;
-               }
-               if (strlen(mail->command) > 1 && (mail->unseen > old_unseen
-                               || (mail->messages > old_messages && mail->unseen > 0))) {
-                       // new mail goodie
-                       if (system(mail->command) == -1) {
-                               perror("system()");
+                       strncpy(sendbuf, "a2 STATUS ", MAXDATASIZE);
+                       strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
+                       strncat(sendbuf, " (MESSAGES UNSEEN)\r\n",
+                                       MAXDATASIZE - strlen(sendbuf) - 1);
+                       if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
+                               perror("send a2");
+                               fail++;
+                               break;
                        }
-               }
-               fail = 0;
-               old_unseen = mail->unseen;
-               old_messages = mail->messages;
-next_iteration:
+                       timeout.tv_sec = 60;    // 60 second timeout i guess
+                       timeout.tv_usec = 0;
+                       FD_ZERO(&fdset);
+                       FD_SET(sockfd, &fdset);
+                       res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
+                       if (res > 0) {
+                               if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
+                                       perror("recv a2");
+                                       fail++;
+                                       break;
+                               }
+                       }
+                       recvbuf[numbytes] = '\0';
+                       if (strstr(recvbuf, "a2 OK") == NULL) {
+                               ERR("IMAP status failed: %s", recvbuf);
+                               fail++;
+                               break;
+                       }
+                       // now we get the data
+                       reply = strstr(recvbuf, " (MESSAGES ");
+                       reply += 2;
+                       *strchr(reply, ')') = '\0';
+                       if (reply == NULL) {
+                               ERR("Error parsing IMAP response: %s", recvbuf);
+                               fail++;
+                               break;
+                       } else {
+                               timed_thread_lock(mail->p_timed_thread);
+                               sscanf(reply, "MESSAGES %lu UNSEEN %lu", &mail->messages,
+                                               &mail->unseen);
+                               timed_thread_unlock(mail->p_timed_thread);
+                       }
+                       strncpy(sendbuf, "a3 logout\r\n", MAXDATASIZE);
+                       if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
+                               perror("send a3");
+                               fail++;
+                               break;
+                       }
+                       timeout.tv_sec = 60;    // 60 second timeout i guess
+                       timeout.tv_usec = 0;
+                       FD_ZERO(&fdset);
+                       FD_SET(sockfd, &fdset);
+                       res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
+                       if (res > 0) {
+                               if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
+                                       perror("recv a3");
+                                       fail++;
+                                       break;
+                               }
+                       }
+                       recvbuf[numbytes] = '\0';
+                       if (strstr(recvbuf, "a3 OK") == NULL) {
+                               ERR("IMAP logout failed: %s", recvbuf);
+                               fail++;
+                               break;
+                       }
+                       if (strlen(mail->command) > 1 && (mail->unseen > old_unseen
+                                               || (mail->messages > old_messages && mail->unseen > 0))) {
+                               // new mail goodie
+                               if (system(mail->command) == -1) {
+                                       perror("system()");
+                               }
+                       }
+                       fail = 0;
+                       old_unseen = mail->unseen;
+                       old_messages = mail->messages;
+               } while (0);
                if ((fstat(sockfd, &stat_buf) == 0) && S_ISSOCK(stat_buf.st_mode)) {
                        /* if a valid socket, close it */
                        close(sockfd);
@@ -1722,7 +1759,7 @@ next_iteration:
        return 0;
 }
 
-void *pop3_thread(struct mail_s *mail)
+void *pop3_thread(void *arg)
 {
        int sockfd, numbytes;
        char recvbuf[MAXDATASIZE];
@@ -1731,184 +1768,196 @@ void *pop3_thread(struct mail_s *mail)
        int fail = 0;
        unsigned int old_unseen = UINT_MAX;
        struct stat stat_buf;
-       struct hostent *he;
+       struct hostent he, *he_res = 0;
+       int he_errno;
+       char hostbuff[2048];
        struct sockaddr_in their_addr;  // connector's address information
+       struct mail_s *mail = (struct mail_s *)arg;
 
-       if ((he = gethostbyname(mail->host)) == NULL) { // get the host info
+#ifdef HAVE_GETHOSTBYNAME_R
+       if (gethostbyname_r(mail->host, &he, hostbuff, sizeof(hostbuff), &he_res, &he_errno)) { // get the host info
+               ERR("POP3 gethostbyname_r: %s", hstrerror(h_errno));
+               exit(1);
+       }
+#else /* HAVE_GETHOSTBYNAME_R */
+       if ((he_res = gethostbyname(mail->host)) == NULL) {     // get the host info
                herror("gethostbyname");
                exit(1);
        }
+#endif /* HAVE_GETHOSTBYNAME_R */
        while (fail < 5) {
+               struct timeval timeout;
+               int res;
+               fd_set fdset;
+
                if (fail > 0) {
                        ERR("Trying POP3 connection again for %s@%s (try %i/5)",
-                               mail->user, mail->host, fail + 1);
-               }
-               if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
-                       perror("socket");
-                       fail++;
-                       goto next_iteration;
+                                       mail->user, mail->host, fail + 1);
                }
+               do {
+                       if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
+                               perror("socket");
+                               fail++;
+                               break;
+                       }
 
-               // host byte order
-               their_addr.sin_family = AF_INET;
-               // short, network byte order
-               their_addr.sin_port = htons(mail->port);
-               their_addr.sin_addr = *((struct in_addr *) he->h_addr);
-               // zero the rest of the struct
-               memset(&(their_addr.sin_zero), '\0', 8);
+                       // host byte order
+                       their_addr.sin_family = AF_INET;
+                       // short, network byte order
+                       their_addr.sin_port = htons(mail->port);
+                       their_addr.sin_addr = *((struct in_addr *) he_res->h_addr);
+                       // zero the rest of the struct
+                       memset(&(their_addr.sin_zero), '\0', 8);
 
-               if (connect(sockfd, (struct sockaddr *) &their_addr,
-                               sizeof(struct sockaddr)) == -1) {
-                       perror("connect");
-                       fail++;
-                       goto next_iteration;
-               }
-               struct timeval timeout;
-               int res;
-               fd_set fdset;
+                       if (connect(sockfd, (struct sockaddr *) &their_addr,
+                                               sizeof(struct sockaddr)) == -1) {
+                               perror("connect");
+                               fail++;
+                               break;
+                       }
 
-               timeout.tv_sec = 60;    // 60 second timeout i guess
-               timeout.tv_usec = 0;
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
-               if (res > 0) {
-                       if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
-                               perror("recv");
+                       timeout.tv_sec = 60;    // 60 second timeout i guess
+                       timeout.tv_usec = 0;
+                       FD_ZERO(&fdset);
+                       FD_SET(sockfd, &fdset);
+                       res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
+                       if (res > 0) {
+                               if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
+                                       perror("recv");
+                                       fail++;
+                                       break;
+                               }
+                       } else {
+                               ERR("POP3 connection failed: timeout\n");
                                fail++;
-                               goto next_iteration;
+                               break;
                        }
-               } else {
-                       ERR("POP3 connection failed: timeout\n");
-                       fail++;
-                       goto next_iteration;
-               }
-               recvbuf[numbytes] = '\0';
-               if (strstr(recvbuf, "+OK ") != recvbuf) {
-                       ERR("POP3 connection failed, probably not a POP3 server");
-                       fail++;
-                       goto next_iteration;
-               }
-               strncpy(sendbuf, "USER ", MAXDATASIZE);
-               strncat(sendbuf, mail->user, MAXDATASIZE - strlen(sendbuf) - 1);
-               strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
-               if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
-                       perror("send USER");
-                       fail++;
-                       goto next_iteration;
-               }
-               timeout.tv_sec = 60;    // 60 second timeout i guess
-               timeout.tv_usec = 0;
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
-               if (res > 0) {
-                       if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
-                               perror("recv USER");
+                       recvbuf[numbytes] = '\0';
+                       if (strstr(recvbuf, "+OK ") != recvbuf) {
+                               ERR("POP3 connection failed, probably not a POP3 server");
+                               fail++;
+                               break;
+                       }
+                       strncpy(sendbuf, "USER ", MAXDATASIZE);
+                       strncat(sendbuf, mail->user, MAXDATASIZE - strlen(sendbuf) - 1);
+                       strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
+                       if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
+                               perror("send USER");
                                fail++;
-                               goto next_iteration;
-                       }
-               }
-               recvbuf[numbytes] = '\0';
-               if (strstr(recvbuf, "+OK ") == NULL) {
-                       ERR("POP3 server login failed: %s", recvbuf);
-                       fail++;
-                       goto next_iteration;
-               }
-               strncpy(sendbuf, "PASS ", MAXDATASIZE);
-               strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1);
-               strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
-               if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
-                       perror("send PASS");
-                       fail++;
-                       goto next_iteration;
-               }
-               timeout.tv_sec = 60;    // 60 second timeout i guess
-               timeout.tv_usec = 0;
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
-               if (res > 0) {
-                       if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
-                               perror("recv PASS");
+                               break;
+                       }
+                       timeout.tv_sec = 60;    // 60 second timeout i guess
+                       timeout.tv_usec = 0;
+                       FD_ZERO(&fdset);
+                       FD_SET(sockfd, &fdset);
+                       res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
+                       if (res > 0) {
+                               if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
+                                       perror("recv USER");
+                                       fail++;
+                                       break;
+                               }
+                       }
+                       recvbuf[numbytes] = '\0';
+                       if (strstr(recvbuf, "+OK ") == NULL) {
+                               ERR("POP3 server login failed: %s", recvbuf);
                                fail++;
-                               goto next_iteration;
-                       }
-               }
-               recvbuf[numbytes] = '\0';
-               if (strstr(recvbuf, "+OK ") == NULL) {
-                       ERR("POP3 server login failed: %s", recvbuf);
-                       fail++;
-                       goto next_iteration;
-               }
-               strncpy(sendbuf, "STAT\r\n", MAXDATASIZE);
-               if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
-                       perror("send STAT");
-                       fail++;
-                       goto next_iteration;
-               }
-               timeout.tv_sec = 60;    // 60 second timeout i guess
-               timeout.tv_usec = 0;
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
-               if (res > 0) {
-                       if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
-                               perror("recv STAT");
+                               break;
+                       }
+                       strncpy(sendbuf, "PASS ", MAXDATASIZE);
+                       strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1);
+                       strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
+                       if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
+                               perror("send PASS");
                                fail++;
-                               goto next_iteration;
+                               break;
                        }
-               }
-               recvbuf[numbytes] = '\0';
-               if (strstr(recvbuf, "+OK ") == NULL) {
-                       ERR("POP3 status failed: %s", recvbuf);
-                       fail++;
-                       goto next_iteration;
-               }
-               // now we get the data
-               reply = recvbuf + 4;
-               if (reply == NULL) {
-                       ERR("Error parsing POP3 response: %s", recvbuf);
-                       fail++;
-                       goto next_iteration;
-               } else {
-                       timed_thread_lock(mail->p_timed_thread);
-                       sscanf(reply, "%lu %lu", &mail->unseen, &mail->used);
-                       timed_thread_unlock(mail->p_timed_thread);
-               }
-               strncpy(sendbuf, "QUIT\r\n", MAXDATASIZE);
-               if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
-                       perror("send QUIT");
-                       fail++;
-                       goto next_iteration;
-               }
-               timeout.tv_sec = 60;    // 60 second timeout i guess
-               timeout.tv_usec = 0;
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
-               if (res > 0) {
-                       if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
-                               perror("recv QUIT");
+                       timeout.tv_sec = 60;    // 60 second timeout i guess
+                       timeout.tv_usec = 0;
+                       FD_ZERO(&fdset);
+                       FD_SET(sockfd, &fdset);
+                       res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
+                       if (res > 0) {
+                               if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
+                                       perror("recv PASS");
+                                       fail++;
+                                       break;
+                               }
+                       }
+                       recvbuf[numbytes] = '\0';
+                       if (strstr(recvbuf, "+OK ") == NULL) {
+                               ERR("POP3 server login failed: %s", recvbuf);
                                fail++;
-                               goto next_iteration;
+                               break;
                        }
-               }
-               recvbuf[numbytes] = '\0';
-               if (strstr(recvbuf, "+OK") == NULL) {
-                       ERR("POP3 logout failed: %s", recvbuf);
-                       fail++;
-                       goto next_iteration;
-               }
-               if (strlen(mail->command) > 1 && mail->unseen > old_unseen) {
-                       // new mail goodie
-                       if (system(mail->command) == -1) {
-                               perror("system()");
+                       strncpy(sendbuf, "STAT\r\n", MAXDATASIZE);
+                       if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
+                               perror("send STAT");
+                               fail++;
+                               break;
                        }
-               }
-               fail = 0;
-               old_unseen = mail->unseen;
-next_iteration:
+                       timeout.tv_sec = 60;    // 60 second timeout i guess
+                       timeout.tv_usec = 0;
+                       FD_ZERO(&fdset);
+                       FD_SET(sockfd, &fdset);
+                       res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
+                       if (res > 0) {
+                               if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
+                                       perror("recv STAT");
+                                       fail++;
+                                       break;
+                               }
+                       }
+                       recvbuf[numbytes] = '\0';
+                       if (strstr(recvbuf, "+OK ") == NULL) {
+                               ERR("POP3 status failed: %s", recvbuf);
+                               fail++;
+                               break;
+                       }
+                       // now we get the data
+                       reply = recvbuf + 4;
+                       if (reply == NULL) {
+                               ERR("Error parsing POP3 response: %s", recvbuf);
+                               fail++;
+                               break;
+                       } else {
+                               timed_thread_lock(mail->p_timed_thread);
+                               sscanf(reply, "%lu %lu", &mail->unseen, &mail->used);
+                               timed_thread_unlock(mail->p_timed_thread);
+                       }
+                       strncpy(sendbuf, "QUIT\r\n", MAXDATASIZE);
+                       if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
+                               perror("send QUIT");
+                               fail++;
+                               break;
+                       }
+                       timeout.tv_sec = 60;    // 60 second timeout i guess
+                       timeout.tv_usec = 0;
+                       FD_ZERO(&fdset);
+                       FD_SET(sockfd, &fdset);
+                       res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
+                       if (res > 0) {
+                               if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
+                                       perror("recv QUIT");
+                                       fail++;
+                                       break;
+                               }
+                       }
+                       recvbuf[numbytes] = '\0';
+                       if (strstr(recvbuf, "+OK") == NULL) {
+                               ERR("POP3 logout failed: %s", recvbuf);
+                               fail++;
+                               break;
+                       }
+                       if (strlen(mail->command) > 1 && mail->unseen > old_unseen) {
+                               // new mail goodie
+                               if (system(mail->command) == -1) {
+                                       perror("system()");
+                               }
+                       }
+                       fail = 0;
+                       old_unseen = mail->unseen;
+               } while (0);
                if ((fstat(sockfd, &stat_buf) == 0) && S_ISSOCK(stat_buf.st_mode)) {
                        /* if a valid socket, close it */
                        close(sockfd);
@@ -1922,14 +1971,20 @@ next_iteration:
        return 0;
 }
 
-void *threaded_exec(struct text_object *obj)
+void *threaded_exec(void *) __attribute__((noreturn));
+
+void *threaded_exec(void *arg)
 {
+       FILE *fp;
+       char *p2;
+       int n2;
+       struct text_object *obj = (struct text_object *)arg;
        while (1) {
-               char *p2 = obj->data.texeci.buffer;
-               FILE *fp = popen(obj->data.texeci.cmd, "r");
+               p2 = obj->data.texeci.buffer;
+               fp = popen(obj->data.texeci.cmd, "r");
 
                timed_thread_lock(obj->data.texeci.p_timed_thread);
-               int n2 = fread(p2, 1, text_buffer_size, fp);
+               n2 = fread(p2, 1, text_buffer_size, fp);
 
                pclose(fp);
                p2[n2] = '\0';
@@ -1947,85 +2002,91 @@ void *threaded_exec(struct text_object *obj)
                        timed_thread_exit(obj->data.texeci.p_timed_thread);
                }
        }
-       return 0;
+       /* never reached */
 }
 
-static struct text_object *new_text_object_internal()
+static struct text_object *new_text_object_internal(void)
 {
        struct text_object *obj = malloc(sizeof(struct text_object));
        memset(obj, 0, sizeof(struct text_object));
        return obj;
 }
 
-static void free_text_objects(unsigned int count, struct text_object *objs)
+static void free_text_objects(struct text_object_list *text_object_list)
 {
        unsigned int i;
+       struct text_object *obj;
+
+       if (text_object_list == NULL) {
+               return;
+       }
 
-       for (i = 0; i < count; i++) {
-               switch (objs[i].type) {
+       for (i = 0; i < text_object_list->text_object_count; i++) {
+               obj = &text_object_list->text_objects[i];
+               switch (obj->type) {
 #ifndef __OpenBSD__
                        case OBJ_acpitemp:
                        case OBJ_acpitempf:
-                               close(objs[i].data.i);
+                               close(obj->data.i);
                                break;
                        case OBJ_i2c:
                        case OBJ_platform:
                        case OBJ_hwmon:
-                               close(objs[i].data.sysfs.fd);
+                               close(obj->data.sysfs.fd);
                                break;
 #endif /* !__OpenBSD__ */
                        case OBJ_time:
                        case OBJ_utime:
-                               free(objs[i].data.s);
+                               free(obj->data.s);
                                break;
                        case OBJ_tztime:
-                               free(objs[i].data.tztime.tz);
-                               free(objs[i].data.tztime.fmt);
+                               free(obj->data.tztime.tz);
+                               free(obj->data.tztime.fmt);
                                break;
                        case OBJ_mboxscan:
-                               free(objs[i].data.mboxscan.args);
-                               free(objs[i].data.mboxscan.output);
+                               free(obj->data.mboxscan.args);
+                               free(obj->data.mboxscan.output);
                                break;
                        case OBJ_mails:
                        case OBJ_new_mails:
-                               free(objs[i].data.local_mail.box);
+                               free(obj->data.local_mail.box);
                                break;
                        case OBJ_imap:
                                free(info.mail);
                                break;
                        case OBJ_imap_unseen:
-                               if (!objs[i].global_mode) {
-                                       free(objs[i].data.mail);
+                               if (!obj->global_mode) {
+                                       free(obj->data.mail);
                                }
                                break;
                        case OBJ_imap_messages:
-                               if (!objs[i].global_mode) {
-                                       free(objs[i].data.mail);
+                               if (!obj->global_mode) {
+                                       free(obj->data.mail);
                                }
                                break;
                        case OBJ_pop3:
                                free(info.mail);
                                break;
                        case OBJ_pop3_unseen:
-                               if (!objs[i].global_mode) {
-                                       free(objs[i].data.mail);
+                               if (!obj->global_mode) {
+                                       free(obj->data.mail);
                                }
                                break;
                        case OBJ_pop3_used:
-                               if (!objs[i].global_mode) {
-                                       free(objs[i].data.mail);
+                               if (!obj->global_mode) {
+                                       free(obj->data.mail);
                                }
                                break;
                        case OBJ_if_empty:
                        case OBJ_if_existing:
                        case OBJ_if_mounted:
                        case OBJ_if_running:
-                               free(objs[i].data.ifblock.s);
-                               free(objs[i].data.ifblock.str);
+                               free(obj->data.ifblock.s);
+                               free(obj->data.ifblock.str);
                                break;
                        case OBJ_tail:
-                               free(objs[i].data.tail.logfile);
-                               free(objs[i].data.tail.buffer);
+                               free(obj->data.tail.logfile);
+                               free(obj->data.tail.buffer);
                                break;
                        case OBJ_text:
                        case OBJ_font:
@@ -2034,7 +2095,7 @@ static void free_text_objects(unsigned int count, struct text_object *objs)
                        case OBJ_execbar:
                        case OBJ_execgraph:
                        case OBJ_execp:
-                               free(objs[i].data.s);
+                               free(obj->data.s);
                                break;
 #ifdef HAVE_ICONV
                        case OBJ_iconv_start:
@@ -2149,30 +2210,30 @@ static void free_text_objects(unsigned int count, struct text_object *objs)
 #endif
 #ifdef RSS
                        case OBJ_rss:
-                               free(objs[i].data.rss.uri);
-                               free(objs[i].data.rss.action);
+                               free(obj->data.rss.uri);
+                               free(obj->data.rss.action);
                                break;
 #endif
                        case OBJ_pre_exec:
                                break;
 #ifndef __OpenBSD__
                        case OBJ_battery:
-                               free(objs[i].data.s);
+                               free(obj->data.s);
                                break;
                        case OBJ_battery_time:
-                               free(objs[i].data.s);
+                               free(obj->data.s);
                                break;
 #endif /* !__OpenBSD__ */
                        case OBJ_execpi:
                        case OBJ_execi:
                        case OBJ_execibar:
                        case OBJ_execigraph:
-                               free(objs[i].data.execi.cmd);
-                               free(objs[i].data.execi.buffer);
+                               free(obj->data.execi.cmd);
+                               free(obj->data.execi.buffer);
                                break;
                        case OBJ_texeci:
-                               free(objs[i].data.texeci.cmd);
-                               free(objs[i].data.texeci.buffer);
+                               free(obj->data.texeci.cmd);
+                               free(obj->data.texeci.buffer);
                                break;
                        case OBJ_nameserver:
                                free_dns_data();
@@ -2186,8 +2247,9 @@ static void free_text_objects(unsigned int count, struct text_object *objs)
                                break;
 #ifdef HDDTEMP
                        case OBJ_hddtemp:
-                               free(objs[i].data.hddtemp.dev);
-                               free(objs[i].data.hddtemp.addr);
+                               free(obj->data.hddtemp.dev);
+                               free(obj->data.hddtemp.addr);
+                               free(obj->data.hddtemp.temp);
                                break;
 #endif
                        case OBJ_entropy_avail:
@@ -2215,11 +2277,15 @@ static void free_text_objects(unsigned int count, struct text_object *objs)
 #ifdef SMAPI
                        case OBJ_smapi:
                        case OBJ_smapi_bat_perc:
-                               free(objs[i].data.s);
+                               free(obj->data.s);
                                break;
                        case OBJ_if_smapi_bat_installed:
-                               free(objs[i].data.ifblock.s);
-                               free(objs[i].data.ifblock.str);
+                               free(obj->data.ifblock.s);
+                               free(obj->data.ifblock.str);
+                               break;
+#endif
+#ifdef NVIDIA
+                       case OBJ_nvidia:
                                break;
 #endif
 #ifdef MPD
@@ -2242,14 +2308,14 @@ static void free_text_objects(unsigned int count, struct text_object *objs)
                        case OBJ_mpd_file:
                        case OBJ_mpd_percent:
                        case OBJ_mpd_smart:
-                               free_mpd_vars(&info);
+                               free_mpd_vars(&info.mpd);
                                break;
 #endif
                }
        }
-       free(objs);
-       /* text_objects = NULL;
-          text_object_count = 0; */
+       free(text_object_list->text_objects);
+       text_object_list->text_objects = NULL;
+       text_object_list->text_object_count = 0;
 }
 
 void scan_mixer_bar(const char *arg, int *a, int *w, int *h)
@@ -2266,6 +2332,10 @@ void scan_mixer_bar(const char *arg, int *a, int *w, int *h)
        }
 }
 
+/* strip a leading /dev/ if any */
+#define DEV_NAME(x) x != NULL && strlen(x) > 5 && strncmp(x, "/dev/", 5) == 0 \
+       ? x + 5 : x
+
 /* construct_text_object() creates a new text_object */
 static struct text_object *construct_text_object(const char *s,
                const char *arg, unsigned int object_count,
@@ -2407,7 +2477,7 @@ static struct text_object *construct_text_object(const char *s,
                } else {
                        strcpy(bat, "BAT0");
                }
-               obj->data.s = strdup(bat);
+               obj->data.s = strndup(bat, text_buffer_size);
        END OBJ(battery_time, 0)
                char bat[64];
 
@@ -2416,7 +2486,7 @@ static struct text_object *construct_text_object(const char *s,
                } else {
                        strcpy(bat, "BAT0");
                }
-               obj->data.s = strdup(bat);
+               obj->data.s = strndup(bat, text_buffer_size);
        END OBJ(battery_percent, 0)
                char bat[64];
 
@@ -2425,7 +2495,7 @@ static struct text_object *construct_text_object(const char *s,
                } else {
                        strcpy(bat, "BAT0");
                }
-               obj->data.s = strdup(bat);
+               obj->data.s = strndup(bat, text_buffer_size);
        END OBJ(battery_bar, 0)
                char bat[64];
                obj->b = 6;
@@ -2435,13 +2505,13 @@ static struct text_object *construct_text_object(const char *s,
                } else {
                        strcpy(bat, "BAT0");
                }
-               obj->data.s = strdup(bat);
+               obj->data.s = strndup(bat, text_buffer_size);
 #endif /* !__OpenBSD__ */
 
 #if defined(__linux__)
        END OBJ(disk_protect, 0)
                if (arg)
-                       obj->data.s = strdup(arg);
+                       obj->data.s = strndup(DEV_NAME(arg), text_buffer_size);
                else
                        CRIT_ERR("disk_protect needs an argument");
        END OBJ(i8k_version, INFO_I8K)
@@ -2476,7 +2546,7 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("if_up needs an argument");
                        obj->data.ifblock.s = 0;
                } else
-                       obj->data.ifblock.s = strdup(arg);
+                       obj->data.ifblock.s = strndup(arg, text_buffer_size);
                blockstart[blockdepth] = object_count;
                obj->data.ifblock.pos = object_count + 2;
                blockdepth++;
@@ -2492,7 +2562,7 @@ static struct text_object *construct_text_object(const char *s,
                        CRIT_ERR("get_ioscheduler needs an argument (e.g. hda)");
                        obj->data.s = 0;
                } else
-                       obj->data.s = strdup(arg);
+                       obj->data.s = strndup(DEV_NAME(arg), text_buffer_size);
        END OBJ(laptop_mode, 0)
        END OBJ(pb_battery, 0)
                if (arg && strcmp(arg, "status") == 0) {
@@ -2582,26 +2652,38 @@ static struct text_object *construct_text_object(const char *s,
                        }
                        free(buf);
                }
+       END OBJ(loadgraph, INFO_LOADAVG)
+               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+                               &obj->e);
+               if (buf) {
+                       int a = 1, r = 3;
+                       if (arg) {
+                               r = sscanf(arg, "%d", &a);
+                       }
+                       obj->data.loadavg[0] = (r >= 1) ? (unsigned char) a : 0;
+                       free(buf);
+               }
+#if defined(__linux__)
        END OBJ(diskio, INFO_DISKIO)
                if (arg) {
-                       obj->data.diskio = prepare_diskio_stat(arg);
+                       obj->data.diskio = prepare_diskio_stat(DEV_NAME(arg));
                } else {
                        obj->data.diskio = NULL;
                }
        END OBJ(diskio_read, INFO_DISKIO)
                if (arg) {
-                       obj->data.diskio = prepare_diskio_stat(arg);
+                       obj->data.diskio = prepare_diskio_stat(DEV_NAME(arg));
                } else {
                        obj->data.diskio = NULL;
                }
        END OBJ(diskio_write, INFO_DISKIO)
                if (arg) {
-                       obj->data.diskio = prepare_diskio_stat(arg);
+                       obj->data.diskio = prepare_diskio_stat(DEV_NAME(arg));
                } else {
                        obj->data.diskio = NULL;
                }
        END OBJ(diskiograph, INFO_DISKIO)
-               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+               char *buf = scan_graph(DEV_NAME(arg), &obj->a, &obj->b, &obj->c, &obj->d,
                        &obj->e);
 
                if (buf) {
@@ -2611,7 +2693,7 @@ static struct text_object *construct_text_object(const char *s,
                        obj->data.diskio = NULL;
                }
        END OBJ(diskiograph_read, INFO_DISKIO)
-               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+               char *buf = scan_graph(DEV_NAME(arg), &obj->a, &obj->b, &obj->c, &obj->d,
                        &obj->e);
 
                if (buf) {
@@ -2621,7 +2703,7 @@ static struct text_object *construct_text_object(const char *s,
                        obj->data.diskio = NULL;
                }
        END OBJ(diskiograph_write, INFO_DISKIO)
-               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+               char *buf = scan_graph(DEV_NAME(arg), &obj->a, &obj->b, &obj->c, &obj->d,
                        &obj->e);
 
                if (buf) {
@@ -2630,6 +2712,7 @@ static struct text_object *construct_text_object(const char *s,
                } else {
                        obj->data.diskio = NULL;
                }
+#endif
        END OBJ(color, 0)
 #ifdef X11
                obj->data.l = arg ? get_x11_color(arg) : default_fg_color;
@@ -2697,18 +2780,18 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("$endif: no matching $if_*");
                }
        END OBJ(image, 0)
-               obj->data.s = strdup(arg ? arg : "");
+               obj->data.s = strndup(arg ? arg : "", text_buffer_size);
 #ifdef HAVE_POPEN
        END OBJ(exec, 0)
-               obj->data.s = strdup(arg ? arg : "");
+               obj->data.s = strndup(arg ? arg : "", text_buffer_size);
        END OBJ(execp, 0)
-               obj->data.s = strdup(arg ? arg : "");
+               obj->data.s = strndup(arg ? arg : "", text_buffer_size);
        END OBJ(execbar, 0)
-               obj->data.s = strdup(arg ? arg : "");
+               obj->data.s = strndup(arg ? arg : "", text_buffer_size);
        END OBJ(execgraph, 0)
-               obj->data.s = strdup(arg ? arg : "");
+               obj->data.s = strndup(arg ? arg : "", text_buffer_size);
        END OBJ(execibar, 0)
-               unsigned int n;
+               int n;
 
                if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
                        char buf[256];
@@ -2716,12 +2799,12 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("${execibar <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
-                       obj->data.s = strdup(buf);
+                       obj->data.s = strndup(buf, text_buffer_size);
                } else {
-                       obj->data.execi.cmd = strdup(arg + n);
+                       obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
                }
        END OBJ(execigraph, 0)
-               unsigned int n;
+               int n;
 
                if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
                        char buf[256];
@@ -2729,12 +2812,12 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("${execigraph <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
-                       obj->data.s = strdup(buf);
+                       obj->data.s = strndup(buf, text_buffer_size);
                } else {
-                       obj->data.execi.cmd = strdup(arg + n);
+                       obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
                }
        END OBJ(execi, 0)
-               unsigned int n;
+               int n;
 
                if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
                        char buf[256];
@@ -2742,13 +2825,13 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("${execi <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
-                       obj->data.s = strdup(buf);
+                       obj->data.s = strndup(buf, text_buffer_size);
                } else {
-                       obj->data.execi.cmd = strdup(arg + n);
+                       obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
                        obj->data.execi.buffer = malloc(text_buffer_size);
                }
        END OBJ(execpi, 0)
-               unsigned int n;
+               int n;
 
                if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
                        char buf[256];
@@ -2756,13 +2839,13 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("${execi <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
-                       obj->data.s = strdup(buf);
+                       obj->data.s = strndup(buf, text_buffer_size);
                } else {
-                       obj->data.execi.cmd = strdup(arg + n);
+                       obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
                        obj->data.execi.buffer = malloc(text_buffer_size);
                }
        END OBJ(texeci, 0)
-               unsigned int n;
+               int n;
 
                if (!arg || sscanf(arg, "%f %n", &obj->data.texeci.interval, &n) <= 0) {
                        char buf[256];
@@ -2770,9 +2853,9 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("${texeci <interval> command}");
                        obj->type = OBJ_text;
                        snprintf(buf, 256, "${%s}", s);
-                       obj->data.s = strdup(buf);
+                       obj->data.s = strndup(buf, text_buffer_size);
                } else {
-                       obj->data.texeci.cmd = strdup(arg + n);
+                       obj->data.texeci.cmd = strndup(arg + n, text_buffer_size);
                        obj->data.texeci.buffer = malloc(text_buffer_size);
                }
                obj->data.texeci.p_timed_thread = NULL;
@@ -2792,9 +2875,9 @@ static struct text_object *construct_text_object(const char *s,
 
                        pclose(fp);
 
-                       obj->data.s = strdup(buf);
+                       obj->data.s = strndup(buf, text_buffer_size);
                } else {
-                       obj->data.s = strdup("");
+                       obj->data.s = strndup("", text_buffer_size);
                }
 #endif
        END OBJ(fs_bar, INFO_FS)
@@ -2867,7 +2950,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg) {
                        ERR("goto needs arguments");
                        obj->type = OBJ_text;
-                       obj->data.s = strdup("${goto}");
+                       obj->data.s = strndup("${goto}", text_buffer_size);
                        return NULL;
                }
 
@@ -2895,7 +2978,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg) {
                        ERR("i2c needs arguments");
                        obj->type = OBJ_text;
-                       // obj->data.s = strdup("${i2c}");
+                       // obj->data.s = strndup("${i2c}", text_buffer_size);
                        return NULL;
                }
 
@@ -2966,7 +3049,7 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg) {
                        ERR("top needs arguments");
                        obj->type = OBJ_text;
-                       // obj->data.s = strdup("${top}");
+                       // obj->data.s = strndup("${top}", text_buffer_size);
                        return NULL;
                }
                if (sscanf(arg, "%63s %i", buf, &n) == 2) {
@@ -2980,6 +3063,10 @@ static struct text_object *construct_text_object(const char *s,
                                obj->data.top.type = TOP_MEM;
                        } else if (strcmp(buf, "time") == 0) {
                                obj->data.top.type = TOP_TIME;
+                       } else if (strcmp(buf, "mem_res") == 0) {
+                               obj->data.top.type = TOP_MEM_RES;
+                       } else if (strcmp(buf, "mem_vsize") == 0) {
+                               obj->data.top.type = TOP_MEM_VSIZE;
                        } else {
                                ERR("invalid arg for top");
                                return NULL;
@@ -2995,14 +3082,14 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("invalid args given for top");
                        return NULL;
                }
-       END OBJ(top_mem, INFO_TOP)
-               char buf[64];
+               END OBJ(top_mem, INFO_TOP)
+                       char buf[64];
                int n;
 
                if (!arg) {
                        ERR("top_mem needs arguments");
                        obj->type = OBJ_text;
-                       obj->data.s = strdup("${top_mem}");
+                       obj->data.s = strndup("${top_mem}", text_buffer_size);
                        return NULL;
                }
                if (sscanf(arg, "%63s %i", buf, &n) == 2) {
@@ -3016,12 +3103,16 @@ static struct text_object *construct_text_object(const char *s,
                                obj->data.top.type = TOP_MEM;
                        } else if (strcmp(buf, "time") == 0) {
                                obj->data.top.type = TOP_TIME;
+                       } else if (strcmp(buf, "mem_res") == 0) {
+                               obj->data.top.type = TOP_MEM_RES;
+                       } else if (strcmp(buf, "mem_vsize") == 0) {
+                               obj->data.top.type = TOP_MEM_VSIZE;
                        } else {
                                ERR("invalid arg for top");
                                return NULL;
                        }
                        if (n < 1 || n > 10) {
-                               CRIT_ERR("invalid arg for top");
+                                       CRIT_ERR("invalid arg for top");
                                return NULL;
                        } else {
                                obj->data.top.num = n - 1;
@@ -3031,35 +3122,35 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("invalid args given for top");
                        return NULL;
                }
-       END OBJ(addr, INFO_NET)
-               if (arg) {
-                       obj->data.net = get_net_stat(arg);
-               } else {
-                       CRIT_ERR("addr needs argument");
-               }
+               END OBJ(addr, INFO_NET)
+                       if (arg) {
+                               obj->data.net = get_net_stat(arg);
+                       } else {
+                               CRIT_ERR("addr needs argument");
+                       }
 #if defined(__linux__)
-     END OBJ(addrs, INFO_NET)
-        if (arg) {
-            obj->data.net = get_net_stat(arg);
-        } else {
-             CRIT_ERR("addrs needs argument");
-        }
+               END OBJ(addrs, INFO_NET)
+                       if (arg) {
+                               obj->data.net = get_net_stat(arg);
+                       } else {
+                               CRIT_ERR("addrs needs argument");
+                       }
 #endif /* __linux__ */
-       END OBJ(tail, 0)
-               char buf[64];
+               END OBJ(tail, 0)
+                       char buf[64];
                int n1, n2;
                struct stat st;
 
                if (!arg) {
                        ERR("tail needs arguments");
                        obj->type = OBJ_text;
-                       obj->data.s = strdup("${tail}");
+                       obj->data.s = strndup("${tail}", text_buffer_size);
                        return NULL;
                }
                if (sscanf(arg, "%63s %i %i", buf, &n1, &n2) == 2) {
-                       if (n1 < 1 || n1 > 30) {
+                       if (n1 < 1 || n1 > MAX_TAIL_LINES) {
                                CRIT_ERR("invalid arg for tail, number of lines must be "
-                                       "between 1 and 30");
+                                               "between 1 and %i", MAX_TAIL_LINES);
                                return NULL;
                        } else {
                                FILE *fp = NULL;
@@ -3098,9 +3189,9 @@ static struct text_object *construct_text_object(const char *s,
                                }
                        }
                } else if (sscanf(arg, "%63s %i %i", buf, &n1, &n2) == 3) {
-                       if (n1 < 1 || n1 > 30) {
+                       if (n1 < 1 || n1 > MAX_TAIL_LINES) {
                                CRIT_ERR("invalid arg for tail, number of lines must be "
-                                       "between 1 and 30");
+                                       "between 1 and %i", MAX_TAIL_LINES);
                                return NULL;
                        } else if (n2 < 1 || n2 < update_interval) {
                                CRIT_ERR("invalid arg for tail, interval must be greater than "
@@ -3155,13 +3246,13 @@ static struct text_object *construct_text_object(const char *s,
                if (!arg) {
                        ERR("head needs arguments");
                        obj->type = OBJ_text;
-                       obj->data.s = strdup("${head}");
+                       obj->data.s = strndup("${head}", text_buffer_size);
                        return NULL;
                }
                if (sscanf(arg, "%63s %i %i", buf, &n1, &n2) == 2) {
-                       if (n1 < 1 || n1 > 30) {
+                       if (n1 < 1 || n1 > MAX_TAIL_LINES) {
                                CRIT_ERR("invalid arg for head, number of lines must be "
-                                       "between 1 and 30");
+                                       "between 1 and %i", MAX_TAIL_LINES);
                                return NULL;
                        } else {
                                FILE *fp;
@@ -3180,9 +3271,9 @@ static struct text_object *construct_text_object(const char *s,
                                }
                        }
                } else if (sscanf(arg, "%63s %i %i", buf, &n1, &n2) == 3) {
-                       if (n1 < 1 || n1 > 30) {
+                       if (n1 < 1 || n1 > MAX_TAIL_LINES) {
                                CRIT_ERR("invalid arg for head, number of lines must be "
-                                       "between 1 and 30");
+                                       "between 1 and %i", MAX_TAIL_LINES);
                                return NULL;
                        } else if (n2 < 1 || n2 < update_interval) {
                                CRIT_ERR("invalid arg for head, interval must be greater than "
@@ -3236,7 +3327,7 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("if_empty needs an argument");
                        obj->data.ifblock.s = 0;
                } else {
-                       obj->data.ifblock.s = strdup(arg);
+                       obj->data.ifblock.s = strndup(arg, text_buffer_size);
                }
                blockstart[blockdepth] = object_count;
                obj->data.ifblock.pos = object_count + 2;
@@ -3254,11 +3345,11 @@ static struct text_object *construct_text_object(const char *s,
                        int r = sscanf(arg, "%255s %255[^\n]", buf1, buf2);
 
                        if (r == 1) {
-                               obj->data.ifblock.s = strdup(buf1);
+                               obj->data.ifblock.s = strndup(buf1, text_buffer_size);
                                obj->data.ifblock.str = NULL;
                        } else {
-                               obj->data.ifblock.s = strdup(buf1);
-                               obj->data.ifblock.str = strdup(buf2);
+                               obj->data.ifblock.s = strndup(buf1, text_buffer_size);
+                               obj->data.ifblock.str = strndup(buf2, text_buffer_size);
                        }
                }
                blockstart[blockdepth] = object_count;
@@ -3272,7 +3363,7 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("if_mounted needs an argument");
                        obj->data.ifblock.s = 0;
                } else {
-                       obj->data.ifblock.s = strdup(arg);
+                       obj->data.ifblock.s = strndup(arg, text_buffer_size);
                }
                blockstart[blockdepth] = object_count;
                obj->data.ifblock.pos = object_count + 2;
@@ -3285,7 +3376,7 @@ static struct text_object *construct_text_object(const char *s,
                        char buf[256];
 
                        snprintf(buf, 256, "pidof %s >/dev/null", arg);
-                       obj->data.ifblock.s = strdup(buf);
+                       obj->data.ifblock.s = strndup(buf, text_buffer_size);
                } else {
                        ERR("if_running needs an argument");
                        obj->data.ifblock.s = 0;
@@ -3301,7 +3392,12 @@ static struct text_object *construct_text_object(const char *s,
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, MAIL_FILE, sizeof(box));
+                       /* Kapil: Changed from MAIL_FILE to
+                          current_mail_spool since the latter
+                          is a copy of the former if undefined
+                          but the latter should take precedence
+                          if defined */
+                       strncpy(box, current_mail_spool, sizeof(box));
                } else {
                        if (sscanf(arg, "%s %f", box, &n1) != 2) {
                                n1 = 9.5;
@@ -3310,7 +3406,7 @@ static struct text_object *construct_text_object(const char *s,
                }
 
                variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strdup(dst);
+               obj->data.local_mail.box = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(mboxscan, 0)
                obj->data.mboxscan.args = (char *) malloc(text_buffer_size);
@@ -3351,7 +3447,12 @@ static struct text_object *construct_text_object(const char *s,
 
                if (!arg) {
                        n1 = 9.5;
-                       strncpy(box, MAIL_FILE, sizeof(box));
+                       /* Kapil: Changed from MAIL_FILE to
+                          current_mail_spool since the latter
+                          is a copy of the former if undefined
+                          but the latter should take precedence
+                          if defined */
+                       strncpy(box, current_mail_spool, sizeof(box));
                } else {
                        if (sscanf(arg, "%s %f", box, &n1) != 2) {
                                n1 = 9.5;
@@ -3360,7 +3461,7 @@ static struct text_object *construct_text_object(const char *s,
                }
 
                variable_substitute(box, dst, sizeof(dst));
-               obj->data.local_mail.box = strdup(dst);
+               obj->data.local_mail.box = strndup(dst, text_buffer_size);
                obj->data.local_mail.interval = n1;
        END OBJ(nodename, 0)
        END OBJ(processes, INFO_PROCS)
@@ -3405,9 +3506,9 @@ static struct text_object *construct_text_object(const char *s,
                        &obj->data.sysfs.arg, obj->data.sysfs.devtype);
 #endif
        END OBJ(time, 0)
-               obj->data.s = strdup(arg ? arg : "%F %T");
+               obj->data.s = strndup(arg ? arg : "%F %T", text_buffer_size);
        END OBJ(utime, 0)
-               obj->data.s = strdup(arg ? arg : "%F %T");
+               obj->data.s = strndup(arg ? arg : "%F %T", text_buffer_size);
        END OBJ(tztime, 0)
                char buf1[256], buf2[256], *fmt, *tz;
 
@@ -3423,8 +3524,8 @@ static struct text_object *construct_text_object(const char *s,
                        }
                }
 
-               obj->data.tztime.fmt = strdup(fmt ? fmt : "%F %T");
-               obj->data.tztime.tz = tz ? strdup(tz) : NULL;
+               obj->data.tztime.fmt = strndup(fmt ? fmt : "%F %T", text_buffer_size);
+               obj->data.tztime.tz = tz ? strndup(tz, text_buffer_size) : NULL;
 #ifdef HAVE_ICONV
        END OBJ(iconv_start, 0)
                if (iconv_converting) {
@@ -3500,9 +3601,11 @@ static struct text_object *construct_text_object(const char *s,
        END OBJ(user_times, INFO_USERS)
        END OBJ(user_terms, INFO_USERS)
        END OBJ(user_number, INFO_USERS)
+#if defined(__linux__)
        END OBJ(gw_iface, INFO_GW)
        END OBJ(gw_ip, INFO_GW)
        END OBJ(if_gw, INFO_GW)
+#endif /* !__linux__ */
 #ifndef __OpenBSD__
        END OBJ(adt746xcpu, 0)
        END OBJ(adt746xfan, 0)
@@ -3548,7 +3651,7 @@ static struct text_object *construct_text_object(const char *s,
 #ifdef SMAPI
        END OBJ(smapi, 0)
                if (arg)
-                       obj->data.s = strdup(arg);
+                       obj->data.s = strndup(arg, text_buffer_size);
                else
                        ERR("smapi needs an argument");
        END OBJ(if_smapi_bat_installed, 0)
@@ -3559,13 +3662,13 @@ static struct text_object *construct_text_object(const char *s,
                        ERR("if_smapi_bat_installed needs an argument");
                        obj->data.ifblock.s = 0;
                } else
-                       obj->data.ifblock.s = strdup(arg);
+                       obj->data.ifblock.s = strndup(arg, text_buffer_size);
                blockstart[blockdepth] = object_count;
                obj->data.ifblock.pos = object_count + 2;
                blockdepth++;
        END OBJ(smapi_bat_perc, 0)
                if (arg)
-                       obj->data.s = strdup(arg);
+                       obj->data.s = strndup(arg, text_buffer_size);
                else
                        ERR("smapi_bat_perc needs an argument");
        END OBJ(smapi_bat_bar, 0)
@@ -3693,10 +3796,11 @@ static struct text_object *construct_text_object(const char *s,
 #ifdef HDDTEMP
        END OBJ(hddtemp, 0)
                if (!arg || scan_hddtemp(arg, &obj->data.hddtemp.dev,
-                               &obj->data.hddtemp.addr, &obj->data.hddtemp.port)) {
+                               &obj->data.hddtemp.addr, &obj->data.hddtemp.port, &obj->data.hddtemp.temp)) {
                        ERR("hddtemp needs arguments");
                        obj->type = OBJ_text;
-                       obj->data.s = strdup("${hddtemp}");
+                       obj->data.s = strndup("${hddtemp}", text_buffer_size);
+                       obj->data.hddtemp.update_time = 0;
                        return NULL;
                }
 #endif
@@ -3790,13 +3894,35 @@ static struct text_object *construct_text_object(const char *s,
        END OBJ(entropy_poolsize, INFO_ENTROPY)
        END OBJ(entropy_bar, INFO_ENTROPY)
                scan_bar(arg, &obj->a, &obj->b);
+#ifdef NVIDIA
+       END OBJ(nvidia, 0)
+               if (!arg){
+                       CRIT_ERR("nvidia needs one argument "
+                                "[temp,threshold,gpufreq,memfreq,imagequality]");
+               } else {
+                       if (strcmp(arg, "temp") == 0)
+                               obj->data.nvidia.type = NV_TEMP;
+                       else if (strcmp(arg, "threshold") == 0)
+                               obj->data.nvidia.type = NV_TEMP_THRESHOLD;
+                       else if (strcmp(arg, "gpufreq") == 0)
+                               obj->data.nvidia.type = NV_GPU_FREQ;
+                       else if (strcmp(arg, "memfreq") == 0)
+                               obj->data.nvidia.type = NV_MEM_FREQ;
+                       else if (strcmp(arg, "imagequality") == 0)
+                               obj->data.nvidia.type = NV_IMAGE_QUALITY;
+                       else
+                               CRIT_ERR("you have to give one of these arguments "
+                                        "[temp,threshold,gpufreq,memfreq,imagequality");
+                       strncpy((char*)&obj->data.nvidia.arg, arg, 20);
+               }
+#endif /* NVIDIA */
        END {
                char buf[256];
 
                ERR("unknown variable %s", s);
                obj->type = OBJ_text;
                snprintf(buf, 256, "${%s}", s);
-               obj->data.s = strdup(buf);
+               obj->data.s = strndup(buf, text_buffer_size);
        }
 #undef OBJ
 
@@ -3814,28 +3940,32 @@ static struct text_object *create_plain_text(const char *s)
        obj = new_text_object_internal();
 
        obj->type = OBJ_text;
-       obj->data.s = strdup(s);
+       obj->data.s = strndup(s, text_buffer_size);
        return obj;
 }
 
-static struct text_object_list *extract_variable_text_internal(const char *p)
+static struct text_object_list *extract_variable_text_internal(const char *const_p)
 {
        struct text_object_list *retval;
        struct text_object *obj;
-       const char *s = p;
+       char *p, *s, *orig_p;
+       long line;
+
+       p = strndup(const_p, max_user_text);
+       s = orig_p = p;
 
        retval = malloc(sizeof(struct text_object_list));
        memset(retval, 0, sizeof(struct text_object_list));
        retval->text_object_count = 0;
 
-       long line = text_lines;
+       line = global_text_lines;
 
        while (*p) {
                if (*p == '\n') {
                        line++;
                }
                if (*p == '$') {
-                       *(char *) p = '\0';
+                       *p = '\0';
                        obj = create_plain_text(s);
                        if (obj != NULL) {
                                // allocate memory for the object
@@ -3847,7 +3977,7 @@ static struct text_object_list *extract_variable_text_internal(const char *p)
                                        sizeof(struct text_object));
                                free(obj);
                        }
-                       *(char *) p = '$';
+                       *p = '$';
                        p++;
                        s = p;
 
@@ -3896,7 +4026,7 @@ static struct text_object_list *extract_variable_text_internal(const char *p)
 
                                /* if variable wasn't found in environment, use some special */
                                if (!var) {
-                                       char *p;
+                                       char *tmp_p;
                                        char *arg = 0;
 
                                        /* split arg */
@@ -3913,10 +4043,10 @@ static struct text_object_list *extract_variable_text_internal(const char *p)
                                        }
 
                                        /* lowercase variable name */
-                                       p = buf;
-                                       while (*p) {
-                                               *p = tolower(*p);
-                                               p++;
+                                       tmp_p = buf;
+                                       while (*tmp_p) {
+                                               *tmp_p = tolower(*tmp_p);
+                                               tmp_p++;
                                        }
 
                                        // create new object
@@ -3966,14 +4096,14 @@ static struct text_object_list *extract_variable_text_internal(const char *p)
                ERR("one or more $endif's are missing");
        }
 
+       free(orig_p);
        return retval;
 }
 
 static void extract_variable_text(const char *p)
 {
-       struct text_object_list *list;
-
-       free_text_objects(text_object_count, text_objects);
+       free_text_objects(global_text_object_list);
+       free(global_text_object_list);
        if (tmpstring1) {
                free(tmpstring1);
                tmpstring1 = 0;
@@ -3986,23 +4116,16 @@ static void extract_variable_text(const char *p)
                free(text_buffer);
                text_buffer = 0;
        }
-       text_object_count = 0;
-       text_objects = NULL;
-
-       list = extract_variable_text_internal(p);
-       text_objects = list->text_objects;
-       text_object_count = list->text_object_count;
 
-       free(list);
+       global_text_object_list = extract_variable_text_internal(p);
 }
 
-struct text_object_list *parse_conky_vars(char *text, char *p, struct information *cur)
+struct text_object_list *parse_conky_vars(char *txt, char *p, struct information *cur)
 {
        struct text_object_list *object_list =
-               extract_variable_text_internal(text);
+               extract_variable_text_internal(txt);
 
-       generate_text_internal(p, max_user_text, object_list->text_objects,
-               object_list->text_object_count, cur);
+       generate_text_internal(p, max_user_text, object_list, cur);
        return object_list;
 }
 
@@ -4087,48 +4210,132 @@ static void tail_pipe(struct text_object *obj, char *dst, size_t dst_size)
        snprintf(dst, dst_size, "%s", obj->data.tail.buffer);
 }
 
-char *format_time(unsigned long time, const int width)
+static inline struct mail_s *ensure_mail_thread(struct text_object *obj,
+               void *thread(void *), const char *text)
+{
+       if (obj->global_mode && info.mail) {
+               // this means we use info
+               if (!info.mail->p_timed_thread) {
+                       info.mail->p_timed_thread =
+                               timed_thread_create(thread,
+                               (void *) info.mail, info.mail->interval * 1000000);
+                       if (!info.mail->p_timed_thread) {
+                               ERR("Error creating %s timed thread", text);
+                       }
+                       timed_thread_register(info.mail->p_timed_thread,
+                               &info.mail->p_timed_thread);
+                       if (timed_thread_run(info.mail->p_timed_thread)) {
+                               ERR("Error running %s timed thread", text);
+                       }
+               }
+               return info.mail;
+       } else if (obj->data.mail) {
+               // this means we use obj
+               if (!obj->data.mail->p_timed_thread) {
+                       obj->data.mail->p_timed_thread =
+                               timed_thread_create(thread,
+                               (void *) obj->data.mail,
+                               obj->data.mail->interval * 1000000);
+                       if (!obj->data.mail->p_timed_thread) {
+                               ERR("Error creating %s timed thread", text);
+                       }
+                       timed_thread_register(obj->data.mail->p_timed_thread,
+                               &obj->data.mail->p_timed_thread);
+                       if (timed_thread_run(obj->data.mail->p_timed_thread)) {
+                               ERR("Error running %s timed thread", text);
+                       }
+               }
+               return obj->data.mail;
+       } else if (!obj->a) {
+               // something is wrong, warn once then stop
+               ERR("Theres a problem with your %s_unseen settings.  "
+                       "Check that the global %s settings are defined "
+                       "properly (line %li).", global_text, global_text, obj->line);
+               obj->a++;
+       }
+       return NULL;
+}
+
+char *format_time(unsigned long timeval, const int width)
 {
        char buf[10];
        unsigned long nt;       // narrow time, for speed on 32-bit
        unsigned cc;            // centiseconds
        unsigned nn;            // multi-purpose whatever
 
-       nt = time;
+       nt = timeval;
        cc = nt % 100;          // centiseconds past second
        nt /= 100;                      // total seconds
        nn = nt % 60;           // seconds past the minute
        nt /= 60;                       // total minutes
        if (width >= snprintf(buf, sizeof buf, "%lu:%02u.%02u",
                                nt, nn, cc)) {
-               return strdup(buf);
+               return strndup(buf, text_buffer_size);
        }
        if (width >= snprintf(buf, sizeof buf, "%lu:%02u", nt, nn)) {
-               return strdup(buf);
+               return strndup(buf, text_buffer_size);
        }
        nn = nt % 60;           // minutes past the hour
        nt /= 60;                       // total hours
        if (width >= snprintf(buf, sizeof buf, "%lu,%02u", nt, nn)) {
-               return strdup(buf);
+               return strndup(buf, text_buffer_size);
        }
        nn = nt;                        // now also hours
        if (width >= snprintf(buf, sizeof buf, "%uh", nn)) {
-               return strdup(buf);
+               return strndup(buf, text_buffer_size);
        }
        nn /= 24;                       // now days
        if (width >= snprintf(buf, sizeof buf, "%ud", nn)) {
-               return strdup(buf);
+               return strndup(buf, text_buffer_size);
        }
        nn /= 7;                        // now weeks
        if (width >= snprintf(buf, sizeof buf, "%uw", nn)) {
-               return strdup(buf);
+               return strndup(buf, text_buffer_size);
        }
        // well shoot, this outta' fit...
-       return strdup("<inf>");
+       return strndup("<inf>", text_buffer_size);
+}
+
+//remove backspaced chars, example: "dog^H^H^Hcat" becomes "cat"
+//string has to end with \0 and it's length should fit in a int
+#define BACKSPACE 8
+void remove_deleted_chars(char *string){
+       int i = 0;
+       while(string[i] != 0){
+               if(string[i] == BACKSPACE){
+                       if(i != 0){
+                               strcpy( &(string[i-1]), &(string[i+1]) );
+                               i--;
+                       }else strcpy( &(string[i]), &(string[i+1]) ); //necessary for ^H's at the start of a string
+               }else i++;
+       }
+}
+
+static inline void format_media_player_time(char *buf, const int size,
+               int seconds)
+{
+       int days, hours, minutes;
+
+       days = seconds / (24 * 60 * 60);
+       seconds %= (24 * 60 * 60);
+       hours = seconds / (60 * 60);
+       seconds %= (60 * 60);
+       minutes = seconds / 60;
+       seconds %= 60;
+
+       if (days > 0) {
+               snprintf(buf, size, "%i days %i:%02i:%02i", days,
+                       hours, minutes, seconds);
+       } else if (hours > 0) {
+               snprintf(buf, size, "%i:%02i:%02i", hours, minutes,
+                       seconds);
+       } else {
+               snprintf(buf, size, "%i:%02i", minutes, seconds);
+       }
 }
 
 static void generate_text_internal(char *p, int p_max_size,
-               struct text_object *objs, unsigned int object_count,
+               struct text_object_list *text_object_list,
                struct information *cur)
 {
        unsigned int i;
@@ -4139,8 +4346,9 @@ static void generate_text_internal(char *p, int p_max_size,
        iconv_converting = 0;
 #endif
 
-       for (i = 0; i < object_count; i++) {
-               struct text_object *obj = &objs[i];
+       p[0] = 0;
+       for (i = 0; i < text_object_list->text_object_count; i++) {
+               struct text_object *obj = &(text_object_list->text_objects[i]);
 
                if (p_max_size < 1) {
                        break;
@@ -4269,8 +4477,8 @@ static void generate_text_internal(char *p, int p_max_size,
                                get_battery_stuff(p, p_max_size, obj->data.s, BATTERY_TIME);
                        }
                        OBJ(battery_percent) {
-                               spaced_print(p, p_max_size, "%*d", pad_percents,
-                                               "battery_percent", get_battery_perct(obj->data.s));
+                               spaced_print(p, p_max_size, "%*d", 4, "battery_percent",
+                                               pad_percents, get_battery_perct(obj->data.s));
                        }
                        OBJ(battery_bar) {
                                new_bar(p, obj->a, obj->b, get_battery_perct_bar(obj->data.s));
@@ -4287,7 +4495,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                if (obj->data.cpu_index > info.cpu_count) {
                                        printf("obj->data.cpu_index %i info.cpu_count %i",
                                                obj->data.cpu_index, info.cpu_count);
-                                       CRIT_ERR("attempting to use more CPUs then you have!");
+                                       CRIT_ERR("attempting to use more CPUs than you have!");
                                }
                                spaced_print(p, p_max_size, "%*d", 4, "cpu", pad_percents,
                                        round_to_int(cur->cpu_usage[obj->data.cpu_index] * 100.0));
@@ -4301,6 +4509,10 @@ static void generate_text_internal(char *p, int p_max_size,
                                        round_to_int(cur->cpu_usage[obj->data.cpu_index] * 100),
                                        100, 1);
                        }
+                       OBJ(loadgraph) {
+                               new_graph(p, obj->a, obj->b, obj->c, obj->d, cur->loadavg[0],
+                                       obj->e, 1);
+                       }
                        OBJ(color) {
                                new_fg(p, obj->data.l);
                        }
@@ -4501,7 +4713,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                                (obj->data.diskio->current / update_interval) * 1024LL,
                                                p, p_max_size, "diskio");
                                } else {
-                                       human_readable(diskio_value * 1024LL, p, p_max_size,
+                                       human_readable(info.diskio_value * 1024LL, p, p_max_size,
                                                "diskio");
                                }
                        }
@@ -4510,7 +4722,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        human_readable((obj->data.diskio->current_write / update_interval) * 1024LL, p, p_max_size,
                                                "diskio_write");
                                } else {
-                                       human_readable(diskio_write_value * 1024LL, p, p_max_size,
+                                       human_readable(info.diskio_write_value * 1024LL, p, p_max_size,
                                                "diskio_write");
                                }
                        }
@@ -4519,7 +4731,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        human_readable((obj->data.diskio->current_read / update_interval) * 1024LL, p, p_max_size,
                                                "diskio_read");
                                } else {
-                                       human_readable(diskio_read_value * 1024LL, p, p_max_size,
+                                       human_readable(info.diskio_read_value * 1024LL, p, p_max_size,
                                                "diskio_read");
                                }
                        }
@@ -4528,7 +4740,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        new_graph(p, obj->a, obj->b, obj->c, obj->d,
                                                obj->data.diskio->current, obj->e, 1);
                                } else {
-                                       new_graph(p, obj->a, obj->b, obj->c, obj->d, diskio_value,
+                                       new_graph(p, obj->a, obj->b, obj->c, obj->d, info.diskio_value,
                                                obj->e, 1);
                                }
                        }
@@ -4538,7 +4750,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                                obj->data.diskio->current_read, obj->e, 1);
                                } else {
                                        new_graph(p, obj->a, obj->b, obj->c, obj->d,
-                                               diskio_read_value, obj->e, 1);
+                                               info.diskio_read_value, obj->e, 1);
                                }
                        }
                        OBJ(diskiograph_write) {
@@ -4547,7 +4759,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                                obj->data.diskio->current_write, obj->e, 1);
                                } else {
                                        new_graph(p, obj->a, obj->b, obj->c, obj->d,
-                                               diskio_write_value, obj->e, 1);
+                                               info.diskio_write_value, obj->e, 1);
                                }
                        }
                        OBJ(downspeed) {
@@ -4574,21 +4786,27 @@ static void generate_text_internal(char *p, int p_max_size,
                        }
 #ifdef HAVE_POPEN
                        OBJ(addr) {
-                               snprintf(p, p_max_size, "%u.%u.%u.%u",
-                                       obj->data.net->addr.sa_data[2] & 255,
-                                       obj->data.net->addr.sa_data[3] & 255,
-                                       obj->data.net->addr.sa_data[4] & 255,
-                                       obj->data.net->addr.sa_data[5] & 255);
+                               if ((obj->data.net->addr.sa_data[2] & 255) == 0
+                                               && (obj->data.net->addr.sa_data[3] & 255) == 0
+                                               && (obj->data.net->addr.sa_data[4] & 255) == 0
+                                               && (obj->data.net->addr.sa_data[5] & 255) == 0) {
+                                       snprintf(p, p_max_size, "No Address");
+                               } else {
+                                       snprintf(p, p_max_size, "%u.%u.%u.%u",
+                                               obj->data.net->addr.sa_data[2] & 255,
+                                               obj->data.net->addr.sa_data[3] & 255,
+                                               obj->data.net->addr.sa_data[4] & 255,
+                                               obj->data.net->addr.sa_data[5] & 255);
+                               }
                        }
-
 #if defined(__linux__)
-           OBJ(addrs) {
-                                    if(NULL != obj->data.net->addrs && strlen(obj->data.net->addrs) > 2)
-                                    {
-                                        obj->data.net->addrs[strlen(obj->data.net->addrs) - 2] = 0; /* remove ", " from end of string */
-                                        strcpy(p, obj->data.net->addrs);
-                                    }
-                                    else
+                       OBJ(addrs) {
+                               if(NULL != obj->data.net->addrs && strlen(obj->data.net->addrs) > 2)
+                               {
+                                       obj->data.net->addrs[strlen(obj->data.net->addrs) - 2] = 0; /* remove ", " from end of string */
+                                       strcpy(p, obj->data.net->addrs);
+                               }
+                               else
                                         strcpy(p, "0.0.0.0");
            }
 #endif /* __linux__ */
@@ -4634,36 +4852,41 @@ static void generate_text_internal(char *p, int p_max_size,
                                pclose(fp);
 
                                p[length] = '\0';
+                               remove_deleted_chars(p);
                                if (length > 0 && p[length - 1] == '\n') {
                                        p[length - 1] = '\0';
                                }
                        }
                        OBJ(execp) {
-                               FILE *fp = popen(obj->data.s, "r");
-                               fread(p, 1, p_max_size, fp);
+                               FILE *fp;
+                               struct information *tmp_info;
+                               struct text_object_list *text_objects;
+                               int length;
 
+                               fp = popen(obj->data.s, "r");
+                               fread(p, 1, p_max_size, fp);
                                pclose(fp);
 
-                               struct information *my_info =
-                                       malloc(sizeof(struct information));
-                               memcpy(my_info, cur, sizeof(struct information));
-                               struct text_object_list *text_objects = parse_conky_vars(p, p, my_info);
+                               tmp_info = malloc(sizeof(struct information));
+                               memcpy(tmp_info, cur, sizeof(struct information));
+                               text_objects = parse_conky_vars(p, p, tmp_info);
 
-                               int length = strlen(p);
+                               length = strlen(p);
 
                                p[length] = '\0';
                                if (length > 0 && p[length - 1] == '\n') {
                                        p[length - 1] = '\0';
                                }
 
-                               free_text_objects(text_objects->text_object_count, text_objects->text_objects);
+                               free_text_objects(text_objects);
                                free(text_objects);
-                               free(my_info);
+                               free(tmp_info);
                        }
                        OBJ(execbar) {
                                char *p2 = p;
                                FILE *fp = popen(obj->data.s, "r");
                                int n2 = fread(p, 1, p_max_size, fp);
+                               double barnum;
 
                                pclose(fp);
                                p[n2] = '\0';
@@ -4677,7 +4900,6 @@ static void generate_text_internal(char *p, int p_max_size,
                                        }
                                        p2++;
                                }
-                               double barnum;
 
                                if (sscanf(p, "%lf", &barnum) == 0) {
                                        ERR("reading execbar value failed (perhaps it's not the "
@@ -4695,6 +4917,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                char *p2 = p;
                                FILE *fp = popen(obj->data.s, "r");
                                int n2 = fread(p, 1, p_max_size, fp);
+                               double barnum;
 
                                pclose(fp);
                                p[n2] = '\0';
@@ -4707,7 +4930,6 @@ static void generate_text_internal(char *p, int p_max_size,
                                        }
                                        p2++;
                                }
-                               double barnum;
 
                                if (sscanf(p, "%lf", &barnum) == 0) {
                                        ERR("reading execgraph value failed (perhaps it's not the "
@@ -4717,8 +4939,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        ERR("your execgraph value is not between 0 and 100, "
                                                "therefore it will be ignored");
                                } else {
-                                       new_graph(p, 0, 25, obj->c, obj->d, (int) (barnum),
-                                               obj->e, 1);
+                                       new_graph(p, 0, 25, obj->c, obj->d, (int) (barnum), 100, 1);
                                }
                        }
                        OBJ(execibar) {
@@ -4729,6 +4950,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        char *p2 = p;
                                        FILE *fp = popen(obj->data.execi.cmd, "r");
                                        int n2 = fread(p, 1, p_max_size, fp);
+                                       float barnum;
 
                                        pclose(fp);
                                        p[n2] = '\0';
@@ -4742,7 +4964,6 @@ static void generate_text_internal(char *p, int p_max_size,
                                                }
                                                p2++;
                                        }
-                                       float barnum;
 
                                        if (sscanf(p, "%f", &barnum) == 0) {
                                                ERR("reading execibar value failed (perhaps it's not "
@@ -4766,6 +4987,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        char *p2 = p;
                                        FILE *fp = popen(obj->data.execi.cmd, "r");
                                        int n2 = fread(p, 1, p_max_size, fp);
+                                       float barnum;
 
                                        pclose(fp);
                                        p[n2] = '\0';
@@ -4779,7 +5001,6 @@ static void generate_text_internal(char *p, int p_max_size,
                                                }
                                                p2++;
                                        }
-                                       float barnum;
 
                                        if (sscanf(p, "%f", &barnum) == 0) {
                                                ERR("reading execigraph value failed (perhaps it's not "
@@ -4818,15 +5039,15 @@ static void generate_text_internal(char *p, int p_max_size,
                                // parse_conky_vars(output, p, cur);
                        }
                        OBJ(execpi) {
-                               struct information *my_info =
-                                       malloc(sizeof(struct information));
-                               memcpy(my_info, cur, sizeof(struct information));
                                struct text_object_list *text_objects = 0;
+                               struct information *tmp_info =
+                                       malloc(sizeof(struct information));
+                               memcpy(tmp_info, cur, sizeof(struct information));
 
                                if (current_update_time - obj->data.execi.last_update
                                                < obj->data.execi.interval
                                                || obj->data.execi.interval == 0) {
-                                       text_objects = parse_conky_vars(obj->data.execi.buffer, p, my_info);
+                                       text_objects = parse_conky_vars(obj->data.execi.buffer, p, tmp_info);
                                } else {
                                        char *output = obj->data.execi.buffer;
                                        FILE *fp = popen(obj->data.execi.cmd, "r");
@@ -4838,18 +5059,18 @@ static void generate_text_internal(char *p, int p_max_size,
                                        if (length > 0 && output[length - 1] == '\n') {
                                                output[length - 1] = '\0';
                                        }
-                                       
-                                       text_objects = parse_conky_vars(obj->data.execi.buffer, p, my_info);
+
+                                       text_objects = parse_conky_vars(obj->data.execi.buffer, p, tmp_info);
                                        obj->data.execi.last_update = current_update_time;
                                }
-                               free_text_objects(text_objects->text_object_count, text_objects->text_objects);
+                               free_text_objects(text_objects);
                                free(text_objects);
-                               free(my_info);
+                               free(tmp_info);
                        }
                        OBJ(texeci) {
                                if (!obj->data.texeci.p_timed_thread) {
                                        obj->data.texeci.p_timed_thread =
-                                               timed_thread_create((void *) threaded_exec,
+                                               timed_thread_create(&threaded_exec,
                                                (void *) obj, obj->data.texeci.interval * 1000000);
                                        if (!obj->data.texeci.p_timed_thread) {
                                                ERR("Error creating texeci timed thread");
@@ -4866,189 +5087,40 @@ static void generate_text_internal(char *p, int p_max_size,
                        }
 #endif /* HAVE_POPEN */
                        OBJ(imap_unseen) {
-                               if (obj->global_mode && info.mail) {
-                                       // this means we use info
-                                       if (!info.mail->p_timed_thread) {
-                                               info.mail->p_timed_thread =
-                                                       timed_thread_create((void *) imap_thread,
-                                                       (void *) info.mail, info.mail->interval * 1000000);
-                                               if (!info.mail->p_timed_thread) {
-                                                       ERR("Error creating imap timed thread");
-                                               }
-                                               timed_thread_register(info.mail->p_timed_thread,
-                                                       &info.mail->p_timed_thread);
-                                               if (timed_thread_run(info.mail->p_timed_thread)) {
-                                                       ERR("Error running imap timed thread");
-                                               }
-                                       }
-                                       timed_thread_lock(info.mail->p_timed_thread);
-                                       snprintf(p, p_max_size, "%lu", info.mail->unseen);
-                                       timed_thread_unlock(info.mail->p_timed_thread);
-                               } else if (obj->data.mail) {
-                                       // this means we use obj
-                                       if (!obj->data.mail->p_timed_thread) {
-                                               obj->data.mail->p_timed_thread =
-                                                       timed_thread_create((void *) imap_thread,
-                                                       (void *) obj->data.mail,
-                                                       obj->data.mail->interval * 1000000);
-                                               if (!obj->data.mail->p_timed_thread) {
-                                                       ERR("Error creating imap timed thread");
-                                               }
-                                               timed_thread_register(obj->data.mail->p_timed_thread,
-                                                       &obj->data.mail->p_timed_thread);
-                                               if (timed_thread_run(obj->data.mail->p_timed_thread)) {
-                                                       ERR("Error running imap timed thread");
-                                               }
-                                       }
-                                       timed_thread_lock(obj->data.mail->p_timed_thread);
-                                       snprintf(p, p_max_size, "%lu", obj->data.mail->unseen);
-                                       timed_thread_unlock(obj->data.mail->p_timed_thread);
-                               } else if (!obj->a) {
-                                       // something is wrong, warn once then stop
-                                       ERR("Theres a problem with your imap_unseen settings.  "
-                                               "Check that the global IMAP settings are defined "
-                                               "properly (line %li).", obj->line);
-                                       obj->a++;
+                               struct mail_s *mail = ensure_mail_thread(obj, imap_thread, "imap");
+
+                               if (mail && mail->p_timed_thread) {
+                                       timed_thread_lock(mail->p_timed_thread);
+                                       snprintf(p, p_max_size, "%lu", mail->unseen);
+                                       timed_thread_unlock(mail->p_timed_thread);
                                }
                        }
                        OBJ(imap_messages) {
-                               if (obj->global_mode && info.mail) {
-                                       // this means we use info
-                                       if (!info.mail->p_timed_thread) {
-                                               info.mail->p_timed_thread =
-                                                       timed_thread_create((void *) imap_thread,
-                                                       (void *) info.mail, info.mail->interval * 1000000);
-                                               if (!info.mail->p_timed_thread) {
-                                                       ERR("Error creating imap timed thread");
-                                               }
-                                               timed_thread_register(info.mail->p_timed_thread,
-                                                       &info.mail->p_timed_thread);
-                                               if (timed_thread_run(info.mail->p_timed_thread)) {
-                                                       ERR("Error running imap timed thread");
-                                               }
-                                       }
-                                       timed_thread_lock(info.mail->p_timed_thread);
-                                       snprintf(p, p_max_size, "%lu", info.mail->messages);
-                                       timed_thread_unlock(info.mail->p_timed_thread);
-                               } else if (obj->data.mail) {
-                                       // this means we use obj
-                                       if (!obj->data.mail->p_timed_thread) {
-                                               obj->data.mail->p_timed_thread =
-                                                       timed_thread_create((void *) imap_thread,
-                                                       (void *) obj->data.mail,
-                                                       obj->data.mail->interval * 1000000);
-                                               if (!obj->data.mail->p_timed_thread) {
-                                                       ERR("Error creating imap timed thread");
-                                               }
-                                               timed_thread_register(obj->data.mail->p_timed_thread,
-                                                       &obj->data.mail->p_timed_thread);
-                                               if (timed_thread_run(obj->data.mail->p_timed_thread)) {
-                                                       ERR("Error runninging imap timed thread");
-                                               }
-                                       }
-                                       timed_thread_lock(obj->data.mail->p_timed_thread);
-                                       snprintf(p, p_max_size, "%lu", obj->data.mail->messages);
-                                       timed_thread_lock(obj->data.mail->p_timed_thread);
-                               } else if (!obj->a) {
-                                       // something is wrong, warn once then stop
-                                       ERR("Theres a problem with your imap_messages settings.  "
-                                               "Check that the global IMAP settings are defined "
-                                               "properly (line %li).", obj->line);
-                                       obj->a++;
+                               struct mail_s *mail = ensure_mail_thread(obj, imap_thread, "imap");
+
+                               if (mail && mail->p_timed_thread) {
+                                       timed_thread_lock(mail->p_timed_thread);
+                                       snprintf(p, p_max_size, "%lu", mail->messages);
+                                       timed_thread_unlock(mail->p_timed_thread);
                                }
                        }
                        OBJ(pop3_unseen) {
-                               if (obj->global_mode && info.mail) {
-                                       // this means we use info
-                                       if (!info.mail->p_timed_thread) {
-                                               info.mail->p_timed_thread =
-                                                       timed_thread_create((void *) pop3_thread,
-                                                       (void *) info.mail, info.mail->interval * 1000000);
-                                               if (!info.mail->p_timed_thread) {
-                                                       ERR("Error creating pop3 timed thread");
-                                               }
-                                               timed_thread_register(info.mail->p_timed_thread,
-                                                       &info.mail->p_timed_thread);
-                                               if (timed_thread_run(info.mail->p_timed_thread)) {
-                                                       ERR("Error running pop3 timed thread");
-                                               }
-                                       }
-                                       timed_thread_lock(info.mail->p_timed_thread);
-                                       snprintf(p, p_max_size, "%lu", info.mail->unseen);
-                                       timed_thread_unlock(info.mail->p_timed_thread);
-                               } else if (obj->data.mail) {
-                                       // this means we use obj
-                                       if (!obj->data.mail->p_timed_thread) {
-                                               obj->data.mail->p_timed_thread =
-                                                       timed_thread_create((void *) pop3_thread,
-                                                       (void *) obj->data.mail,
-                                                       obj->data.mail->interval * 1000000);
-                                               if (!obj->data.mail->p_timed_thread) {
-                                                       ERR("Error creating pop3 timed thread");
-                                               }
-                                               timed_thread_register(obj->data.mail->p_timed_thread,
-                                                       &obj->data.mail->p_timed_thread);
-                                               if (timed_thread_run(obj->data.mail->p_timed_thread)) {
-                                                       ERR("Error running pop3 timed thread");
-                                               }
-                                       }
-                                       timed_thread_lock(obj->data.mail->p_timed_thread);
-                                       snprintf(p, p_max_size, "%lu", obj->data.mail->unseen);
-                                       timed_thread_unlock(obj->data.mail->p_timed_thread);
-                               } else if (!obj->a) {
-                                       // something is wrong, warn once then stop
-                                       ERR("Theres a problem with your pop3_unseen settings.  "
-                                               "Check that the global POP3 settings are defined "
-                                               "properly (line %li).", obj->line);
-                                       obj->a++;
+                               struct mail_s *mail = ensure_mail_thread(obj, pop3_thread, "pop3");
+
+                               if (mail && mail->p_timed_thread) {
+                                       timed_thread_lock(mail->p_timed_thread);
+                                       snprintf(p, p_max_size, "%lu", mail->unseen);
+                                       timed_thread_unlock(mail->p_timed_thread);
                                }
                        }
                        OBJ(pop3_used) {
-                               if (obj->global_mode && info.mail) {
-                                       // this means we use info
-                                       if (!info.mail->p_timed_thread) {
-                                               info.mail->p_timed_thread =
-                                                       timed_thread_create((void *) pop3_thread,
-                                                       (void *) info.mail, info.mail->interval * 1000000);
-                                               if (!info.mail->p_timed_thread) {
-                                                       ERR("Error creating pop3 timed thread");
-                                               }
-                                               timed_thread_register(info.mail->p_timed_thread,
-                                                       &info.mail->p_timed_thread);
-                                               if (timed_thread_run(info.mail->p_timed_thread)) {
-                                                       ERR("Error running pop3 timed thread");
-                                               }
-                                       }
-                                       timed_thread_lock(info.mail->p_timed_thread);
-                                       snprintf(p, p_max_size, "%.1f",
-                                               info.mail->used / 1024.0 / 1024.0);
-                                       timed_thread_unlock(info.mail->p_timed_thread);
-                               } else if (obj->data.mail) {
-                                       // this means we use obj
-                                       if (!obj->data.mail->p_timed_thread) {
-                                               obj->data.mail->p_timed_thread =
-                                                       timed_thread_create((void *) pop3_thread,
-                                                       (void *) obj->data.mail,
-                                                       obj->data.mail->interval * 1000000);
-                                               if (!obj->data.mail->p_timed_thread) {
-                                                       ERR("Error creating pop3 timed thread");
-                                               }
-                                               timed_thread_register(obj->data.mail->p_timed_thread,
-                                                       &obj->data.mail->p_timed_thread);
-                                               if (timed_thread_run(obj->data.mail->p_timed_thread)) {
-                                                       ERR("Error running pop3 timed thread");
-                                               }
-                                       }
-                                       timed_thread_lock(obj->data.mail->p_timed_thread);
+                               struct mail_s *mail = ensure_mail_thread(obj, pop3_thread, "pop3");
+
+                               if (mail && mail->p_timed_thread) {
+                                       timed_thread_lock(mail->p_timed_thread);
                                        snprintf(p, p_max_size, "%.1f",
-                                               obj->data.mail->used / 1024.0 / 1024.0);
-                                       timed_thread_unlock(obj->data.mail->p_timed_thread);
-                               } else if (!obj->a) {
-                                       // something is wrong, warn once then stop
-                                       ERR("Theres a problem with your pop3_used settings.  "
-                                               "Check that the global POP3 settings are defined "
-                                               "properly (line %li).", obj->line);
-                                       obj->a++;
+                                               mail->used / 1024.0 / 1024.0);
+                                       timed_thread_unlock(mail->p_timed_thread);
                                }
                        }
                        OBJ(fs_bar) {
@@ -5070,9 +5142,9 @@ static void generate_text_internal(char *p, int p_max_size,
                        OBJ(fs_free_perc) {
                                if (obj->data.fs != NULL) {
                                        if (obj->data.fs->size) {
-                                               spaced_print(p, p_max_size, "%*d", pad_percents,
-                                                       "fs_free_perc", (int) ((obj->data.fs->avail * 100) /
-                                                       obj->data.fs->size));
+                                               spaced_print(p, p_max_size, "%*d", 4, "fs_free_perc",
+                                                               pad_percents, (int) ((obj->data.fs->avail * 100) /
+                                                                       obj->data.fs->size));
                                        } else {
                                                snprintf(p, p_max_size, "0");
                                        }
@@ -5108,9 +5180,9 @@ static void generate_text_internal(char *p, int p_max_size,
                        OBJ(fs_used_perc) {
                                if (obj->data.fs != NULL) {
                                        if (obj->data.fs->size) {
-                                               spaced_print(p, 4, "%*d", pad_percents,
-                                                       "fs_used_perc", 100 - ((int) ((obj->data.fs->avail * 100) /
-                                                       obj->data.fs->size)));
+                                               spaced_print(p, 4, "%*d", 4, "fs_used_perc",
+                                                               pad_percents, 100 - ((int) ((obj->data.fs->avail * 100) /
+                                                                               obj->data.fs->size)));
                                        } else {
                                                snprintf(p, p_max_size, "0");
                                        }
@@ -5185,9 +5257,9 @@ static void generate_text_internal(char *p, int p_max_size,
                                        } else if (!strcmp(obj->data.rss.action, "item_titles")) {
                                                if (data->item_count > 0) {
                                                        int itmp;
+                                                       int show;
 
                                                        p[0] = 0;
-                                                       int show;
 
                                                        if (obj->data.rss.act_par > data->item_count) {
                                                                show = data->item_count;
@@ -5218,17 +5290,22 @@ static void generate_text_internal(char *p, int p_max_size,
 #endif
 #ifdef HDDTEMP
                        OBJ(hddtemp) {
-                               char *temp;
-                               char unit;
-
-                               temp = get_hddtemp_info(obj->data.hddtemp.dev,
-                                       obj->data.hddtemp.addr, obj->data.hddtemp.port, &unit);
-                               if (!temp) {
+                               if (obj->data.hddtemp.update_time < current_update_time - 30) {
+                                       char *str = get_hddtemp_info(obj->data.hddtemp.dev,
+                                                       obj->data.hddtemp.addr, obj->data.hddtemp.port, &obj->data.hddtemp.unit);
+                                       if (str) {
+                                               strncpy(obj->data.hddtemp.temp, str, text_buffer_size);
+                                       } else {
+                                               obj->data.hddtemp.temp[0] = 0;
+                                       }
+                                       obj->data.hddtemp.update_time = current_update_time;
+                               }
+                               if (!obj->data.hddtemp.temp) {
                                        snprintf(p, p_max_size, "N/A");
-                               } else if (unit == '*') {
-                                       snprintf(p, p_max_size, "%s", temp);
+                               } else if (obj->data.hddtemp.unit == '*') {
+                                       snprintf(p, p_max_size, "%s", obj->data.hddtemp.temp);
                                } else {
-                                       snprintf(p, p_max_size, "%s°%c", temp, unit);
+                                       snprintf(p, p_max_size, "%s%c", obj->data.hddtemp.temp, obj->data.hddtemp.unit);
                                }
                        }
 #endif
@@ -5283,11 +5360,12 @@ static void generate_text_internal(char *p, int p_max_size,
                                new_alignc(p, obj->data.i);
                        }
                        OBJ(if_empty) {
-                               struct information *my_info =
+                               struct text_object_list *text_objects;
+                               struct information *tmp_info =
                                        malloc(sizeof(struct information));
+                               memcpy(tmp_info, cur, sizeof(struct information));
+                               text_objects = parse_conky_vars(obj->data.ifblock.s, p, tmp_info);
 
-                               memcpy(my_info, cur, sizeof(struct information));
-                               struct text_object_list *text_objects = parse_conky_vars(obj->data.ifblock.s, p, my_info);
                                if (strlen(p) != 0) {
                                        i = obj->data.ifblock.pos;
                                        if_jumped = 1;
@@ -5295,9 +5373,9 @@ static void generate_text_internal(char *p, int p_max_size,
                                        if_jumped = 0;
                                }
                                p[0] = '\0';
-                               free_text_objects(text_objects->text_object_count, text_objects->text_objects);
+                               free_text_objects(text_objects);
                                free(text_objects);
-                               free(my_info);
+                               free(tmp_info);
                        }
                        OBJ(if_existing) {
                                struct stat tmp;
@@ -5337,9 +5415,11 @@ static void generate_text_internal(char *p, int p_max_size,
                                        if_jumped = 0;
                                }
                        }
+#if defined(__linux__)
                        OBJ(ioscheduler) {
                                snprintf(p, p_max_size, "%s", get_ioscheduler(obj->data.s));
                        }
+#endif
                        OBJ(kernel) {
                                snprintf(p, p_max_size, "%s", cur->uname_s.release);
                        }
@@ -5356,7 +5436,7 @@ static void generate_text_internal(char *p, int p_max_size,
                        }
                        OBJ(memperc) {
                                if (cur->memmax) {
-                                       spaced_print(p, p_max_size, "%*Lu", 4, "memperc",
+                                       spaced_print(p, p_max_size, "%*llu", 4, "memperc",
                                                pad_percents, cur->mem * 100 / cur->memmax);
                                }
                        }
@@ -5439,7 +5519,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                if (cur->swapmax == 0) {
                                        strncpy(p, "No swap", p_max_size);
                                } else {
-                                       spaced_print(p, p_max_size, "%*Lu", 4, "swapperc",
+                                       spaced_print(p, p_max_size, "%*llu", 4, "swapperc",
                                                pad_percents, cur->swap * 100 / cur->swapmax);
                                }
                        }
@@ -5465,14 +5545,16 @@ static void generate_text_internal(char *p, int p_max_size,
                        }
                        OBJ(tztime) {
                                char *oldTZ = NULL;
+                               time_t t;
+                               struct tm *tm;
 
                                if (obj->data.tztime.tz) {
                                        oldTZ = getenv("TZ");
                                        setenv("TZ", obj->data.tztime.tz, 1);
                                        tzset();
                                }
-                               time_t t = time(NULL);
-                               struct tm *tm = localtime(&t);
+                               t = time(NULL);
+                               tm = localtime(&t);
 
                                setlocale(LC_TIME, "");
                                strftime(p, p_max_size, obj->data.tztime.fmt, tm);
@@ -5585,62 +5667,14 @@ static void generate_text_internal(char *p, int p_max_size,
                                snprintf(p, p_max_size, "%s", cur->mpd.status);
                        }
                        OBJ(mpd_elapsed) {
-                               int days = 0, hours = 0, minutes = 0, seconds = 0;
-                               int tmp = cur->mpd.elapsed;
-
-                               while (tmp >= 86400) {
-                                       tmp -= 86400;
-                                       days++;
-                               }
-                               while (tmp >= 3600) {
-                                       tmp -= 3600;
-                                       hours++;
-                               }
-                               while (tmp >= 60) {
-                                       tmp -= 60;
-                                       minutes++;
-                               }
-                               seconds = tmp;
-                               if (days > 0) {
-                                       snprintf(p, p_max_size, "%i days %i:%02i:%02i", days,
-                                               hours, minutes, seconds);
-                               } else if (hours > 0) {
-                                       snprintf(p, p_max_size, "%i:%02i:%02i", hours, minutes,
-                                               seconds);
-                               } else {
-                                       snprintf(p, p_max_size, "%i:%02i", minutes, seconds);
-                               }
+                               format_media_player_time(p, p_max_size, cur->mpd.elapsed);
                        }
                        OBJ(mpd_length) {
-                               int days = 0, hours = 0, minutes = 0, seconds = 0;
-                               int tmp = cur->mpd.length;
-
-                               while (tmp >= 86400) {
-                                       tmp -= 86400;
-                                       days++;
-                               }
-                               while (tmp >= 3600) {
-                                       tmp -= 3600;
-                                       hours++;
-                               }
-                               while (tmp >= 60) {
-                                       tmp -= 60;
-                                       minutes++;
-                               }
-                               seconds = tmp;
-                               if (days > 0) {
-                                       snprintf(p, p_max_size, "%i days %i:%02i:%02i", days,
-                                               hours, minutes, seconds);
-                               } else if (hours > 0) {
-                                       snprintf(p, p_max_size, "%i:%02i:%02i", hours, minutes,
-                                               seconds);
-                               } else {
-                                       snprintf(p, p_max_size, "%i:%02i", minutes, seconds);
-                               }
+                               format_media_player_time(p, p_max_size, cur->mpd.length);
                        }
                        OBJ(mpd_percent) {
-                               spaced_print(p, p_max_size, "%*d", pad_percents,
-                                               "mpd_percent", (int) (cur->mpd.progress * 100));
+                               spaced_print(p, p_max_size, "%*d", 4, "mpd_percent",
+                                               pad_percents, (int) (cur->mpd.progress * 100));
                        }
                        OBJ(mpd_bar) {
                                new_bar(p, obj->data.pair.a, obj->data.pair.b,
@@ -5817,7 +5851,7 @@ static void generate_text_internal(char *p, int p_max_size,
 #endif
                        OBJ(top) {
                                if (obj->data.top.num >= 0 && obj->data.top.num < 10) {
-                                       char *time;
+                                       char *timeval;
 
                                        switch (obj->data.top.type) {
                                                case TOP_NAME:
@@ -5837,10 +5871,18 @@ static void generate_text_internal(char *p, int p_max_size,
                                                                cur->cpu[obj->data.top.num]->totalmem);
                                                        break;
                                                case TOP_TIME:
-                                                       time = format_time(
+                                                       timeval = format_time(
                                                                cur->cpu[obj->data.top.num]->total_cpu_time, 9);
-                                                       snprintf(p, 10, "%9s", time);
-                                                       free(time);
+                                                       snprintf(p, 10, "%9s", timeval);
+                                                       free(timeval);
+                                                       break;
+                                               case TOP_MEM_RES:
+                                                       human_readable(cur->cpu[obj->data.top.num]->rss,
+                                                                       p, 255, "top_rss");
+                                                       break;
+                                               case TOP_MEM_VSIZE:
+                                                       human_readable(cur->cpu[obj->data.top.num]->vsize,
+                                                                       p, 255, "top_rss");
                                                        break;
                                                default:
                                                        ERR("Unhandled top data type: %d\n",
@@ -5852,7 +5894,7 @@ static void generate_text_internal(char *p, int p_max_size,
                        }
                        OBJ(top_mem) {
                                if (obj->data.top.num >= 0 && obj->data.top.num < 10) {
-                                       char *time;
+                                       char *timeval;
 
                                        switch (obj->data.top.type) {
                                                case TOP_NAME:
@@ -5872,11 +5914,19 @@ static void generate_text_internal(char *p, int p_max_size,
                                                                cur->memu[obj->data.top.num]->totalmem);
                                                        break;
                                                case TOP_TIME:
-                                                       time = format_time(
+                                                       timeval = format_time(
                                                                cur->memu[obj->data.top.num]->total_cpu_time,
                                                                9);
-                                                       snprintf(p, 10, "%9s", time);
-                                                       free(time);
+                                                       snprintf(p, 10, "%9s", timeval);
+                                                       free(timeval);
+                                                       break;
+                                               case TOP_MEM_RES:
+                                                       human_readable(cur->cpu[obj->data.top.num]->rss,
+                                                                       p, 255, "top_rss");
+                                                       break;
+                                               case TOP_MEM_VSIZE:
+                                                       human_readable(cur->cpu[obj->data.top.num]->vsize,
+                                                                       p, 255, "top_rss");
                                                        break;
                                                default:
                                                        ERR("Unhandled top data type: %d\n",
@@ -5891,11 +5941,12 @@ static void generate_text_internal(char *p, int p_max_size,
                                                < obj->data.tail.interval) {
                                        snprintf(p, p_max_size, "%s", obj->data.tail.buffer);
                                } else {
-                                       obj->data.tail.last_update = current_update_time;
                                        FILE *fp;
                                        long nl = 0, bsize;
                                        int iter;
 
+                                       obj->data.tail.last_update = current_update_time;
+
                                        if (obj->data.tail.fd != -1) {
                                                tail_pipe(obj, p, p_max_size);
                                                goto head;
@@ -5960,18 +6011,18 @@ static void generate_text_internal(char *p, int p_max_size,
                                }                       /* if cur_upd_time >= */
                                // parse_conky_vars(obj->data.tail.buffer, p, cur);
                        }
-
 head:
                        OBJ(head) {
                                if (current_update_time - obj->data.tail.last_update
                                                < obj->data.tail.interval) {
                                        snprintf(p, p_max_size, "%s", obj->data.tail.buffer);
                                } else {
-                                       obj->data.tail.last_update = current_update_time;
                                        FILE *fp;
                                        long nl = 0;
                                        int iter;
 
+                                       obj->data.tail.last_update = current_update_time;
+
                                        fp = fopen(obj->data.tail.logfile, "rt");
                                        if (fp == NULL) {
                                                /* Send one message, but do not consistently spam
@@ -6103,6 +6154,17 @@ head:
                                        new_bar(p, obj->a, obj->b, 0);
                        }
 #endif /* SMAPI */
+#ifdef NVIDIA
+                       OBJ(nvidia) {
+                               int hol = (strcmp((char*)&obj->data.nvidia.arg, "gpufreq")) ? 1 : 0;
+                               if(!(obj->data.nvidia.value = get_nvidia_value(obj->data.nvidia.type, display, hol)))
+                                       snprintf(p, p_max_size, "value unavailible");
+                               else
+                                       spaced_print(p, p_max_size, "%*d", 4, "nvidia",
+                                                            4, obj->data.nvidia.value);
+
+                       }
+#endif /* NVIDIA */
 
                        break;
                }
@@ -6145,7 +6207,7 @@ head:
 
 double current_update_time, last_update_time;
 
-static void generate_text()
+static void generate_text(void)
 {
        struct information *cur = &info;
        char *p;
@@ -6156,11 +6218,11 @@ static void generate_text()
 
        current_update_time = get_time();
 
-       update_stuff(cur);
+       update_stuff();
        /* fix diskio rates to b/s (use update_interval */
-       diskio_read_value = diskio_read_value / update_interval;
-       diskio_write_value = diskio_write_value / update_interval;
-       diskio_value = diskio_value / update_interval;
+       info.diskio_read_value /= update_interval;
+       info.diskio_write_value /= update_interval;
+       info.diskio_value /= update_interval;
 
        /* add things to the buffer */
 
@@ -6168,15 +6230,15 @@ static void generate_text()
 
        p = text_buffer;
 
-       generate_text_internal(p, max_user_text, text_objects, text_object_count, cur);
+       generate_text_internal(p, max_user_text, global_text_object_list, cur);
 
        if (stuff_in_upper_case) {
-               char *p;
+               char *tmp_p;
 
-               p = text_buffer;
-               while (*p) {
-                       *p = toupper(*p);
-                       p++;
+               tmp_p = text_buffer;
+               while (*tmp_p) {
+                       *tmp_p = toupper(*tmp_p);
+                       tmp_p++;
                }
        }
 
@@ -6186,7 +6248,7 @@ static void generate_text()
 }
 
 #ifdef X11
-static void set_font()
+static void set_font(void)
 {
 #ifdef XFT
        if (use_xft) {
@@ -6215,17 +6277,18 @@ static inline int get_string_width(const char *s)
 
 static inline int get_string_width_special(char *s)
 {
+#ifdef X11
+       char *p, *final;
+       int idx = 1;
+       int width = 0;
+       unsigned int i;
+
        if (!s) {
                return 0;
        }
-#ifdef X11
-       char *p, *final;
 
-       p = strdup(s);
+       p = strndup(s, text_buffer_size);
        final = p;
-       int index = 1;
-       int width = 0;
-       unsigned int i;
 
        while (*p) {
                if (*p == SPECIAL_CHAR) {
@@ -6234,11 +6297,11 @@ static inline int get_string_width_special(char *s)
                        for (i = 0; i < strlen(p); i++) {
                                *(p + i) = *(p + i + 1);
                        }
-                       if (specials[special_index + index].type == GRAPH
-                                       || specials[special_index + index].type == BAR) {
-                               width += specials[special_index + index].width;
+                       if (specials[special_index + idx].type == GRAPH
+                                       || specials[special_index + idx].type == BAR) {
+                               width += specials[special_index + idx].width;
                        }
-                       index++;
+                       idx++;
                } else {
                        p++;
                }
@@ -6249,7 +6312,7 @@ static inline int get_string_width_special(char *s)
        free(final);
        return width;
 #else
-       return strlen(s);
+       return (s) ? strlen(s) : 0;
 #endif /* X11 */
 }
 
@@ -6257,7 +6320,7 @@ static inline int get_string_width_special(char *s)
 static void text_size_updater(char *s);
 
 int last_font_height;
-static void update_text_area()
+static void update_text_area(void)
 {
        int x, y;
 
@@ -6361,7 +6424,10 @@ static void update_text_area()
 /* drawing stuff */
 
 static int cur_x, cur_y;       /* current x and y for drawing */
+#endif
+//draw_mode also without X11 because we only need to print to stdout with FG
 static int draw_mode;          /* FG, BG or OUTLINE */
+#ifdef X11
 static long current_color;
 
 #ifdef X11
@@ -6437,15 +6503,16 @@ static inline void set_foreground_color(long c)
 
 static void draw_string(const char *s)
 {
-       if (s[0] == '\0') {
-               return;
-       }
        int i, i2, pos, width_of_s;
        int max = 0;
        int added;
 
+       if (s[0] == '\0') {
+               return;
+       }
+
        width_of_s = get_string_width(s);
-       if (out_to_console) {
+       if (out_to_console && draw_mode == FG) {
                printf("%s\n", s);
                fflush(stdout); /* output immediately, don't buffer */
        }
@@ -6454,17 +6521,15 @@ static void draw_string(const char *s)
        strncpy(tmpstring1, s, text_buffer_size - 1);
        pos = 0;
        added = 0;
-       char space[2];
 
-       snprintf(space, 2, " ");
 #ifdef X11
-       max = ((text_width - width_of_s) / get_string_width(space));
+       max = ((text_width - width_of_s) / get_string_width(" "));
 #endif /* X11 */
        /* This code looks for tabs in the text and coverts them to spaces.
         * The trick is getting the correct number of spaces, and not going
         * over the window's size without forcing the window larger. */
-       for (i = 0; i < (int)text_buffer_size; i++) {
-               if (tmpstring1[i] == '\t') {    // 9 is ascii tab
+       for (i = 0; i < (int) text_buffer_size; i++) {
+               if (tmpstring1[i] == '\t') {
                        i2 = 0;
                        for (i2 = 0; i2 < (8 - (1 + pos) % 8) && added <= max; i2++) {
                                /* guard against overrun */
@@ -6473,11 +6538,9 @@ static void draw_string(const char *s)
                        }
                        pos += i2;
                } else {
-                       if (tmpstring1[i] != 9) {
-                               /* guard against overrun */
-                               tmpstring2[MIN(pos, (int)text_buffer_size - 1)] = tmpstring1[i];
-                               pos++;
-                       }
+                       /* guard against overrun */
+                       tmpstring2[MIN(pos, (int) text_buffer_size - 1)] = tmpstring1[i];
+                       pos++;
                }
        }
 #ifdef X11
@@ -6507,10 +6570,10 @@ static void draw_string(const char *s)
                c2.color.alpha = fonts[selected_font].font_alpha;
                if (utf8_mode) {
                        XftDrawStringUtf8(window.xftdraw, &c2, fonts[selected_font].xftfont,
-                               cur_x, cur_y, (XftChar8 *) s, strlen(s));
+                               cur_x, cur_y, (const XftChar8 *) s, strlen(s));
                } else {
                        XftDrawString8(window.xftdraw, &c2, fonts[selected_font].xftfont,
-                               cur_x, cur_y, (XftChar8 *) s, strlen(s));
+                               cur_x, cur_y, (const XftChar8 *) s, strlen(s));
                }
        } else
 #endif
@@ -6525,8 +6588,9 @@ static void draw_string(const char *s)
 
 long redmask, greenmask, bluemask;
 
-void set_up_gradient()
+void set_up_gradient(void)
 {
+       int i;
 #ifdef X11
        colour_depth = DisplayPlanes(display, screen);
 #else
@@ -6536,7 +6600,6 @@ void set_up_gradient()
                ERR("using non-standard colour depth, gradients may look like a "
                        "lolly-pop");
        }
-       int i;
 
        redmask = 0;
        greenmask = 0;
@@ -6617,14 +6680,17 @@ inline unsigned long do_gradient(unsigned long first_colour,
 inline unsigned long gradient_max(unsigned long first_colour,
                unsigned long last_colour)
 {
+       int red1, green1, blue1;                                // first colour
+       int red2, green2, blue2;                                // second colour
+       int red3 = 0, green3 = 0, blue3 = 0;                    // difference
+       long redshift, greenshift;
+       int max;
+
        if (colour_depth == 0) {
                set_up_gradient();
        }
-       int red1, green1, blue1;                                // first colour
-       int red2, green2, blue2;                                // second colour
-       long redshift = (2 * colour_depth / 3 + colour_depth % 3);
-       long greenshift = (colour_depth / 3);
-       int red3 = 0, green3 = 0, blue3 = 0;    // difference
+       redshift = (2 * colour_depth / 3 + colour_depth % 3);
+       greenshift = (colour_depth / 3);
 
        red1 = (first_colour & redmask) >> redshift;
        green1 = (first_colour & greenmask) >> greenshift;
@@ -6635,7 +6701,7 @@ inline unsigned long gradient_max(unsigned long first_colour,
        red3 = abs(red1 - red2);
        green3 = abs(green1 - green2);
        blue3 = abs(blue1 - blue2);
-       int max = red3;
+       max = red3;
 
        if (green3 > max) {
                max = green3;
@@ -6650,11 +6716,13 @@ static void draw_line(char *s)
 {
 #ifdef X11
        char *p;
+       int cur_y_add = 0;
+       short font_h;
+       char *tmp_str;
 
        cur_x = text_start_x;
        cur_y += font_ascent();
-       int cur_y_add = 0;
-       short font_h = font_height();
+       font_h = font_height();
 
        /* find specials and draw stuff */
        p = s;
@@ -6687,9 +6755,9 @@ static void draw_line(char *s)
                                case STIPPLED_HR:
                                {
                                        int h = specials[special_index].height;
-                                       int s = specials[special_index].arg;
+                                       int tmp_s = specials[special_index].arg;
                                        int mid = font_ascent() / 2;
-                                       char ss[2] = { s, s };
+                                       char ss[2] = { tmp_s, tmp_s };
 
                                        w = text_start_x + text_width - cur_x - 1;
                                        XSetLineAttributes(display, window.gc, h, LineOnOffDash,
@@ -6702,13 +6770,14 @@ static void draw_line(char *s)
 
                                case BAR:
                                {
+                                       int h, bar_usage, by;
                                        if (cur_x - text_start_x > maximum_width
                                                        && maximum_width > 0) {
                                                break;
                                        }
-                                       int h = specials[special_index].height;
-                                       int bar_usage = specials[special_index].arg;
-                                       int by = cur_y - (font_ascent() / 2) - 1;
+                                       h = specials[special_index].height;
+                                       bar_usage = specials[special_index].arg;
+                                       by = cur_y - (font_ascent() / 2) - 1;
 
                                        if (h < font_height()) {
                                                by -= h / 2 - 1;
@@ -6737,13 +6806,20 @@ static void draw_line(char *s)
 
                                case GRAPH:
                                {
+                                       int h, by, i, j = 0;
+                                       int gradient_size = 0;
+                                       float gradient_factor = 0;
+                                       float gradient_update = 0;
+                                       unsigned long last_colour = current_color;
+                                       unsigned long tmpcolour = current_color;
+                                       int show_scale_x = cur_x + font_ascent() / 2;
+                                       int show_scale_y = cur_y + font_height() / 2;
                                        if (cur_x - text_start_x > maximum_width
                                                        && maximum_width > 0) {
                                                break;
                                        }
-                                       int h = specials[special_index].height;
-                                       unsigned long last_colour = current_color;
-                                       int by = cur_y - (font_ascent() / 2) - 1;
+                                       h = specials[special_index].height;
+                                       by = cur_y - (font_ascent() / 2) - 1;
 
                                        if (h < font_height()) {
                                                by -= h / 2 - 1;
@@ -6763,12 +6839,6 @@ static void draw_line(char *s)
                                        }
                                        XSetLineAttributes(display, window.gc, 1, LineSolid,
                                                CapButt, JoinMiter);
-                                       int i;
-                                       int j = 0;
-                                       int gradient_size = 0;
-                                       float gradient_factor = 0;
-                                       float gradient_update = 0;
-                                       unsigned long tmpcolour = current_color;
 
                                        if (specials[special_index].last_colour != 0
                                                        || specials[special_index].first_colour != 0) {
@@ -6811,6 +6881,20 @@ static void draw_line(char *s)
                                        } else {
                                                set_foreground_color(default_fg_color);
                                        } */
+                                       if (show_graph_scale && (specials[special_index].show_scale == 1)) {
+                                               int tmp_x = cur_x;
+                                               int tmp_y = cur_y;
+                                               cur_x = show_scale_x;
+                                               cur_y = show_scale_y;
+                                               tmp_str = (char *)
+                                                       calloc(log10(floor(specials[special_index].graph_scale)) + 4,
+                                                                       sizeof(char));
+                                               sprintf(tmp_str, "%.1f", specials[special_index].graph_scale);
+                                               draw_string(tmp_str);
+                                               free(tmp_str);
+                                               cur_x = tmp_x;
+                                               cur_y = tmp_y;
+                                       }
                                        set_foreground_color(last_colour);
                                        break;
                                }
@@ -6934,7 +7018,7 @@ static void draw_line(char *s)
 #endif /* X11 */
 }
 
-static void draw_text()
+static void draw_text(void)
 {
 #ifdef X11
        cur_y = text_start_y;
@@ -6965,7 +7049,7 @@ static void draw_text()
        for_each_line(text_buffer, draw_line);
 }
 
-static void draw_stuff()
+static void draw_stuff(void)
 {
 #ifdef X11
        selected_font = 0;
@@ -6980,8 +7064,8 @@ static void draw_stuff()
        }
 
        if (draw_outline) {
-               selected_font = 0;
                int i, j;
+               selected_font = 0;
 
                for (i = -1; i < 2; i++) {
                        for (j = -1; j < 2; j++) {
@@ -7000,8 +7084,8 @@ static void draw_stuff()
        }
 
        set_foreground_color(default_fg_color);
-       draw_mode = FG;
 #endif /* X11 */
+       draw_mode = FG;
        draw_text();
 #ifdef X11
 #ifdef HAVE_XDBE
@@ -7038,7 +7122,7 @@ static void clear_text(int exposures)
 static int need_to_update;
 
 /* update_text() generates new text and clears old text area */
-static void update_text()
+static void update_text(void)
 {
        generate_text();
 #ifdef X11
@@ -7047,35 +7131,35 @@ static void update_text()
        need_to_update = 1;
 }
 
-static void main_loop()
+static void main_loop(void)
 {
 #ifdef SIGNAL_BLOCKING
        sigset_t newmask, oldmask;
-
-       sigemptyset(&newmask);
-       sigaddset(&newmask, SIGINT);
-       sigaddset(&newmask, SIGTERM);
-       sigaddset(&newmask, SIGUSR1);
 #endif
-
 #ifdef X11
        Region region = XCreateRegion();
 
 #ifdef HAVE_XDAMAGE
+       Damage damage;
+       XserverRegion region2, part;
        int event_base, error_base;
 
        if (!XDamageQueryExtension(display, &event_base, &error_base)) {
                ERR("Xdamage extension unavailable");
        }
-       Damage damage = XDamageCreate(display, window.window,
-               XDamageReportNonEmpty);
-       XserverRegion region2 = XFixesCreateRegionFromWindow(display,
-               window.window, 0);
-       XserverRegion part = XFixesCreateRegionFromWindow(display,
-               window.window, 0);
+       damage = XDamageCreate(display, window.window, XDamageReportNonEmpty);
+       region2 = XFixesCreateRegionFromWindow(display, window.window, 0);
+       part = XFixesCreateRegionFromWindow(display, window.window, 0);
 #endif /* HAVE_XDAMAGE */
 #endif /* X11 */
 
+#ifdef SIGNAL_BLOCKING
+       sigemptyset(&newmask);
+       sigaddset(&newmask, SIGINT);
+       sigaddset(&newmask, SIGTERM);
+       sigaddset(&newmask, SIGUSR1);
+#endif
+
        info.looped = 0;
        while (total_run_times == 0 || info.looped < total_run_times) {
                info.looped++;
@@ -7440,8 +7524,6 @@ void reload_config(void)
 
 #ifdef X11
        free_fonts();
-       load_fonts();
-       set_font();
 #endif /* X11 */
 
 #ifdef TCP_PORT_MONITOR
@@ -7459,6 +7541,8 @@ void reload_config(void)
                }
 
 #ifdef X11
+               load_fonts();
+               set_font();
                // clear the window first
                XClearWindow(display, RootWindow(display, screen));
 
@@ -7466,9 +7550,9 @@ void reload_config(void)
 #ifdef TCP_PORT_MONITOR
                info.p_tcp_port_monitor_collection = NULL;
 #endif
-               extract_variable_text(text);
-               free(text);
-               text = NULL;
+               extract_variable_text(global_text);
+               free(global_text);
+               global_text = NULL;
                if (tmpstring1) {
                        free(tmpstring1);
                }
@@ -7519,7 +7603,9 @@ void clean_up(void)
        free_fonts();
 #endif /* X11 */
 
-       free_text_objects(text_object_count, text_objects);
+       free_text_objects(global_text_object_list);
+       free(global_text_object_list);
+       global_text_object_list = NULL;
        if (tmpstring1) {
                free(tmpstring1);
                tmpstring1 = 0;
@@ -7532,12 +7618,10 @@ void clean_up(void)
                free(text_buffer);
                text_buffer = 0;
        }
-       text_object_count = 0;
-       text_objects = NULL;
 
-       if (text) {
-               free(text);
-               text = 0;
+       if (global_text) {
+               free(global_text);
+               global_text = 0;
        }
 
        free(current_config);
@@ -7568,6 +7652,7 @@ void clean_up(void)
 static int string_to_bool(const char *s)
 {
        if (!s) {
+               // Assumes an option without a true/false means true
                return 1;
        } else if (strcasecmp(s, "yes") == 0) {
                return 1;
@@ -7661,6 +7746,7 @@ static void set_default_configurations(void)
        out_to_console = 1;
 #endif
 #ifdef X11
+       show_graph_scale = 0;
        default_fg_color = WhitePixel(display, screen);
        default_bg_color = BlackPixel(display, screen);
        default_out_color = BlackPixel(display, screen);
@@ -7704,7 +7790,7 @@ static void set_default_configurations(void)
 
                variable_substitute(MAIL_FILE, buf, 256);
                if (buf[0] != '\0') {
-                       current_mail_spool = strdup(buf);
+                       current_mail_spool = strndup(buf, text_buffer_size);
                }
        }
 
@@ -7813,6 +7899,9 @@ static void load_config_file(const char *f)
                }
 #endif /* X11 */
 #ifdef X11
+               CONF("show_graph_scale") {
+                       show_graph_scale = string_to_bool(value);
+               }
                CONF("border_margin") {
                        if (value) {
                                border_margin = strtol(value, 0, 0);
@@ -8110,15 +8199,15 @@ static void load_config_file(const char *f)
 #endif /* X11 */
                CONF("mail_spool") {
                        if (value) {
-                               char buf[256];
+                               char buffer[256];
 
-                               variable_substitute(value, buf, 256);
+                               variable_substitute(value, buffer, 256);
 
-                               if (buf[0] != '\0') {
+                               if (buffer[0] != '\0') {
                                        if (current_mail_spool) {
                                                free(current_mail_spool);
                                        }
-                                       current_mail_spool = strdup(buf);
+                                       current_mail_spool = strndup(buffer, text_buffer_size);
                                }
                        } else {
                                CONF_ERR;
@@ -8238,6 +8327,8 @@ static void load_config_file(const char *f)
                                        window.type = TYPE_NORMAL;
                                } else if (strncmp(value, "desktop", 7) == 0) {
                                        window.type = TYPE_DESKTOP;
+                               } else if (strncmp(value, "dock", 7) == 0) {
+                                       window.type = TYPE_DOCK;
                                } else if (strncmp(value, "override", 8) == 0) {
                                        window.type = TYPE_OVERRIDE;
                                } else {
@@ -8311,29 +8402,32 @@ static void load_config_file(const char *f)
                        }
                }
                CONF("text") {
-                       if (text) {
-                               free(text);
-                               text = 0;
+                       if (global_text) {
+                               free(global_text);
+                               global_text = 0;
                        }
 
-                       text = (char *) malloc(1);
-                       text[0] = '\0';
+                       global_text = (char *) malloc(1);
+                       global_text[0] = '\0';
 
                        while (!feof(fp)) {
-                               unsigned int l = strlen(text);
+                               unsigned int l = strlen(global_text);
 
                                if (fgets(buf, 256, fp) == NULL) {
                                        break;
                                }
-                               text = (char *) realloc(text, l + strlen(buf) + 1);
-                               strcat(text, buf);
+                               global_text = (char *) realloc(global_text, l + strlen(buf) + 1);
+                               strcat(global_text, buf);
 
-                               if (strlen(text) > max_user_text) {
+                               if (strlen(global_text) > max_user_text) {
                                        break;
                                }
                        }
                        fclose(fp);
-                       text_lines = line + 1;
+                       if (strlen(global_text) < 1) {
+                               CRIT_ERR("no text supplied in configuration; exiting");
+                       }
+                       global_text_lines = line + 1;
                        return;
                }
 #ifdef TCP_PORT_MONITOR
@@ -8355,6 +8449,21 @@ static void load_config_file(const char *f)
                         * as per config */
                }
 #endif
+               CONF("if_up_strictness") {
+                       if (!value) {
+                               ERR("incorrect if_up_strictness value, defaulting to 'up'");
+                               ifup_strictness = IFUP_UP;
+                       } else if (!strcmp(value, "up")) {
+                               ifup_strictness = IFUP_UP;
+                       } else if (!strcmp(value, "link")) {
+                               ifup_strictness = IFUP_LINK;
+                       } else if (!strcmp(value, "address")) {
+                               ifup_strictness = IFUP_ADDR;
+                       } else {
+                               ERR("incorrect if_up_strictness value, defaulting to 'up'");
+                               ifup_strictness = IFUP_UP;
+                       }
+               }
                else {
                        ERR("%s: %d: no such configuration: '%s'", f, line, name);
                }
@@ -8371,10 +8480,43 @@ static void load_config_file(const char *f)
                // default to update_interval
                info.music_player_interval = update_interval;
        }
+       if (!global_text) { // didn't supply any text
+               CRIT_ERR("missing text block in configuration; exiting");
+       }
+}
+
+static void print_help(const char *prog_name) {
+       printf("Usage: %s [OPTION]...\n"
+                       "Conky is a system monitor that renders text on desktop or to own transparent\n"
+                       "window. Command line options will override configurations defined in config\n"
+                       "file.\n"
+                       "   -v, --version             version\n"
+                       "   -q, --quiet               quiet mode\n"
+                       "   -c, --config=FILE         config file to load\n"
+                       "   -d, --daemonize           daemonize, fork to background\n"
+                       "   -h, --help                help\n"
+#ifdef X11
+                       "   -a, --alignment=ALIGNMENT text alignment on screen, {top,bottom,middle}_{left,right,middle}\n"
+                       "   -f, --font=FONT           font to use\n"
+#ifdef OWN_WINDOW
+                       "   -o, --own-window          create own window to draw\n"
+#endif
+#ifdef HAVE_XDBE
+                       "   -b, --double-buffer       double buffer (prevents flickering)\n"
+#endif
+                       "   -w, --window-id=WIN_ID    window id to draw\n"
+                       "   -x X                      x position\n"
+                       "   -y Y                      y position\n"
+#endif /* X11 */
+                       "   -t, --text=TEXT           text to render, remember single quotes, like -t '$uptime'\n"
+                       "   -u, --interval=SECS       update interval\n"
+                       "   -i COUNT                  number of times to update Conky (and quit)\n",
+                       prog_name
+       );
 }
 
 /* : means that character before that takes an argument */
-static const char *getopt_string = "vVdt:u:i:hc:"
+static const char *getopt_string = "vVqdt:u:i:hc:"
 #ifdef X11
        "x:y:w:a:f:"
 #ifdef OWN_WINDOW
@@ -8409,6 +8551,10 @@ static const struct option longopts[] = {
 
 int main(int argc, char **argv)
 {
+#ifdef X11
+       char *s, *temp;
+       unsigned int x;
+#endif
        struct sigaction act, oact;
 
        g_signal_pending = 0;
@@ -8421,9 +8567,6 @@ int main(int argc, char **argv)
 
        /* handle command line parameters that don't change configs */
 #ifdef X11
-       char *s, *temp;
-       unsigned int x;
-
        if (((s = getenv("LC_ALL")) && *s) || ((s = getenv("LC_CTYPE")) && *s)
                        || ((s = getenv("LANG")) && *s)) {
                temp = (char *) malloc((strlen(s) + 1) * sizeof(char));
@@ -8459,36 +8602,13 @@ int main(int argc, char **argv)
                                if (current_config) {
                                        free(current_config);
                                }
-                               current_config = strdup(optarg);
+                               current_config = strndup(optarg, max_user_text);
+                               break;
+                       case 'q':
+                               freopen("/dev/null", "w", stderr);
                                break;
-
                        case 'h':
-                               printf("Usage: %s [OPTION]...\n"
-                                          "Conky is a system monitor that renders text on desktop or to own transparent\n"
-                                          "window. Command line options will override configurations defined in config\n"
-                                          "file.\n"
-                                          "   -V, --version             version\n"
-                                          "   -c, --config=FILE         config file to load\n"
-                                          "   -d, --daemonize           daemonize, fork to background\n"
-                                          "   -h, --help                help\n"
-#ifdef X11
-                                          "   -a, --alignment=ALIGNMENT text alignment on screen, {top,bottom}_{left,right}\n"
-                                          "   -f, --font=FONT           font to use\n"
-#ifdef OWN_WINDOW
-                                          "   -o, --own-window          create own window to draw\n"
-#endif
-#ifdef HAVE_XDBE
-                                          "   -b, --double-buffer       double buffer (prevents flickering)\n"
-#endif
-                                          "   -w, --window-id=WIN_ID    window id to draw\n"
-                                          "   -x X                      x position\n"
-                                          "   -y Y                      y position\n"
-#endif /* X11 */
-                                          "   -t, --text=TEXT           text to render, remember single quotes, like -t '$uptime'\n"
-                                          "   -u, --interval=SECS       update interval\n"
-                                          "   -i NUM                    number of times to update Conky\n",
-                                          argv[0]
-                               );
+                               print_help(argv[0]);
                                return 0;
 #ifdef X11
                        case 'w':
@@ -8527,13 +8647,13 @@ int main(int argc, char **argv)
                /* Try to use personal config file first */
                variable_substitute(CONFIG_FILE, buf, sizeof(buf));
                if (buf[0] && (fp = fopen(buf, "r"))) {
-                       current_config = strdup(buf);
+                       current_config = strndup(buf, max_user_text);
                        fclose(fp);
                }
 
                /* Try to use system config file if personal config not readable */
                if (!current_config && (fp = fopen(SYSTEM_CONFIG_FILE, "r"))) {
-                       current_config = strdup(SYSTEM_CONFIG_FILE);
+                       current_config = strndup(SYSTEM_CONFIG_FILE, max_user_text);
                        fclose(fp);
                }
 
@@ -8557,7 +8677,7 @@ int main(int argc, char **argv)
                variable_substitute(MAIL_FILE, buf, 256);
 
                if (buf[0] != '\0') {
-                       current_mail_spool = strdup(buf);
+                       current_mail_spool = strndup(buf, text_buffer_size);
                }
        }
 #endif
@@ -8610,12 +8730,12 @@ int main(int argc, char **argv)
 #endif
 #endif /* X11 */
                        case 't':
-                               if (text) {
-                                       free(text);
-                                       text = 0;
+                               if (global_text) {
+                                       free(global_text);
+                                       global_text = 0;
                                }
-                               text = strdup(optarg);
-                               convert_escapes(text);
+                               global_text = strndup(optarg, max_user_text);
+                               convert_escapes(global_text);
                                break;
 
                        case 'u':
@@ -8650,12 +8770,12 @@ int main(int argc, char **argv)
 #endif /* X11 */
 
        /* generate text and get initial size */
-       extract_variable_text(text);
-       if (text) {
-               free(text);
-               text = 0;
+       extract_variable_text(global_text);
+       if (global_text) {
+               free(global_text);
+               global_text = 0;
        }
-       text = NULL;
+       global_text = NULL;
        /* fork */
        if (fork_to_background) {
                int pid = fork();