diff --git a/cmake/ConkyBuildOptions.cmake b/cmake/ConkyBuildOptions.cmake index 219acb33..580a9a24 100644 --- a/cmake/ConkyBuildOptions.cmake +++ b/cmake/ConkyBuildOptions.cmake @@ -73,12 +73,14 @@ if(OS_LINUX) option(BUILD_WLAN "Enable wireless support" false) # nvidia may also work on FreeBSD, not sure option(BUILD_NVIDIA "Enable nvidia support" false) + option(BUILD_IPV6 "Enable if you want IPv6 support" true) else(OS_LINUX) set(BUILD_PORT_MONITORS false) set(BUILD_IBM false) set(BUILD_HDDTEMP false) set(BUILD_WLAN false) set(BUILD_NVIDIA false) + set(BUILD_IPV6 false) endif(OS_LINUX) # Optional features etc diff --git a/cmake/ConkyPlatformChecks.cmake b/cmake/ConkyPlatformChecks.cmake index a852c999..38159525 100644 --- a/cmake/ConkyPlatformChecks.cmake +++ b/cmake/ConkyPlatformChecks.cmake @@ -82,6 +82,13 @@ if(BUILD_IRC) set(conky_libs ${conky_libs} -lircclient) endif(BUILD_IRC) +if(BUILD_IPV6) + find_file(IF_INET6 if_inet6 PATHS /proc/net) + if(NOT IF_INET6) + message(FATAL_ERROR "/proc/net/if_inet6 unavailable") + endif(NOT IF_INET6) +endif(BUILD_IPV6) + if(BUILD_HTTP) find_file(HTTP_H_ microhttpd.h) #I'm not using check_include_files because microhttpd.h seems to need a lot of different headers and i'm not sure which... diff --git a/cmake/config.h.in b/cmake/config.h.in index a505765b..f946aecf 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -95,6 +95,8 @@ #cmakedefine BUILD_IRC 1 +#cmakedefine BUILD_IPV6 1 + #cmakedefine BUILD_HTTP 1 #cmakedefine BUILD_ICONV 1 diff --git a/doc/variables.xml b/doc/variables.xml index 06d30e67..a2c0770b 100644 --- a/doc/variables.xml +++ b/doc/variables.xml @@ -2032,6 +2032,15 @@ Bar that shows amount of memory in use (including memory used by system buffers and caches) + + + + + + + Amount of "dirty" memory (linux only) + + @@ -3909,6 +3918,19 @@ Display time in UTC (universal coordinate time). + + + + + + + + IPv6 addresses for an interface, followed by + netmask if -n is specified and scope with -s. Scopes are + Global(G), Host-local(H), Link-local(L), Site-local(S), Compat(C) + and Unspecified(/). Linux only. + + diff --git a/src/common.cc b/src/common.cc index d7a32d64..ead2bbe4 100644 --- a/src/common.cc +++ b/src/common.cc @@ -395,6 +395,7 @@ PRINT_HR_GENERATOR(memwithbuffers) PRINT_HR_GENERATOR(memeasyfree) PRINT_HR_GENERATOR(memfree) PRINT_HR_GENERATOR(memmax) +PRINT_HR_GENERATOR(memdirty) PRINT_HR_GENERATOR(swap) PRINT_HR_GENERATOR(swapfree) PRINT_HR_GENERATOR(swapmax) diff --git a/src/common.h b/src/common.h index 34255db2..026dd045 100644 --- a/src/common.h +++ b/src/common.h @@ -103,6 +103,7 @@ void print_memwithbuffers(struct text_object *, char *, int); void print_memeasyfree(struct text_object *, char *, int); void print_memfree(struct text_object *, char *, int); void print_memmax(struct text_object *, char *, int); +void print_memdirty(struct text_object *, char *, int); void print_swap(struct text_object *, char *, int); void print_swapfree(struct text_object *, char *, int); void print_swapmax(struct text_object *, char *, int); diff --git a/src/conky.cc b/src/conky.cc index 547b3459..da2f56bb 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -256,6 +256,9 @@ static void print_version(void) #ifdef BUILD_HTTP << _(" * HTTP\n") #endif +#ifdef BUILD_IPV6 + << _(" * IPv6\n") +#endif /* BUILD_IPV6 */ #ifdef BUILD_IRC << _(" * IRC\n") #endif diff --git a/src/conky.h b/src/conky.h index c996f9de..148ca062 100644 --- a/src/conky.h +++ b/src/conky.h @@ -179,7 +179,7 @@ struct information { double uptime; /* memory information in kilobytes */ - unsigned long long mem, memwithbuffers, memeasyfree, memfree, memmax; + unsigned long long mem, memwithbuffers, memeasyfree, memfree, memmax, memdirty; unsigned long long swap, swapfree, swapmax; unsigned long long bufmem, buffers, cached; diff --git a/src/core.cc b/src/core.cc index ada33288..010dc3b7 100644 --- a/src/core.cc +++ b/src/core.cc @@ -883,6 +883,11 @@ struct text_object *construct_text_object(char *s, const char *arg, long END OBJ(addrs, &update_net_stats) parse_net_stat_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_addrs; +#ifdef BUILD_IPV6 + END OBJ(v6addrs, &update_net_stats) + parse_net_stat_arg(obj, arg, free_at_crash); + obj->callbacks.print = &print_v6addrs; +#endif /* BUILD_IPV6 */ END #endif /* __linux__ */ OBJ_ARG(tail, 0, "tail needs arguments") @@ -1003,6 +1008,10 @@ struct text_object *construct_text_object(char *s, const char *arg, long obj->callbacks.print = &print_memmax; END OBJ(memperc, &update_meminfo) obj->callbacks.percentage = &mem_percentage; +#ifdef __linux__ + END OBJ(memdirty, &update_meminfo) + obj->callbacks.print = &print_memdirty; +#endif #ifdef BUILD_X11 END OBJ(memgauge, &update_meminfo) scan_gauge(obj, arg, 1); diff --git a/src/eve.cc b/src/eve.cc index 187a5f4e..40853d6a 100644 --- a/src/eve.cc +++ b/src/eve.cc @@ -254,19 +254,6 @@ static char *formatTime(struct tm *ends) } } -static int file_exists(const char *filename) -{ - struct stat fi; - - if ((stat(filename, &fi)) == 0) { - if (fi.st_size > 0) - return 1; - else - return 0; - } else - return 0; -} - static void writeSkilltree(char *content, const char *filename) { FILE *fp = fopen(filename, "w"); @@ -283,13 +270,12 @@ static char *getSkillname(const char *file, int skillid) xmlDocPtr doc = 0; xmlNodePtr root = 0; - if (!file_exists(file)) { - skilltree = getXmlFromAPI(NULL, NULL, NULL, EVEURL_SKILLTREE); - writeSkilltree(skilltree, file); - free(skilltree); - } + skilltree = getXmlFromAPI(NULL, NULL, NULL, EVEURL_SKILLTREE); + writeSkilltree(skilltree, file); + free(skilltree); doc = xmlReadFile(file, NULL, 0); + unlink(file); if (!doc) return NULL; @@ -340,7 +326,7 @@ static char *getSkillname(const char *file, int skillid) static char *eve(char *userid, char *apikey, char *charid) { Character *chr = NULL; - const char *skillfile = "/tmp/.cesf"; + char skillfile[] = "/tmp/.cesfXXXXXX"; int i = 0; char *output = 0; char *timel = 0; @@ -348,6 +334,7 @@ static char *eve(char *userid, char *apikey, char *charid) char *content = 0; time_t now = 0; char *error = 0; + int tmp_fd, old_umask; for (i = 0; i < MAXCHARS; i++) { @@ -400,6 +387,14 @@ static char *eve(char *userid, char *apikey, char *charid) output = (char *)malloc(200 * sizeof(char)); timel = formatTime(&chr->ends); + old_umask = umask(0066); + tmp_fd = mkstemp(skillfile); + umask(old_umask); + if (tmp_fd == -1) { + error = strdup("Cannot create temporary file"); + return error; + } + close(tmp_fd); skill = getSkillname(skillfile, chr->skill); chr->skillname = strdup(skill); diff --git a/src/linux.cc b/src/linux.cc index d25dff82..880405fe 100644 --- a/src/linux.cc +++ b/src/linux.cc @@ -32,6 +32,7 @@ #include "net_stat.h" #include "diskio.h" #include "temphelper.h" +#include "proc.h" #include #include #include @@ -165,7 +166,7 @@ int update_meminfo(void) /* unsigned int a; */ char buf[256]; - info.mem = info.memwithbuffers = info.memmax = info.swap = info.swapfree = info.swapmax = + info.mem = info.memwithbuffers = info.memmax = info.memdirty = info.swap = info.swapfree = info.swapmax = info.bufmem = info.buffers = info.cached = info.memfree = info.memeasyfree = 0; if (!(meminfo_fp = open_file("/proc/meminfo", &rep))) { @@ -189,6 +190,8 @@ int update_meminfo(void) sscanf(buf, "%*s %llu", &info.buffers); } else if (strncmp(buf, "Cached:", 7) == 0) { sscanf(buf, "%*s %llu", &info.cached); + } else if (strncmp(buf, "Dirty:", 6) == 0) { + sscanf(buf, "%*s %llu", &info.memdirty); } } @@ -567,6 +570,54 @@ int update_net_stats(void) free(winfo); #endif } + +#ifdef BUILD_IPV6 + FILE *file; + char v6addr[32]; + char devname[21]; + unsigned int netmask, scope; + struct net_stat *ns; + struct v6addr *lastv6; + if ((file = fopen(PROCDIR"/net/if_inet6", "r")) != NULL) { + while (fscanf(file, "%32s %*02x %02x %02x %*02x %20s\n", v6addr, &netmask, &scope, devname) != EOF) { + ns = get_net_stat(devname, NULL, NULL); + if(ns->v6addrs == NULL) { + lastv6 = (struct v6addr *) malloc(sizeof(struct v6addr)); + ns->v6addrs = lastv6; + } else { + lastv6 = ns->v6addrs; + while(lastv6->next) lastv6 = lastv6->next; + lastv6->next = (struct v6addr *) malloc(sizeof(struct v6addr)); + lastv6 = lastv6->next; + } + for(int i=0; i<16; i++) + sscanf(v6addr+2*i, "%2hhx", &(lastv6->addr.s6_addr[i])); + lastv6->netmask = netmask; + switch(scope) { + case 0: //global + lastv6->scope = 'G'; + break; + case 16: //host-local + lastv6->scope = 'H'; + break; + case 32: //link-local + lastv6->scope = 'L'; + break; + case 64: //site-local + lastv6->scope = 'S'; + break; + case 128: //compat + lastv6->scope = 'C'; + break; + default: + lastv6->scope = '?'; + } + lastv6->next = NULL; + } + } + fclose(file); +#endif /* BUILD_IPV6 */ + first = 0; fclose(net_dev_fp); @@ -842,6 +893,26 @@ int update_cpu_usage(void) return 0; } +//fscanf() that reads floats with points even if you are using a locale where +//floats are with commas +int fscanf_no_i18n(FILE *stream, const char *format, ...) { + int returncode; + va_list ap; + +#ifdef BUILD_I18N + const char *oldlocale = setlocale(LC_NUMERIC, NULL); + + setlocale(LC_NUMERIC, "C"); +#endif + va_start(ap, format); + returncode = vfscanf(stream, format, ap); + va_end(ap); +#ifdef BUILD_I18N + setlocale(LC_NUMERIC, oldlocale); +#endif + return returncode; +} + int update_load_average(void) { #ifdef HAVE_GETLOADAVG @@ -862,7 +933,7 @@ int update_load_average(void) info.loadavg[0] = info.loadavg[1] = info.loadavg[2] = 0.0; return 0; } - if (fscanf(fp, "%f %f %f", &info.loadavg[0], &info.loadavg[1], + if (fscanf_no_i18n(fp, "%f %f %f", &info.loadavg[0], &info.loadavg[1], &info.loadavg[2]) < 0) info.loadavg[0] = info.loadavg[1] = info.loadavg[2] = 0.0; fclose(fp); @@ -1588,6 +1659,12 @@ present voltage: 16608 mV On some systems POWER_SUPPLY_ENERGY_* is replaced by POWER_SUPPLY_CHARGE_* */ +/* Tiago Marques Vale + Regarding the comment above, since kernel 2.6.36.1 I have + POWER_SUPPLY_POWER_NOW instead of POWER_SUPPLY_CURRENT_NOW + See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=532000 +*/ + #define SYSFS_BATTERY_BASE_PATH "/sys/class/power_supply" #define ACPI_BATTERY_BASE_PATH "/proc/acpi/battery" #define APM_PATH "/proc/apm" @@ -1709,6 +1786,8 @@ void get_battery_stuff(char *buffer, unsigned int n, const char *bat, int item) * tradition! */ else if (strncmp(buf, "POWER_SUPPLY_CURRENT_NOW=", 25) == 0) sscanf(buf, "POWER_SUPPLY_CURRENT_NOW=%d", &present_rate); + else if (strncmp(buf, "POWER_SUPPLY_POWER_NOW=", 23) == 0) + sscanf(buf, "POWER_SUPPLY_POWER_NOW=%d", &present_rate); else if (strncmp(buf, "POWER_SUPPLY_ENERGY_NOW=", 24) == 0) sscanf(buf, "POWER_SUPPLY_ENERGY_NOW=%d", &remaining_capacity); else if (strncmp(buf, "POWER_SUPPLY_ENERGY_FULL=", 25) == 0) diff --git a/src/net_stat.cc b/src/net_stat.cc index d7b5251e..42b7e1fd 100644 --- a/src/net_stat.cc +++ b/src/net_stat.cc @@ -90,10 +90,35 @@ struct net_stat *get_net_stat(const char *dev, void *free_at_crash1, void *free_ void parse_net_stat_arg(struct text_object *obj, const char *arg, void *free_at_crash) { + bool shownetmask = false; + bool showscope = false; + char nextarg[21]; //longest arg possible is a devname (max 20 chars) + int i=0; + struct net_stat *netstat = NULL; + if (!arg) arg = DEFAULTNETDEV; - obj->data.opaque = get_net_stat(arg, obj, free_at_crash); + while(sscanf(arg+i, " %20s", nextarg) == 1) { + if(strcmp(nextarg, "-n") == 0 || strcmp(nextarg, "--netmask") == 0) shownetmask = true; + else if(strcmp(nextarg, "-s") == 0 || strcmp(nextarg, "--scope") == 0) showscope = true; + else if(nextarg[0]=='-') { //multiple flags in 1 arg + for(int j=1; nextarg[j] != 0; j++) { + if(nextarg[j]=='n') shownetmask = true; + if(nextarg[j]=='s') showscope = true; + } + } + else netstat = get_net_stat(nextarg, obj, free_at_crash); + i+=strlen(nextarg); //skip this arg + while( ! (isspace(arg[i]) || arg[i] == 0)) i++; //and skip the spaces in front of it + } + if(netstat == NULL) netstat = get_net_stat(DEFAULTNETDEV, obj, free_at_crash); + +#ifdef BUILD_IPV6 + netstat->v6show_nm = shownetmask; + netstat->v6show_sc = showscope; +#endif /* BUILD_IPV6 */ + obj->data.opaque = netstat; } void parse_net_stat_bar_arg(struct text_object *obj, const char *arg, void *free_at_crash) @@ -205,6 +230,47 @@ void print_addrs(struct text_object *obj, char *p, int p_max_size) strncpy(p, "0.0.0.0", p_max_size); } } + +#ifdef BUILD_IPV6 +void print_v6addrs(struct text_object *obj, char *p, int p_max_size) +{ + struct net_stat *ns = (struct net_stat *)obj->data.opaque; + char tempaddress[INET6_ADDRSTRLEN]; + struct v6addr *current_v6 = ns->v6addrs; + + if (!ns) + return; + + if(p_max_size == 0) return; + if( ! ns->v6addrs) { + strncpy(p, "::", p_max_size); + if(ns->v6show_nm) strncat(p, "/128", p_max_size); + if(ns->v6show_sc) strncat(p, "(/)", p_max_size); + return; + } + *p=0; + while(current_v6) { + inet_ntop(AF_INET6, &(current_v6->addr), tempaddress, INET6_ADDRSTRLEN); + strncat(p, tempaddress, p_max_size); + //netmask + if(ns->v6show_nm) { + char netmaskstr[5]; //max 5 chars (/128 + null-terminator) + sprintf(netmaskstr, "/%u", current_v6->netmask); + strncat(p, netmaskstr, p_max_size); + } + //scope + if(ns->v6show_sc) { + char scopestr[3]; + sprintf(scopestr, "(%c)", current_v6->scope); + strncat(p, scopestr, p_max_size); + } + //next (or last) address + current_v6 = current_v6->next; + if(current_v6) strncat(p, ", ", p_max_size); + } +} +#endif /* BUILD_IPV6 */ + #endif /* __linux__ */ #ifdef BUILD_X11 @@ -353,9 +419,19 @@ double wireless_link_barval(struct text_object *obj) void clear_net_stats(void) { +#ifdef BUILD_IPV6 + struct v6addr *nextv6; +#endif /* BUILD_IPV6 */ int i; for (i = 0; i < MAX_NET_INTERFACES; i++) { free_and_zero(netstats[i].dev); +#ifdef BUILD_IPV6 + while(netstats[i].v6addrs) { + nextv6 = netstats[i].v6addrs; + netstats[i].v6addrs = netstats[i].v6addrs->next; + free_and_zero(nextv6); + } +#endif /* BUILD_IPV6 */ } memset(netstats, 0, sizeof(netstats)); } diff --git a/src/net_stat.h b/src/net_stat.h index e048eba7..5446785f 100644 --- a/src/net_stat.h +++ b/src/net_stat.h @@ -33,6 +33,15 @@ #include /* struct sockaddr */ +#ifdef BUILD_IPV6 +struct v6addr { + struct in6_addr addr; + unsigned int netmask; + char scope; + struct v6addr *next; +}; +#endif /* BUILD_IPV6 */ + struct net_stat { char *dev; int up; @@ -40,6 +49,11 @@ struct net_stat { long long recv, trans; double recv_speed, trans_speed; struct sockaddr addr; +#ifdef BUILD_IPV6 + struct v6addr *v6addrs; + bool v6show_nm; + bool v6show_sc; +#endif /* BUILD_IPV6 */ #if defined(__linux__) char addrs[273]; #endif /* __linux__ */ @@ -70,6 +84,9 @@ void print_totalup(struct text_object *, char *, int); void print_addr(struct text_object *, char *, int); #ifdef __linux__ void print_addrs(struct text_object *, char *, int); +#ifdef BUILD_IPV6 +void print_v6addrs(struct text_object *, char *, int); +#endif /* BUILD_IPV6 */ #endif /* __linux__ */ #ifdef BUILD_X11 void parse_net_stat_graph_arg(struct text_object *, const char *, void *); diff --git a/src/specials.cc b/src/specials.cc index 3e05810e..900a2eca 100644 --- a/src/specials.cc +++ b/src/specials.cc @@ -279,8 +279,7 @@ struct special_t *new_special_t_node() { special_t *newnode = new special_t; - newnode->graph = NULL; - newnode->next = NULL; + memset(newnode, 0, sizeof *newnode); return newnode; } diff --git a/src/xmms2.cc b/src/xmms2.cc index d3159412..f6078d50 100644 --- a/src/xmms2.cc +++ b/src/xmms2.cc @@ -371,9 +371,12 @@ double xmms2_barval(struct text_object *obj) void print_xmms2_smart(struct text_object *obj, char *p, int p_max_size) { (void)obj; - if (strlen(info.xmms2.title) < 2 - && strlen(info.xmms2.title) < 2) { + int artist_len = strlen(info.xmms2.artist); + int title_len = strlen(info.xmms2.title); + if (artist_len < 2 && title_len < 2) { snprintf(p, p_max_size, "%s", info.xmms2.url); + } else if (artist_len < 1) { + snprintf(p, p_max_size, "%s", info.xmms2.title); } else { snprintf(p, p_max_size, "%s - %s", info.xmms2.artist, info.xmms2.title);