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);