X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fconky.c;h=8edbc241cdd77cbe7db74bd35f770aae588b78cf;hb=2913a7121634c99cc685e5bdfdddfef519ce0830;hp=5ceac4a79ea18e8fbdb10175ebd42c44c97e437d;hpb=3d26a4880e92df2c6004d85c1be458e35c6bfc3a;p=monky diff --git a/src/conky.c b/src/conky.c index 5ceac4a..8edbc24 100644 --- a/src/conky.c +++ b/src/conky.c @@ -74,12 +74,12 @@ /* #define SIGNAL_BLOCKING */ #undef SIGNAL_BLOCKING -static void print_version() +static void print_version(void) { printf("Conky %s compiled %s for %s\n", VERSION, BUILD_DATE, BUILD_ARCH); printf("\nCompiled in features:\n\n" - "system config file: %s\n\n" + "System config file: %s\n\n" #ifdef X11 " X11:\n" # ifdef HAVE_XDAMAGE @@ -117,13 +117,18 @@ static void print_version() #endif /* RSS */ #ifdef HAVE_IWLIB " * wireless\n" -#endif - "", SYSTEM_CONFIG_FILE +#endif /* HAVE_IWLIB */ +#ifdef SMAPI + " * smapi\n" +#endif /* SMAPI */ + "", SYSTEM_CONFIG_FILE ); exit(0); } +static const char *suffixes[] = { "B", "kiB", "MiB", "GiB", "TiB", "PiB", "" }; + #ifdef X11 /* text size */ @@ -135,15 +140,19 @@ static int text_width, text_height; enum alignment { TOP_LEFT = 1, TOP_RIGHT, + TOP_MIDDLE, BOTTOM_LEFT, BOTTOM_RIGHT, + BOTTOM_MIDDLE, + MIDDLE_LEFT, + MIDDLE_RIGHT, NONE }; /* for fonts */ struct font_list { - char name[TEXT_BUFFER_SIZE]; + char name[DEFAULT_TEXT_BUFFER_SIZE]; int num; XFontStruct *font; @@ -157,8 +166,6 @@ static int selected_font = 0; static int font_count = -1; struct font_list *fonts = NULL; -static char *suffixes[] = { "B", "kiB", "MiB", "GiB", "TiB", "PiB", "" }; - #ifdef XFT #define font_height() (use_xft ? (fonts[selected_font].xftfont->ascent + \ @@ -181,7 +188,7 @@ static char *suffixes[] = { "B", "kiB", "MiB", "GiB", "TiB", "PiB", "" }; #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) { @@ -197,14 +204,16 @@ int addfont(const char *data_in) == NULL) { CRIT_ERR("malloc"); } + memset(fonts, 0, sizeof(struct font_list)); } fonts = realloc(fonts, (sizeof(struct font_list) * (font_count + 1))); + memset(&fonts[font_count], 0, sizeof(struct font_list)); if (fonts == NULL) { CRIT_ERR("realloc in addfont"); } // must account for null terminator - if (strlen(data_in) < TEXT_BUFFER_SIZE) { - strncpy(fonts[font_count].name, data_in, TEXT_BUFFER_SIZE); + if (strlen(data_in) < DEFAULT_TEXT_BUFFER_SIZE) { + strncpy(fonts[font_count].name, data_in, DEFAULT_TEXT_BUFFER_SIZE); #ifdef XFT fonts[font_count].font_alpha = 0xffff; #endif @@ -221,17 +230,18 @@ void set_first_font(const char *data_in) == NULL) { CRIT_ERR("malloc"); } + memset(fonts, 0, sizeof(struct font_list)); font_count++; } if (strlen(data_in) > 1) { - strncpy(fonts[0].name, data_in, TEXT_BUFFER_SIZE - 1); + strncpy(fonts[0].name, data_in, DEFAULT_TEXT_BUFFER_SIZE - 1); #ifdef XFT fonts[0].font_alpha = 0xffff; #endif } } -void free_fonts() +void free_fonts(void) { int i; @@ -239,10 +249,12 @@ void free_fonts() #ifdef XFT if (use_xft) { XftFontClose(display, fonts[i].xftfont); + fonts[i].xftfont = 0; } else #endif { XFreeFont(display, fonts[i].font); + fonts[i].font = 0; } } free(fonts); @@ -251,19 +263,22 @@ void free_fonts() selected_font = 0; } -static void load_fonts() +static void load_fonts(void) { int i; for (i = 0; i <= font_count; i++) { #ifdef XFT /* load Xft font */ - if (use_xft) { + if (use_xft && fonts[i].xftfont) { + continue; + } else if (use_xft) { /* if (fonts[i].xftfont != NULL && selected_font == 0) { XftFontClose(display, fonts[i].xftfont); } */ - if ((fonts[i].xftfont = XftFontOpenName(display, screen, - fonts[i].name)) != NULL) { + fonts[i].xftfont = XftFontOpenName(display, screen, + fonts[i].name); + if (fonts[i].xftfont != NULL) { continue; } @@ -288,7 +303,7 @@ static void load_fonts() XFreeFont(display, fonts[i].font); } */ - if ((fonts[i].font = XLoadQueryFont(display, fonts[i].name)) == NULL) { + if (fonts[i].font || (fonts[i].font = XLoadQueryFont(display, fonts[i].name)) == NULL) { ERR("can't load font '%s'", fonts[i].name); if ((fonts[i].font = XLoadQueryFont(display, "fixed")) == NULL) { CRIT_ERR("can't load font '%s'", "fixed"); @@ -361,7 +376,7 @@ static unsigned int max_specials = MAX_SPECIALS_DEFAULT; static unsigned int max_user_text = MAX_USER_TEXT_DEFAULT; /* maximum size of individual text buffers, ie $exec buffer size */ -unsigned int text_buffer_size = TEXT_BUFFER_SIZE; +unsigned int text_buffer_size = DEFAULT_TEXT_BUFFER_SIZE; #ifdef HAVE_ICONV #define CODEPAGE_LENGTH 20 @@ -461,10 +476,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 @@ -478,7 +493,7 @@ static inline int calc_text_width(const char *s, int l) /* formatted text to render on screen, generated in generate_text(), * drawn in draw_stuff() */ -static char text_buffer[TEXT_BUFFER_SIZE * 4]; +static char *text_buffer; /* special stuff in text_buffer */ @@ -673,7 +688,7 @@ static void new_font(char *buf, char *args) if (args) { struct special_t *s = new_special(buf, FONT); - if (!s->font_added || strcmp(args, fonts[s->font_added].name)) { + if (s->font_added > font_count || !s->font_added || strncmp(args, fonts[s->font_added].name, DEFAULT_TEXT_BUFFER_SIZE)) { int tmp = selected_font; selected_font = s->font_added = addfont(args); @@ -692,10 +707,11 @@ static void new_font(char *buf, char *args) 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; @@ -712,7 +728,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 @@ -789,7 +805,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; } @@ -797,7 +813,7 @@ 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); } @@ -809,14 +825,14 @@ static char *scan_graph(const char *args, int *w, int *h, 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); } @@ -827,14 +843,14 @@ static char *scan_graph(const char *args, int *w, int *h, 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); @@ -954,11 +970,16 @@ 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 *buf, int size, const char *format, int width, + const char *func_name, ...) { int len; va_list argp; - char *tempbuf = malloc(size * sizeof(char)); + char *tempbuf; + + if (size < 1) { + return 0; + } + tempbuf = malloc(size * sizeof(char)); // Passes the varargs along to vsnprintf va_start(argp, func_name); @@ -970,10 +991,10 @@ static int spaced_print(char *buf, int size, char *format, int width, len = snprintf(buf, size, "%s", tempbuf); break; case LEFT_SPACER: - len = snprintf(buf, width, "%*s", width - 1, tempbuf); + len = snprintf(buf, size, "%*s", width - 1, tempbuf); break; case RIGHT_SPACER: - len = snprintf(buf, width, "%-*s", width - 1, tempbuf); + len = snprintf(buf, size, "%-*s", width - 1, tempbuf); break; default: CRIT_ERR("%s encountered invalid use_spacer value (%d)", func_name, @@ -986,9 +1007,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; @@ -1031,6 +1052,9 @@ static void human_readable(long long num, char *buf, int size, char *func_name) enum text_object_type { OBJ_addr, +#if defined(__linux__) + OBJ_addrs, +#endif /* __linux__ */ #ifndef __OpenBSD__ OBJ_acpiacadapter, OBJ_adt746xcpu, @@ -1056,6 +1080,9 @@ enum text_object_type { OBJ_color7, OBJ_color8, OBJ_color9, + OBJ_conky_version, + OBJ_conky_build_date, + OBJ_conky_build_arch, OBJ_font, OBJ_cpu, OBJ_cpubar, @@ -1079,6 +1106,8 @@ enum text_object_type { OBJ_execgraph, OBJ_execibar, OBJ_execigraph, + OBJ_execp, + OBJ_execpi, OBJ_freq, OBJ_freq_g, OBJ_freq_dyn, @@ -1088,6 +1117,7 @@ enum text_object_type { OBJ_fs_free, OBJ_fs_free_perc, OBJ_fs_size, + OBJ_fs_type, OBJ_fs_used, OBJ_fs_used_perc, OBJ_goto, @@ -1101,6 +1131,7 @@ enum text_object_type { OBJ_platform, OBJ_hwmon, #if defined(__linux__) + OBJ_disk_protect, OBJ_i8k_version, OBJ_i8k_bios, OBJ_i8k_serial, @@ -1116,6 +1147,12 @@ enum text_object_type { OBJ_ibm_temps, OBJ_ibm_volume, OBJ_ibm_brightness, + OBJ_if_up, + OBJ_if_gw, + OBJ_ioscheduler, + OBJ_gw_iface, + OBJ_gw_ip, + OBJ_laptop_mode, OBJ_pb_battery, OBJ_voltage_mv, OBJ_voltage_v, @@ -1152,6 +1189,7 @@ enum text_object_type { OBJ_mixerbar, OBJ_mixerlbar, OBJ_mixerrbar, + OBJ_nameserver, OBJ_new_mails, OBJ_nodename, OBJ_pre_exec, @@ -1179,6 +1217,10 @@ enum text_object_type { OBJ_upspeedgraph, OBJ_uptime, OBJ_uptime_short, + OBJ_user_names, + OBJ_user_terms, + OBJ_user_times, + OBJ_user_number, OBJ_imap, OBJ_imap_messages, OBJ_imap_unseen, @@ -1226,8 +1268,6 @@ enum text_object_type { OBJ_xmms2_title, OBJ_xmms2_genre, OBJ_xmms2_comment, - OBJ_xmms2_decoder, - OBJ_xmms2_transport, OBJ_xmms2_url, OBJ_xmms2_date, OBJ_xmms2_tracknr, @@ -1240,6 +1280,8 @@ enum text_object_type { OBJ_xmms2_status, OBJ_xmms2_bar, OBJ_xmms2_smart, + OBJ_xmms2_playlist, + OBJ_xmms2_timesplayed, #endif #ifdef AUDACIOUS OBJ_audacious_status, @@ -1277,6 +1319,12 @@ enum text_object_type { #ifdef HDDTEMP OBJ_hddtemp, #endif +#ifdef SMAPI + OBJ_smapi, + OBJ_smapi_bat_bar, + OBJ_smapi_bat_perc, + OBJ_if_smapi_bat_installed, +#endif OBJ_entropy_avail, OBJ_entropy_poolsize, OBJ_entropy_bar @@ -1406,8 +1454,8 @@ struct text_object_list { struct text_object *text_objects; }; -static unsigned int text_object_count; -static struct text_object *text_objects; +static unsigned int global_text_object_count; +static struct text_object *global_text_objects; static void generate_text_internal(char *p, int p_max_size, struct text_object *objs, unsigned int object_count, struct information *cur); @@ -1419,9 +1467,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) { @@ -1475,8 +1524,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; @@ -1492,7 +1541,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]; @@ -1504,12 +1553,17 @@ void *imap_thread(struct mail_s *mail) struct stat stat_buf; struct hostent *he; 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 herror("gethostbyname"); exit(1); } 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); @@ -1534,9 +1588,6 @@ void *imap_thread(struct mail_s *mail) fail++; goto next_iteration; } - struct timeval timeout; - int res; - fd_set fdset; timeout.tv_sec = 60; // 60 second timeout i guess timeout.tv_usec = 0; @@ -1564,7 +1615,7 @@ void *imap_thread(struct mail_s *mail) strncat(sendbuf, mail->user, MAXDATASIZE - strlen(sendbuf) - 1); strncat(sendbuf, " ", MAXDATASIZE - strlen(sendbuf) - 1); strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1); - strncat(sendbuf, "\n", MAXDATASIZE - strlen(sendbuf) - 1); + strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1); if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) { perror("send a1"); fail++; @@ -1590,7 +1641,7 @@ void *imap_thread(struct mail_s *mail) } strncpy(sendbuf, "a2 STATUS ", MAXDATASIZE); strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1); - strncat(sendbuf, " (MESSAGES UNSEEN)\n", + strncat(sendbuf, " (MESSAGES UNSEEN)\r\n", MAXDATASIZE - strlen(sendbuf) - 1); if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) { perror("send a2"); @@ -1629,7 +1680,7 @@ void *imap_thread(struct mail_s *mail) &mail->unseen); timed_thread_unlock(mail->p_timed_thread); } - strncpy(sendbuf, "a3 logout\n", MAXDATASIZE); + strncpy(sendbuf, "a3 logout\r\n", MAXDATASIZE); if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) { perror("send a3"); fail++; @@ -1677,7 +1728,7 @@ next_iteration: return 0; } -void *pop3_thread(struct mail_s *mail) +void *pop3_thread(void *arg) { int sockfd, numbytes; char recvbuf[MAXDATASIZE]; @@ -1688,12 +1739,17 @@ void *pop3_thread(struct mail_s *mail) struct stat stat_buf; struct hostent *he; 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 herror("gethostbyname"); exit(1); } 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); @@ -1718,9 +1774,6 @@ void *pop3_thread(struct mail_s *mail) fail++; goto next_iteration; } - struct timeval timeout; - int res; - fd_set fdset; timeout.tv_sec = 60; // 60 second timeout i guess timeout.tv_usec = 0; @@ -1746,7 +1799,7 @@ void *pop3_thread(struct mail_s *mail) } strncpy(sendbuf, "USER ", MAXDATASIZE); strncat(sendbuf, mail->user, MAXDATASIZE - strlen(sendbuf) - 1); - strncat(sendbuf, "\n", MAXDATASIZE - strlen(sendbuf) - 1); + strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1); if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) { perror("send USER"); fail++; @@ -1772,7 +1825,7 @@ void *pop3_thread(struct mail_s *mail) } strncpy(sendbuf, "PASS ", MAXDATASIZE); strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1); - strncat(sendbuf, "\n", MAXDATASIZE - strlen(sendbuf) - 1); + strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1); if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) { perror("send PASS"); fail++; @@ -1796,7 +1849,7 @@ void *pop3_thread(struct mail_s *mail) fail++; goto next_iteration; } - strncpy(sendbuf, "STAT\n", MAXDATASIZE); + strncpy(sendbuf, "STAT\r\n", MAXDATASIZE); if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) { perror("send STAT"); fail++; @@ -1831,7 +1884,7 @@ void *pop3_thread(struct mail_s *mail) sscanf(reply, "%lu %lu", &mail->unseen, &mail->used); timed_thread_unlock(mail->p_timed_thread); } - strncpy(sendbuf, "QUIT\n", MAXDATASIZE); + strncpy(sendbuf, "QUIT\r\n", MAXDATASIZE); if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) { perror("send QUIT"); fail++; @@ -1877,14 +1930,18 @@ next_iteration: return 0; } -void *threaded_exec(struct text_object *obj) +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'; @@ -1905,7 +1962,7 @@ void *threaded_exec(struct text_object *obj) return 0; } -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)); @@ -1920,24 +1977,16 @@ static void free_text_objects(unsigned int count, struct text_object *objs) switch (objs[i].type) { #ifndef __OpenBSD__ case OBJ_acpitemp: - close(objs[i].data.i); - break; case OBJ_acpitempf: close(objs[i].data.i); break; case OBJ_i2c: - close(objs[i].data.sysfs.fd); - break; case OBJ_platform: - close(objs[i].data.sysfs.fd); - break; case OBJ_hwmon: close(objs[i].data.sysfs.fd); break; #endif /* !__OpenBSD__ */ case OBJ_time: - free(objs[i].data.s); - break; case OBJ_utime: free(objs[i].data.s); break; @@ -1992,31 +2041,45 @@ static void free_text_objects(unsigned int count, struct text_object *objs) break; case OBJ_text: case OBJ_font: - free(objs[i].data.s); - break; case OBJ_image: - free(objs[i].data.s); - break; case OBJ_exec: - free(objs[i].data.s); - break; case OBJ_execbar: - free(objs[i].data.s); - break; case OBJ_execgraph: + case OBJ_execp: free(objs[i].data.s); break; - /* case OBJ_execibar: - free(objs[i].data.s); - break; - case OBJ_execigraph: - free(objs[i].data.s); - break; */ #ifdef HAVE_ICONV case OBJ_iconv_start: free_iconv(); break; #endif +#ifdef __LINUX__ + case OBJ_disk_protect: + free(objs[i].data.s); + break; + case OBJ_if_up: + free(objs[i].data.ifblock.s); + free(objs[i].data.ifblock.str); + break; + case OBJ_if_gw: + free(objs[i].data.ifblock.s); + free(objs[i].data.ifblock.str); + case OBJ_gw_iface: + case OBJ_gw_ip: + if (info.gw_info.iface) { + free(info.gw_info.iface); + info.gw_info.iface = 0; + } + if (info.gw_info.ip) { + free(info.gw_info.ip); + info.gw_info.ip = 0; + } + break; + case OBJ_ioscheduler: + if(objs[i].data.s) + free(objs[i].data.s); + break; +#endif #ifdef XMMS2 case OBJ_xmms2_artist: if (info.xmms2.artist) { @@ -2048,18 +2111,6 @@ static void free_text_objects(unsigned int count, struct text_object *objs) info.xmms2.comment = 0; } break; - case OBJ_xmms2_decoder: - if (info.xmms2.decoder) { - free(info.xmms2.decoder); - info.xmms2.url = 0; - } - break; - case OBJ_xmms2_transport: - if (info.xmms2.transport) { - free(info.xmms2.transport); - info.xmms2.url = 0; - } - break; case OBJ_xmms2_url: if (info.xmms2.url) { free(info.xmms2.url); @@ -2078,6 +2129,12 @@ static void free_text_objects(unsigned int count, struct text_object *objs) info.xmms2.status = 0; } break; + case OBJ_xmms2_playlist: + if (info.xmms2.playlist) { + free(info.xmms2.playlist); + info.xmms2.playlist = 0; + } + break; case OBJ_xmms2_smart: if (info.xmms2.artist) { free(info.xmms2.artist); @@ -2118,7 +2175,10 @@ static void free_text_objects(unsigned int count, struct text_object *objs) free(objs[i].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); break; @@ -2126,12 +2186,10 @@ static void free_text_objects(unsigned int count, struct text_object *objs) free(objs[i].data.texeci.cmd); free(objs[i].data.texeci.buffer); break; - case OBJ_top: - if (info.first_process) { - free_all_processes(); - info.first_process = NULL; - } + case OBJ_nameserver: + free_dns_data(); break; + case OBJ_top: case OBJ_top_mem: if (info.first_process) { free_all_processes(); @@ -2148,49 +2206,62 @@ static void free_text_objects(unsigned int count, struct text_object *objs) case OBJ_entropy_poolsize: case OBJ_entropy_bar: break; + case OBJ_user_names: + if (info.users.names) { + free(info.users.names); + info.users.names = 0; + } + break; + case OBJ_user_terms: + if (info.users.terms) { + free(info.users.terms); + info.users.terms = 0; + } + break; + case OBJ_user_times: + if (info.users.times) { + free(info.users.times); + info.users.times = 0; + } + break; +#ifdef SMAPI + case OBJ_smapi: + case OBJ_smapi_bat_perc: + free(objs[i].data.s); + break; + case OBJ_if_smapi_bat_installed: + free(objs[i].data.ifblock.s); + free(objs[i].data.ifblock.str); + break; +#endif +#ifdef MPD + case OBJ_mpd_title: + case OBJ_mpd_artist: + case OBJ_mpd_album: + case OBJ_mpd_random: + case OBJ_mpd_repeat: + case OBJ_mpd_vol: + case OBJ_mpd_bitrate: + case OBJ_mpd_status: + case OBJ_mpd_host: + case OBJ_mpd_port: + case OBJ_mpd_password: + case OBJ_mpd_bar: + case OBJ_mpd_elapsed: + case OBJ_mpd_length: + case OBJ_mpd_track: + case OBJ_mpd_name: + case OBJ_mpd_file: + case OBJ_mpd_percent: + case OBJ_mpd_smart: + free_mpd_vars(&info); + break; +#endif } } free(objs); -#ifdef MPD - if (info.mpd.title) { - free(info.mpd.title); - info.mpd.title = NULL; - } - if (info.mpd.artist) { - free(info.mpd.artist); - info.mpd.artist = NULL; - } - if (info.mpd.album) { - free(info.mpd.album); - info.mpd.album = NULL; - } - if (info.mpd.random) { - free(info.mpd.random); - info.mpd.random = NULL; - } - if (info.mpd.repeat) { - free(info.mpd.repeat); - info.mpd.repeat = NULL; - } - if (info.mpd.track) { - free(info.mpd.track); - info.mpd.track = NULL; - } - if (info.mpd.name) { - free(info.mpd.name); - info.mpd.name = NULL; - } - if (info.mpd.file) { - free(info.mpd.file); - info.mpd.file = NULL; - } - if (info.mpd.status) { - free(info.mpd.status); - info.mpd.status = NULL; - } -#endif /* text_objects = NULL; - text_object_count = 0; */ + text_object_count = 0; */ } void scan_mixer_bar(const char *arg, int *a, int *w, int *h) @@ -2369,7 +2440,7 @@ static struct text_object *construct_text_object(const char *s, obj->data.s = strdup(bat); END OBJ(battery_bar, 0) char bat[64]; - + obj->b = 6; if (arg) { arg = scan_bar(arg, &obj->a, &obj->b); sscanf(arg, "%63s", bat); @@ -2380,6 +2451,11 @@ static struct text_object *construct_text_object(const char *s, #endif /* !__OpenBSD__ */ #if defined(__linux__) + END OBJ(disk_protect, 0) + if (arg) + obj->data.s = strdup(arg); + else + CRIT_ERR("disk_protect needs an argument"); END OBJ(i8k_version, INFO_I8K) END OBJ(i8k_bios, INFO_I8K) END OBJ(i8k_serial, INFO_I8K) @@ -2404,6 +2480,32 @@ static struct text_object *construct_text_object(const char *s, obj->data.sensor = atoi(&arg[0]); END OBJ(ibm_volume, 0) END OBJ(ibm_brightness, 0) + END OBJ(if_up, 0) + if (blockdepth >= MAX_IF_BLOCK_DEPTH) { + CRIT_ERR("MAX_IF_BLOCK_DEPTH exceeded"); + } + if (!arg) { + ERR("if_up needs an argument"); + obj->data.ifblock.s = 0; + } else + obj->data.ifblock.s = strdup(arg); + blockstart[blockdepth] = object_count; + obj->data.ifblock.pos = object_count + 2; + blockdepth++; + END OBJ(if_gw, 0) + if (blockdepth >= MAX_IF_BLOCK_DEPTH) { + CRIT_ERR("MAX_IF_BLOCK_DEPTH exceeded"); + } + blockstart[blockdepth] = object_count; + obj->data.ifblock.pos = object_count + 2; + blockdepth++; + END OBJ(ioscheduler, 0) + if (!arg) { + CRIT_ERR("get_ioscheduler needs an argument (e.g. hda)"); + obj->data.s = 0; + } else + obj->data.s = strdup(arg); + END OBJ(laptop_mode, 0) END OBJ(pb_battery, 0) if (arg && strcmp(arg, "status") == 0) { obj->data.i = PB_BATT_STATUS; @@ -2566,6 +2668,9 @@ static struct text_object *construct_text_object(const char *s, obj->data.l = color9; END OBJ(font, 0) obj->data.s = scan_font(arg); + END OBJ(conky_version, 0) + END OBJ(conky_build_date, 0) + END OBJ(conky_build_arch, 0) END OBJ(downspeed, INFO_NET) if (arg) { obj->data.net = get_net_stat(arg); @@ -2608,12 +2713,14 @@ static struct text_object *construct_text_object(const char *s, #ifdef HAVE_POPEN END OBJ(exec, 0) obj->data.s = strdup(arg ? arg : ""); + END OBJ(execp, 0) + obj->data.s = strdup(arg ? arg : ""); END OBJ(execbar, 0) obj->data.s = strdup(arg ? arg : ""); END OBJ(execgraph, 0) obj->data.s = strdup(arg ? arg : ""); END OBJ(execibar, 0) - unsigned int n; + int n; if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) { char buf[256]; @@ -2626,7 +2733,7 @@ static struct text_object *construct_text_object(const char *s, obj->data.execi.cmd = strdup(arg + n); } END OBJ(execigraph, 0) - unsigned int n; + int n; if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) { char buf[256]; @@ -2639,7 +2746,21 @@ static struct text_object *construct_text_object(const char *s, obj->data.execi.cmd = strdup(arg + n); } END OBJ(execi, 0) - unsigned int n; + int n; + + if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) { + char buf[256]; + + ERR("${execi command}"); + obj->type = OBJ_text; + snprintf(buf, 256, "${%s}", s); + obj->data.s = strdup(buf); + } else { + obj->data.execi.cmd = strdup(arg + n); + obj->data.execi.buffer = malloc(text_buffer_size); + } + END OBJ(execpi, 0) + int n; if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) { char buf[256]; @@ -2650,10 +2771,10 @@ static struct text_object *construct_text_object(const char *s, obj->data.s = strdup(buf); } else { obj->data.execi.cmd = strdup(arg + n); - obj->data.execi.buffer = (char *) calloc(1, 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]; @@ -2664,7 +2785,7 @@ static struct text_object *construct_text_object(const char *s, obj->data.s = strdup(buf); } else { obj->data.texeci.cmd = strdup(arg + n); - obj->data.texeci.buffer = (char *) calloc(1, text_buffer_size); + obj->data.texeci.buffer = malloc(text_buffer_size); } obj->data.texeci.p_timed_thread = NULL; END OBJ(pre_exec, 0) @@ -2689,7 +2810,6 @@ static struct text_object *construct_text_object(const char *s, } #endif END OBJ(fs_bar, INFO_FS) - obj->data.fsbar.h = 4; arg = scan_bar(arg, &obj->data.fsbar.w, &obj->data.fsbar.h); if (arg) { while (isspace(*arg)) { @@ -2703,16 +2823,18 @@ static struct text_object *construct_text_object(const char *s, } obj->data.fsbar.fs = prepare_fs_stat(arg); END OBJ(fs_bar_free, INFO_FS) - obj->data.fsbar.h = 4; + arg = scan_bar(arg, &obj->data.fsbar.w, &obj->data.fsbar.h); if (arg) { - unsigned int n; - - if (sscanf(arg, "%d %n", &obj->data.fsbar.h, &n) >= 1) { - arg += n; + while (isspace(*arg)) { + arg++; + } + if (*arg == '\0') { + arg = "/"; } } else { arg = "/"; } + obj->data.fsbar.fs = prepare_fs_stat(arg); END OBJ(fs_free, INFO_FS) if (!arg) { @@ -2734,6 +2856,11 @@ static struct text_object *construct_text_object(const char *s, arg = "/"; } obj->data.fs = prepare_fs_stat(arg); + END OBJ(fs_type, INFO_FS) + if (!arg) { + arg = "/"; + } + obj->data.fs = prepare_fs_stat(arg); END OBJ(fs_used, INFO_FS) if (!arg) { arg = "/"; @@ -2741,6 +2868,8 @@ static struct text_object *construct_text_object(const char *s, obj->data.fs = prepare_fs_stat(arg); END OBJ(hr, 0) obj->data.i = arg ? atoi(arg) : 1; + END OBJ(nameserver, INFO_DNS) + obj->data.i = arg ? atoi(arg) : 0; END OBJ(offset, 0) obj->data.i = arg ? atoi(arg) : 1; END OBJ(voffset, 0) @@ -2920,6 +3049,14 @@ static struct text_object *construct_text_object(const char *s, } 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"); + } +#endif /* __linux__ */ END OBJ(tail, 0) char buf[64]; int n1, n2; @@ -3188,11 +3325,11 @@ static struct text_object *construct_text_object(const char *s, obj->data.local_mail.box = strdup(dst); obj->data.local_mail.interval = n1; END OBJ(mboxscan, 0) - obj->data.mboxscan.args = (char *) malloc(TEXT_BUFFER_SIZE); + obj->data.mboxscan.args = (char *) malloc(text_buffer_size); obj->data.mboxscan.output = (char *) malloc(text_buffer_size); /* if '1' (in mboxscan.c) then there was SIGUSR1, hmm */ obj->data.mboxscan.output[0] = 1; - strncpy(obj->data.mboxscan.args, arg, TEXT_BUFFER_SIZE); + strncpy(obj->data.mboxscan.args, arg, text_buffer_size); END OBJ(mem, INFO_MEM) END OBJ(memmax, INFO_MEM) END OBJ(memperc, INFO_MEM) @@ -3371,6 +3508,13 @@ static struct text_object *construct_text_object(const char *s, } END OBJ(uptime_short, INFO_UPTIME) END OBJ(uptime, INFO_UPTIME) + END OBJ(user_names, INFO_USERS) + END OBJ(user_times, INFO_USERS) + END OBJ(user_terms, INFO_USERS) + END OBJ(user_number, INFO_USERS) + END OBJ(gw_iface, INFO_GW) + END OBJ(gw_ip, INFO_GW) + END OBJ(if_gw, INFO_GW) #ifndef __OpenBSD__ END OBJ(adt746xcpu, 0) END OBJ(adt746xfan, 0) @@ -3413,16 +3557,52 @@ static struct text_object *construct_text_object(const char *s, } else { obj->global_mode = 1; } -#ifdef MPD - END OBJ(mpd_artist, INFO_MPD) - END OBJ(mpd_title, INFO_MPD) - if (arg) { - sscanf(arg, "%d", &info.mpd.max_title_len); - if (info.mpd.max_title_len > 0) { - info.mpd.max_title_len++; +#ifdef SMAPI + END OBJ(smapi, 0) + if (arg) + obj->data.s = strdup(arg); + else + ERR("smapi needs an argument"); + END OBJ(if_smapi_bat_installed, 0) + if (blockdepth >= MAX_IF_BLOCK_DEPTH) { + CRIT_ERR("MAX_IF_BLOCK_DEPTH exceeded"); + } + if (!arg) { + ERR("if_smapi_bat_installed needs an argument"); + obj->data.ifblock.s = 0; + } else + obj->data.ifblock.s = strdup(arg); + 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); + else + ERR("smapi_bat_perc needs an argument"); + END OBJ(smapi_bat_bar, 0) + if(arg) { + int cnt; + if(sscanf(arg, "%i %n", &obj->data.i, &cnt) <= 0) { + ERR("first argument to smapi_bat_bar must be an integer value"); + obj->data.i = -1; } else { - CRIT_ERR("mpd_title: invalid length argument"); + obj->b = 4; + arg = scan_bar(arg + cnt, &obj->a, &obj->b); } + } else + ERR("if_smapi_bat_bar needs an argument"); +#endif /* SMAPI */ +#ifdef MPD + END OBJ(mpd_artist, INFO_MPD) + END OBJ(mpd_title, INFO_MPD) + if (arg) { + sscanf(arg, "%d", &info.mpd.max_title_len); + if (info.mpd.max_title_len > 0) { + info.mpd.max_title_len++; + } else { + CRIT_ERR("mpd_title: invalid length argument"); + } } else { info.mpd.max_title_len = 0; } @@ -3448,8 +3628,6 @@ static struct text_object *construct_text_object(const char *s, END OBJ(xmms2_title, INFO_XMMS2) END OBJ(xmms2_genre, INFO_XMMS2) END OBJ(xmms2_comment, INFO_XMMS2) - END OBJ(xmms2_decoder, INFO_XMMS2) - END OBJ(xmms2_transport, INFO_XMMS2) END OBJ(xmms2_url, INFO_XMMS2) END OBJ(xmms2_tracknr, INFO_XMMS2) END OBJ(xmms2_bitrate, INFO_XMMS2) @@ -3463,6 +3641,8 @@ static struct text_object *construct_text_object(const char *s, END OBJ(xmms2_bar, INFO_XMMS2) scan_bar(arg, &obj->data.pair.a, &obj->data.pair.b); END OBJ(xmms2_smart, INFO_XMMS2) + END OBJ(xmms2_playlist, INFO_XMMS2) + END OBJ(xmms2_timesplayed, INFO_XMMS2) #endif #ifdef AUDACIOUS END OBJ(audacious_status, INFO_AUDACIOUS) @@ -3650,24 +3830,28 @@ static struct text_object *create_plain_text(const char *s) 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 = strdup(const_p); + 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 = 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 @@ -3679,7 +3863,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; @@ -3728,7 +3912,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 */ @@ -3745,10 +3929,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 @@ -3798,6 +3982,7 @@ 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; } @@ -3805,25 +3990,37 @@ static void extract_variable_text(const char *p) { struct text_object_list *list; - free_text_objects(text_object_count, text_objects); - text_object_count = 0; - text_objects = NULL; + free_text_objects(global_text_object_count, global_text_objects); + if (tmpstring1) { + free(tmpstring1); + tmpstring1 = 0; + } + if (tmpstring2) { + free(tmpstring2); + tmpstring2 = 0; + } + if (text_buffer) { + free(text_buffer); + text_buffer = 0; + } + global_text_object_count = 0; + global_text_objects = NULL; list = extract_variable_text_internal(p); - text_objects = list->text_objects; - text_object_count = list->text_object_count; + global_text_objects = list->text_objects; + global_text_object_count = list->text_object_count; free(list); } -void parse_conky_vars(char *text, char *p, struct information *cur) +struct text_object_list *parse_conky_vars(char *text, char *p, struct information *cur) { struct text_object_list *object_list = extract_variable_text_internal(text); - generate_text_internal(p, P_MAX_SIZE, object_list->text_objects, + generate_text_internal(p, max_user_text, object_list->text_objects, object_list->text_object_count, cur); - free(object_list); + return object_list; } /* Allows reading from a FIFO (i.e., /dev/xconsole). @@ -3907,6 +4104,46 @@ 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) +{ + char buf[10]; + unsigned long nt; // narrow time, for speed on 32-bit + unsigned cc; // centiseconds + unsigned nn; // multi-purpose whatever + + nt = time; + 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); + } + if (width >= snprintf(buf, sizeof buf, "%lu:%02u", nt, nn)) { + return strdup(buf); + } + nn = nt % 60; // minutes past the hour + nt /= 60; // total hours + if (width >= snprintf(buf, sizeof buf, "%lu,%02u", nt, nn)) { + return strdup(buf); + } + nn = nt; // now also hours + if (width >= snprintf(buf, sizeof buf, "%uh", nn)) { + return strdup(buf); + } + nn /= 24; // now days + if (width >= snprintf(buf, sizeof buf, "%ud", nn)) { + return strdup(buf); + } + nn /= 7; // now weeks + if (width >= snprintf(buf, sizeof buf, "%uw", nn)) { + return strdup(buf); + } + // well shoot, this outta' fit... + return strdup(""); +} + static void generate_text_internal(char *p, int p_max_size, struct text_object *objs, unsigned int object_count, struct information *cur) @@ -3914,13 +4151,18 @@ static void generate_text_internal(char *p, int p_max_size, unsigned int i; #ifdef HAVE_ICONV - char buff_in[P_MAX_SIZE] = { 0 }; + char buff_in[p_max_size]; + buff_in[0] = 0; iconv_converting = 0; #endif for (i = 0; i < object_count; i++) { struct text_object *obj = &objs[i]; + if (p_max_size < 1) { + break; + }; + #define OBJ(a) break; case OBJ_##a: switch (obj->type) { @@ -3994,7 +4236,7 @@ static void generate_text_internal(char *p, int p_max_size, } OBJ(wireless_link_qual_perc) { if (obj->data.net->link_qual_max > 0) { - spaced_print(p, p_max_size, "%.0f%%", 5, + spaced_print(p, p_max_size, "%.0f", 5, "wireless_link_qual_perc", (double) obj->data.net->link_qual / obj->data.net->link_qual_max * 100); @@ -4044,7 +4286,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) { - snprintf(p, p_max_size, "%d", 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)); @@ -4108,7 +4351,20 @@ static void generate_text_internal(char *p, int p_max_size, OBJ(color9) { new_fg(p, color9); } + OBJ(conky_version) { + snprintf(p, p_max_size, "%s", VERSION); + } + OBJ(conky_build_date) { + snprintf(p, p_max_size, "%s", BUILD_DATE); + } + OBJ(conky_build_arch) { + snprintf(p, p_max_size, "%s", BUILD_ARCH); + } #if defined(__linux__) + OBJ(disk_protect) { + snprintf(p, p_max_size, "%s", + get_disk_protect_queue(obj->data.s)); + } OBJ(i8k_version) { snprintf(p, p_max_size, "%s", i8k.version); } @@ -4191,6 +4447,32 @@ static void generate_text_internal(char *p, int p_max_size, OBJ(ibm_brightness) { get_ibm_acpi_brightness(p, p_max_size); } + OBJ(if_up) { + if ((obj->data.ifblock.s) + && (!interface_up(obj->data.ifblock.s))) { + i = obj->data.ifblock.pos; + if_jumped = 1; + } else { + if_jumped = 0; + } + } + OBJ(if_gw) { + if (!cur->gw_info.count) { + i = obj->data.ifblock.pos; + if_jumped = 1; + } else { + if_jumped = 0; + } + } + OBJ(gw_iface) { + snprintf(p, p_max_size, "%s", cur->gw_info.iface); + } + OBJ(gw_ip) { + snprintf(p, p_max_size, "%s", cur->gw_info.ip); + } + OBJ(laptop_mode) { + snprintf(p, p_max_size, "%d", get_laptop_mode()); + } OBJ(pb_battery) { get_powerbook_batt_info(p, p_max_size, obj->data.i); } @@ -4316,6 +4598,18 @@ static void generate_text_internal(char *p, int p_max_size, 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 + strcpy(p, "0.0.0.0"); + } +#endif /* __linux__ */ + #if defined(IMLIB2) && defined(X11) OBJ(image) { if (obj->a < 1) { @@ -4355,20 +4649,42 @@ static void generate_text_internal(char *p, int p_max_size, int length = fread(p, 1, p_max_size, fp); pclose(fp); - /* output[length] = '\0'; - if (length > 0 && output[length - 1] == '\n') { - output[length - 1] = '\0'; - } */ + p[length] = '\0'; if (length > 0 && p[length - 1] == '\n') { p[length - 1] = '\0'; } - // parse_conky_vars(output, p, cur); + } + OBJ(execp) { + FILE *fp; + struct information *my_info; + struct text_object_list *text_objects; + int length; + + fp = popen(obj->data.s, "r"); + fread(p, 1, p_max_size, fp); + pclose(fp); + + my_info = malloc(sizeof(struct information)); + memcpy(my_info, cur, sizeof(struct information)); + text_objects = parse_conky_vars(p, p, my_info); + + 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); + free(my_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'; @@ -4382,7 +4698,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 " @@ -4400,6 +4715,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'; @@ -4412,7 +4728,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 " @@ -4434,6 +4749,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'; @@ -4447,7 +4763,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 " @@ -4471,6 +4786,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'; @@ -4484,7 +4800,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 " @@ -4510,7 +4825,6 @@ static void generate_text_internal(char *p, int p_max_size, char *output = obj->data.execi.buffer; FILE *fp = popen(obj->data.execi.cmd, "r"); - // int length = fread(output, 1, text_buffer_size, fp); int length = fread(output, 1, text_buffer_size, fp); pclose(fp); @@ -4523,10 +4837,39 @@ static void generate_text_internal(char *p, int p_max_size, } // parse_conky_vars(output, p, cur); } + OBJ(execpi) { + struct text_object_list *text_objects = 0; + struct information *my_info = + malloc(sizeof(struct information)); + memcpy(my_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); + } else { + char *output = obj->data.execi.buffer; + FILE *fp = popen(obj->data.execi.cmd, "r"); + int length = fread(output, 1, text_buffer_size, fp); + + pclose(fp); + + output[length] = '\0'; + if (length > 0 && output[length - 1] == '\n') { + output[length - 1] = '\0'; + } + + text_objects = parse_conky_vars(obj->data.execi.buffer, p, my_info); + obj->data.execi.last_update = current_update_time; + } + free_text_objects(text_objects->text_object_count, text_objects->text_objects); + free(text_objects); + free(my_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"); @@ -4547,7 +4890,7 @@ static void generate_text_internal(char *p, int p_max_size, // this means we use info if (!info.mail->p_timed_thread) { info.mail->p_timed_thread = - timed_thread_create((void *) imap_thread, + timed_thread_create(&imap_thread, (void *) info.mail, info.mail->interval * 1000000); if (!info.mail->p_timed_thread) { ERR("Error creating imap timed thread"); @@ -4565,7 +4908,7 @@ static void generate_text_internal(char *p, int p_max_size, // this means we use obj if (!obj->data.mail->p_timed_thread) { obj->data.mail->p_timed_thread = - timed_thread_create((void *) imap_thread, + timed_thread_create(&imap_thread, (void *) obj->data.mail, obj->data.mail->interval * 1000000); if (!obj->data.mail->p_timed_thread) { @@ -4593,7 +4936,7 @@ static void generate_text_internal(char *p, int p_max_size, // this means we use info if (!info.mail->p_timed_thread) { info.mail->p_timed_thread = - timed_thread_create((void *) imap_thread, + timed_thread_create(&imap_thread, (void *) info.mail, info.mail->interval * 1000000); if (!info.mail->p_timed_thread) { ERR("Error creating imap timed thread"); @@ -4611,7 +4954,7 @@ static void generate_text_internal(char *p, int p_max_size, // this means we use obj if (!obj->data.mail->p_timed_thread) { obj->data.mail->p_timed_thread = - timed_thread_create((void *) imap_thread, + timed_thread_create(&imap_thread, (void *) obj->data.mail, obj->data.mail->interval * 1000000); if (!obj->data.mail->p_timed_thread) { @@ -4639,7 +4982,7 @@ static void generate_text_internal(char *p, int p_max_size, // this means we use info if (!info.mail->p_timed_thread) { info.mail->p_timed_thread = - timed_thread_create((void *) pop3_thread, + timed_thread_create(&pop3_thread, (void *) info.mail, info.mail->interval * 1000000); if (!info.mail->p_timed_thread) { ERR("Error creating pop3 timed thread"); @@ -4657,7 +5000,7 @@ static void generate_text_internal(char *p, int p_max_size, // this means we use obj if (!obj->data.mail->p_timed_thread) { obj->data.mail->p_timed_thread = - timed_thread_create((void *) pop3_thread, + timed_thread_create(&pop3_thread, (void *) obj->data.mail, obj->data.mail->interval * 1000000); if (!obj->data.mail->p_timed_thread) { @@ -4685,7 +5028,7 @@ static void generate_text_internal(char *p, int p_max_size, // this means we use info if (!info.mail->p_timed_thread) { info.mail->p_timed_thread = - timed_thread_create((void *) pop3_thread, + timed_thread_create(&pop3_thread, (void *) info.mail, info.mail->interval * 1000000); if (!info.mail->p_timed_thread) { ERR("Error creating pop3 timed thread"); @@ -4704,7 +5047,7 @@ static void generate_text_internal(char *p, int p_max_size, // this means we use obj if (!obj->data.mail->p_timed_thread) { obj->data.mail->p_timed_thread = - timed_thread_create((void *) pop3_thread, + timed_thread_create(&pop3_thread, (void *) obj->data.mail, obj->data.mail->interval * 1000000); if (!obj->data.mail->p_timed_thread) { @@ -4747,9 +5090,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) { - snprintf(p, p_max_size, "%*d", pad_percents, - (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"); } @@ -4760,6 +5103,10 @@ static void generate_text_internal(char *p, int p_max_size, human_readable(obj->data.fs->size, p, 255, "fs_size"); } } + OBJ(fs_type) { + if (obj->data.fs != NULL) + snprintf(p, p_max_size, "%s", obj->data.fs->type); + } OBJ(fs_used) { if (obj->data.fs != NULL) { human_readable(obj->data.fs->size - (obj->data.fs->free @@ -4781,9 +5128,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) { - snprintf(p, 4, "%d", - 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"); } @@ -4815,6 +5162,11 @@ static void generate_text_internal(char *p, int p_max_size, OBJ(hr) { new_hr(p, obj->data.i); } + OBJ(nameserver) { + if (cur->nameserver_info.nscount > obj->data.i) + snprintf(p, p_max_size, "%s", + cur->nameserver_info.ns_list[obj->data.i]); + } #ifdef RSS OBJ(rss) { PRSS *data = get_rss_info(obj->data.rss.uri, @@ -4853,9 +5205,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; @@ -4951,11 +5303,12 @@ static void generate_text_internal(char *p, int p_max_size, new_alignc(p, obj->data.i); } OBJ(if_empty) { + struct text_object_list *text_objects; struct information *my_info = malloc(sizeof(struct information)); - memcpy(my_info, cur, sizeof(struct information)); - parse_conky_vars(obj->data.ifblock.s, p, my_info); + text_objects = parse_conky_vars(obj->data.ifblock.s, p, my_info); + if (strlen(p) != 0) { i = obj->data.ifblock.pos; if_jumped = 1; @@ -4963,6 +5316,8 @@ 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); free(my_info); } OBJ(if_existing) { @@ -5003,6 +5358,9 @@ static void generate_text_internal(char *p, int p_max_size, if_jumped = 0; } } + OBJ(ioscheduler) { + snprintf(p, p_max_size, "%s", get_ioscheduler(obj->data.s)); + } OBJ(kernel) { snprintf(p, p_max_size, "%s", cur->uname_s.release); } @@ -5019,7 +5377,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); } } @@ -5063,7 +5421,7 @@ static void generate_text_internal(char *p, int p_max_size, } OBJ(mboxscan) { mbox_scan(obj->data.mboxscan.args, obj->data.mboxscan.output, - TEXT_BUFFER_SIZE); + text_buffer_size); snprintf(p, p_max_size, "%s", obj->data.mboxscan.output); } OBJ(new_mails) { @@ -5102,7 +5460,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); } } @@ -5128,14 +5486,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); @@ -5174,7 +5534,18 @@ static void generate_text_internal(char *p, int p_max_size, OBJ(uptime) { format_seconds(p, p_max_size, (int) cur->uptime); } - + OBJ(user_names) { + snprintf(p, p_max_size, "%s", cur->users.names); + } + OBJ(user_terms) { + snprintf(p, p_max_size, "%s", cur->users.terms); + } + OBJ(user_times) { + snprintf(p, p_max_size, "%s", cur->users.times); + } + OBJ(user_number) { + snprintf(p, p_max_size, "%d", cur->users.number); + } #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ || defined(__OpenBSD__)) && (defined(i386) || defined(__i386__)) OBJ(apm_adapter) { @@ -5291,7 +5662,8 @@ static void generate_text_internal(char *p, int p_max_size, } } OBJ(mpd_percent) { - snprintf(p, p_max_size, "%2.0f", 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, @@ -5331,12 +5703,6 @@ static void generate_text_internal(char *p, int p_max_size, OBJ(xmms2_comment) { snprintf(p, p_max_size, "%s", cur->xmms2.comment); } - OBJ(xmms2_decoder) { - snprintf(p, p_max_size, "%s", cur->xmms2.decoder); - } - OBJ(xmms2_transport) { - snprintf(p, p_max_size, "%s", cur->xmms2.transport); - } OBJ(xmms2_url) { snprintf(p, p_max_size, "%s", cur->xmms2.url); } @@ -5376,6 +5742,12 @@ static void generate_text_internal(char *p, int p_max_size, new_bar(p, obj->data.pair.a, obj->data.pair.b, (int) (cur->xmms2.progress * 255.0f)); } + OBJ(xmms2_playlist) { + snprintf(p, p_max_size, "%s", cur->xmms2.playlist); + } + OBJ(xmms2_timesplayed) { + snprintf(p, p_max_size, "%i", cur->xmms2.timesplayed); + } OBJ(xmms2_smart) { if (strlen(cur->xmms2.title) < 2 && strlen(cur->xmms2.title) < 2) { @@ -5466,47 +5838,6 @@ static void generate_text_internal(char *p, int p_max_size, snprintf(p, p_max_size, "%i", cur->bmpx.bitrate); } #endif - - char *format_time(unsigned long time, 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; - 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); - } - if (width >= snprintf(buf, sizeof buf, "%lu:%02u", nt, nn)) { - return strdup(buf); - } - nn = nt % 60; // minutes past the hour - nt /= 60; // total hours - if (width >= snprintf(buf, sizeof buf, "%lu,%02u", nt, nn)) { - return strdup(buf); - } - nn = nt; // now also hours - if (width >= snprintf(buf, sizeof buf, "%uh", nn)) { - return strdup(buf); - } - nn /= 24; // now days - if (width >= snprintf(buf, sizeof buf, "%ud", nn)) { - return strdup(buf); - } - nn /= 7; // now weeks - if (width >= snprintf(buf, sizeof buf, "%uw", nn)) { - return strdup(buf); - } - // well shoot, this outta' fit... - return strdup(""); - } - OBJ(top) { if (obj->data.top.num >= 0 && obj->data.top.num < 10) { char *time; @@ -5553,7 +5884,7 @@ static void generate_text_internal(char *p, int p_max_size, break; case TOP_CPU: snprintf(p, 7, "%6.2f", - cur->memu[obj->data.top.num]->cpu_perc); + cur->memu[obj->data.top.num]->amount); break; case TOP_PID: snprintf(p, 6, "%5i", @@ -5583,11 +5914,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; @@ -5659,11 +5991,12 @@ head: < 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 @@ -5758,6 +6091,43 @@ head: (double) cur->entropy.poolsize; new_bar(p, obj->a, obj->b, (int) (entropy_perc * 255.0f)); } +#ifdef SMAPI + OBJ(smapi) { + char *s; + if(obj->data.s) { + s = smapi_get_val(obj->data.s); + snprintf(p, p_max_size, "%s", s); + free(s); + } + } + OBJ(if_smapi_bat_installed) { + int idx; + if(obj->data.ifblock.s && sscanf(obj->data.ifblock.s, "%i", &idx) == 1) { + if(!smapi_bat_installed(idx)) { + i = obj->data.ifblock.pos; + if_jumped = 1; + } else + if_jumped = 0; + } else + ERR("argument to if_smapi_bat_installed must be an integer"); + } + OBJ(smapi_bat_perc) { + int idx, val; + if(obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) { + val = smapi_bat_installed(idx) ? + smapi_get_bat_int(idx, "remaining_percent") : 0; + spaced_print(p, p_max_size, "%*d", 4, "smapi_bat_perc", pad_percents, val); + } else + ERR("argument to smapi_bat_perc must be an integer"); + } + OBJ(smapi_bat_bar) { + if(obj->data.i >= 0 && smapi_bat_installed(obj->data.i)) + new_bar(p, obj->a, obj->b, (int) + (255 * smapi_get_bat_int(obj->data.i, "remaining_percent") / 100)); + else + new_bar(p, obj->a, obj->b, 0); + } +#endif /* SMAPI */ break; } @@ -5775,12 +6145,12 @@ head: dummy1 = dummy2 = a; - strncpy(buff_in, p, P_MAX_SIZE); + strncpy(buff_in, p, p_max_size); iconv(*iconv_cd[iconv_selected - 1], NULL, NULL, NULL, NULL); while (dummy1 > 0) { bytes = iconv(*iconv_cd[iconv_selected - 1], &ptr, &dummy1, - &outptr, &dummy2); + &outptr, &dummy2); if (bytes == -1) { ERR("Iconv codeset conversion failed"); break; @@ -5791,7 +6161,7 @@ head: * singlebyte codepage */ a = outptr - p; } -#endif +#endif /* HAVE_ICONV */ p += a; p_max_size -= a; } @@ -5800,7 +6170,7 @@ head: double current_update_time, last_update_time; -static void generate_text() +static void generate_text(void) { struct information *cur = &info; char *p; @@ -5811,7 +6181,7 @@ 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; @@ -5823,7 +6193,8 @@ static void generate_text() p = text_buffer; - generate_text_internal(p, P_MAX_SIZE, text_objects, text_object_count, cur); + generate_text_internal(p, max_user_text, global_text_objects, + global_text_object_count, cur); if (stuff_in_upper_case) { char *p; @@ -5841,7 +6212,7 @@ static void generate_text() } #ifdef X11 -static void set_font() +static void set_font(void) { #ifdef XFT if (use_xft) { @@ -5870,17 +6241,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 index = 1; + int width = 0; + unsigned int i; + if (!s) { return 0; } -#ifdef X11 - char *p, *final; p = strdup(s); final = p; - int index = 1; - int width = 0; - unsigned int i; while (*p) { if (*p == SPECIAL_CHAR) { @@ -5904,7 +6276,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 */ } @@ -5912,7 +6284,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; @@ -5947,6 +6319,11 @@ static void update_text_area() y = gap_y; break; + case TOP_MIDDLE: + x = workarea[2] / 2 - text_width / 2 - gap_x; + y = gap_y; + break; + default: case BOTTOM_LEFT: x = gap_x; @@ -5958,6 +6335,21 @@ static void update_text_area() y = workarea[3] - text_height - gap_y; break; + case BOTTOM_MIDDLE: + x = workarea[2] / 2 - text_width / 2 - gap_x; + y = workarea[3] - text_height - gap_y; + break; + + case MIDDLE_LEFT: + x = gap_x; + y = workarea[3] / 2 - text_height / 2 - gap_y; + break; + + case MIDDLE_RIGHT: + x = workarea[2] - text_width - gap_x; + y = workarea[3] / 2 - text_height / 2 - gap_y; + break; + #ifdef OWN_WINDOW case NONE: // Let the WM manage the window x = window.x; @@ -6072,24 +6464,25 @@ 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; + char space[2]; + + if (s[0] == '\0') { + return; + } width_of_s = get_string_width(s); if (out_to_console) { printf("%s\n", s); fflush(stdout); /* output immediately, don't buffer */ } - memset(tmpstring1, 0, TEXT_BUFFER_SIZE); - memset(tmpstring2, 0, TEXT_BUFFER_SIZE); - strncpy(tmpstring1, s, TEXT_BUFFER_SIZE - 1); + memset(tmpstring1, 0, text_buffer_size); + memset(tmpstring2, 0, text_buffer_size); + strncpy(tmpstring1, s, text_buffer_size - 1); pos = 0; added = 0; - char space[2]; snprintf(space, 2, " "); #ifdef X11 @@ -6098,25 +6491,19 @@ static void draw_string(const char *s) /* 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 < TEXT_BUFFER_SIZE; i++) { + for (i = 0; i < (int)text_buffer_size; i++) { if (tmpstring1[i] == '\t') { // 9 is ascii tab i2 = 0; for (i2 = 0; i2 < (8 - (1 + pos) % 8) && added <= max; i2++) { - /* if (pos + i2 > TEXT_BUFFER_SIZE - 1) { - fprintf(stderr, "buffer overrun detected\n"); - } */ /* guard against overrun */ - tmpstring2[MIN(pos + i2, TEXT_BUFFER_SIZE - 1)] = ' '; + tmpstring2[MIN(pos + i2, (int)text_buffer_size - 1)] = ' '; added++; } pos += i2; } else { if (tmpstring1[i] != 9) { - /* if (pos > TEXT_BUFFER_SIZE - 1) { - fprintf(stderr, "buffer overrun detected\n"); - } */ /* guard against overrun */ - tmpstring2[MIN(pos, TEXT_BUFFER_SIZE - 1)] = tmpstring1[i]; + tmpstring2[MIN(pos, (int)text_buffer_size - 1)] = tmpstring1[i]; pos++; } } @@ -6148,10 +6535,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 @@ -6161,13 +6548,14 @@ static void draw_string(const char *s) } cur_x += width_of_s; #endif /* X11 */ - memcpy(tmpstring1, s, TEXT_BUFFER_SIZE); + memcpy(tmpstring1, s, text_buffer_size); } long redmask, greenmask, bluemask; -void set_up_gradient() +void set_up_gradient(void) { + int i; #ifdef X11 colour_depth = DisplayPlanes(display, screen); #else @@ -6177,7 +6565,6 @@ void set_up_gradient() ERR("using non-standard colour depth, gradients may look like a " "lolly-pop"); } - int i; redmask = 0; greenmask = 0; @@ -6258,14 +6645,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; @@ -6276,7 +6666,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; @@ -6291,11 +6681,12 @@ static void draw_line(char *s) { #ifdef X11 char *p; + int cur_y_add = 0; + short font_h; 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; @@ -6343,13 +6734,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; @@ -6378,13 +6770,18 @@ 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; 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; @@ -6404,12 +6801,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) { @@ -6575,7 +6966,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; @@ -6606,7 +6997,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; @@ -6621,8 +7012,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++) { @@ -6679,7 +7070,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 @@ -6688,35 +7079,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++; @@ -6981,8 +7372,9 @@ static void main_loop() #endif switch (g_signal_pending) { + case SIGHUP: case SIGUSR1: - ERR("received SIGUSR1. reloading the config file."); + ERR("received SIGHUP or SIGUSR1. reloading the config file."); reload_config(); break; case SIGINT: @@ -6992,6 +7384,11 @@ static void main_loop() #ifdef X11 XDestroyRegion(region); region = NULL; +#ifdef HAVE_XDAMAGE + XDamageDestroy(display, damage); + XFixesDestroyRegion(display, region2); + XFixesDestroyRegion(display, part); +#endif /* HAVE_XDAMAGE */ #endif /* X11 */ return; /* return from main_loop */ /* break; */ @@ -7075,6 +7472,8 @@ void reload_config(void) #ifdef X11 free_fonts(); + load_fonts(); + set_font(); #endif /* X11 */ #ifdef TCP_PORT_MONITOR @@ -7092,9 +7491,6 @@ void reload_config(void) } #ifdef X11 - load_fonts(); - set_font(); - // clear the window first XClearWindow(display, RootWindow(display, screen)); @@ -7102,16 +7498,24 @@ void reload_config(void) #ifdef TCP_PORT_MONITOR info.p_tcp_port_monitor_collection = NULL; #endif -#ifdef AUDACIOUS - if (create_audacious_thread() != 0) { - CRIT_ERR("unable to create audacious thread!"); - } - timed_thread_register(info.audacious.p_timed_thread, - &info.audacious.p_timed_thread); -#endif extract_variable_text(text); free(text); text = NULL; + if (tmpstring1) { + free(tmpstring1); + } + tmpstring1 = malloc(text_buffer_size); + memset(tmpstring1, 0, text_buffer_size); + if (tmpstring2) { + free(tmpstring2); + } + tmpstring2 = malloc(text_buffer_size); + memset(tmpstring2, 0, text_buffer_size); + if (text_buffer) { + free(text_buffer); + } + text_buffer = malloc(max_user_text); + memset(text_buffer, 0, max_user_text); update_text(); } } @@ -7147,12 +7551,25 @@ void clean_up(void) free_fonts(); #endif /* X11 */ - free_text_objects(text_object_count, text_objects); - text_object_count = 0; - text_objects = NULL; + free_text_objects(global_text_object_count, global_text_objects); + if (tmpstring1) { + free(tmpstring1); + tmpstring1 = 0; + } + if (tmpstring2) { + free(tmpstring2); + tmpstring2 = 0; + } + if (text_buffer) { + free(text_buffer); + text_buffer = 0; + } + global_text_object_count = 0; + global_text_objects = NULL; - if (!text) { + if (text) { free(text); + text = 0; } free(current_config); @@ -7183,15 +7600,15 @@ void clean_up(void) static int string_to_bool(const char *s) { if (!s) { - return TRUE; + return 1; } else if (strcasecmp(s, "yes") == 0) { - return TRUE; + return 1; } else if (strcasecmp(s, "true") == 0) { - return TRUE; + return 1; } else if (strcasecmp(s, "1") == 0) { - return TRUE; + return 1; } - return FALSE; + return 0; } #ifdef X11 @@ -7201,18 +7618,34 @@ static enum alignment string_to_alignment(const char *s) return TOP_LEFT; } else if (strcasecmp(s, "top_right") == 0) { return TOP_RIGHT; + } else if (strcasecmp(s, "top_middle") == 0) { + return TOP_MIDDLE; } else if (strcasecmp(s, "bottom_left") == 0) { return BOTTOM_LEFT; } else if (strcasecmp(s, "bottom_right") == 0) { return BOTTOM_RIGHT; + } else if (strcasecmp(s, "bottom_middle") == 0) { + return BOTTOM_MIDDLE; + } else if (strcasecmp(s, "middle_left") == 0) { + return MIDDLE_LEFT; + } else if (strcasecmp(s, "middle_right") == 0) { + return MIDDLE_RIGHT; } else if (strcasecmp(s, "tl") == 0) { return TOP_LEFT; } else if (strcasecmp(s, "tr") == 0) { return TOP_RIGHT; + } else if (strcasecmp(s, "tm") == 0) { + return TOP_MIDDLE; } else if (strcasecmp(s, "bl") == 0) { return BOTTOM_LEFT; } else if (strcasecmp(s, "br") == 0) { return BOTTOM_RIGHT; + } else if (strcasecmp(s, "bm") == 0) { + return BOTTOM_MIDDLE; + } else if (strcasecmp(s, "ml") == 0) { + return MIDDLE_LEFT; + } else if (strcasecmp(s, "mr") == 0) { + return MIDDLE_RIGHT; } else if (strcasecmp(s, "none") == 0) { return NONE; } @@ -7249,10 +7682,9 @@ static void set_default_configurations(void) info.xmms2.title = NULL; info.xmms2.genre = NULL; info.xmms2.comment = NULL; - info.xmms2.decoder = NULL; - info.xmms2.transport = NULL; info.xmms2.url = NULL; info.xmms2.status = NULL; + info.xmms2.playlist = NULL; #endif use_spacer = NO_SPACER; #ifdef X11 @@ -7312,6 +7744,7 @@ static void set_default_configurations(void) update_interval = 3.0; info.music_player_interval = 1.0; stuff_in_upper_case = 0; + info.users.number = 1; #ifdef TCP_PORT_MONITOR tcp_port_monitor_args.max_port_monitor_connections = @@ -7901,13 +8334,18 @@ static void load_config_file(const char *f) CONF("text_buffer_size") { if (value) { text_buffer_size = atoi(value); + if (text_buffer_size < DEFAULT_TEXT_BUFFER_SIZE) { + ERR("text_buffer_size must be >=%i bytes", DEFAULT_TEXT_BUFFER_SIZE); + text_buffer_size = DEFAULT_TEXT_BUFFER_SIZE; + } } else { CONF_ERR; } } CONF("text") { - if (!text) { + if (text) { free(text); + text = 0; } text = (char *) malloc(1); @@ -8003,6 +8441,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; @@ -8015,9 +8457,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)); @@ -8100,6 +8539,17 @@ int main(int argc, char **argv) init_X11(); #endif /* X11 */ + /* check if specified config file is valid */ + if (current_config) { + struct stat sb; + if (stat(current_config, &sb) || + (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))) { + ERR("invalid configuration file '%s'\n", current_config); + free(current_config); + current_config = 0; + } + } + /* load current_config, CONFIG_FILE or SYSTEM_CONFIG_FILE */ if (!current_config) { @@ -8147,7 +8597,7 @@ int main(int argc, char **argv) /* handle other command line arguments */ -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) \ || defined(__NetBSD__) optind = optreset = 1; #else @@ -8193,8 +8643,9 @@ int main(int argc, char **argv) #endif #endif /* X11 */ case 't': - if (!text) { + if (text) { free(text); + text = 0; } text = strdup(optarg); convert_escapes(text); @@ -8233,8 +8684,9 @@ int main(int argc, char **argv) /* generate text and get initial size */ extract_variable_text(text); - if (!text) { + if (text) { free(text); + text = 0; } text = NULL; /* fork */ @@ -8263,13 +8715,26 @@ int main(int argc, char **argv) } } + text_buffer = malloc(max_user_text); + memset(text_buffer, 0, max_user_text); + tmpstring1 = malloc(text_buffer_size); + memset(tmpstring1, 0, text_buffer_size); + tmpstring2 = malloc(text_buffer_size); + memset(tmpstring2, 0, text_buffer_size); + #ifdef X11 selected_font = 0; update_text_area(); /* to get initial size of the window */ +#ifdef OWN_WINDOW init_window(own_window, text_width + border_margin * 2 + 1, text_height + border_margin * 2 + 1, set_transparent, background_colour, argv, argc); +#else /* OWN_WINDOW */ + init_window(0, text_width + border_margin * 2 + 1, + text_height + border_margin * 2 + 1, set_transparent, 0, + argv, argc); +#endif /* OWN_WINDOW */ selected_font = 0; update_text_area(); /* to position text/window on screen */ @@ -8301,18 +8766,11 @@ int main(int argc, char **argv) if (sigaction(SIGINT, &act, &oact) < 0 || sigaction(SIGUSR1, &act, &oact) < 0 + || sigaction(SIGHUP,&act,&oact) < 0 || sigaction(SIGTERM, &act, &oact) < 0) { ERR("error setting signal handler: %s", strerror(errno)); } -#ifdef AUDACIOUS - if (create_audacious_thread() != 0) { - CRIT_ERR("unable to create audacious thread!"); - } - timed_thread_register(info.audacious.p_timed_thread, - &info.audacious.p_timed_thread); -#endif - /* *************** * * MAIN CONKY LOOP * * *************** */