sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dwmstatus-netusage.c (3845B)


      1 #define _BSD_SOURCE
      2 #include <unistd.h>
      3 #include <stdbool.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <stdarg.h>
      7 #include <string.h>
      8 #include <strings.h>
      9 #include <sys/time.h>
     10 #include <time.h>
     11 #include <sys/types.h>
     12 #include <sys/wait.h>
     13 
     14 #include <X11/Xlib.h>
     15 
     16 char *tzargentina = "America/Buenos_Aires";
     17 char *tzutc = "UTC";
     18 char *tzberlin = "Europe/Berlin";
     19 
     20 static Display *dpy;
     21 
     22 char *
     23 smprintf(char *fmt, ...)
     24 {
     25 	va_list fmtargs;
     26 	char *ret;
     27 	int len;
     28 
     29 	va_start(fmtargs, fmt);
     30 	len = vsnprintf(NULL, 0, fmt, fmtargs);
     31 	va_end(fmtargs);
     32 
     33 	ret = malloc(++len);
     34 	if (ret == NULL) {
     35 		perror("malloc");
     36 		exit(1);
     37 	}
     38 
     39 	va_start(fmtargs, fmt);
     40 	vsnprintf(ret, len, fmt, fmtargs);
     41 	va_end(fmtargs);
     42 
     43 	return ret;
     44 }
     45 
     46 void
     47 settz(char *tzname)
     48 {
     49 	setenv("TZ", tzname, 1);
     50 }
     51 
     52 int
     53 parse_netdev(unsigned long long int *receivedabs, unsigned long long int *sentabs)
     54 {
     55 	char buf[255];
     56 	char *datastart;
     57 	static int bufsize;
     58 	int rval;
     59 	FILE *devfd;
     60 	unsigned long long int receivedacc, sentacc;
     61 
     62 	bufsize = 255;
     63 	devfd = fopen("/proc/net/dev", "r");
     64 	rval = 1;
     65 
     66 	// Ignore the first two lines of the file
     67 	fgets(buf, bufsize, devfd);
     68 	fgets(buf, bufsize, devfd);
     69 
     70 	while (fgets(buf, bufsize, devfd)) {
     71 	    if ((datastart = strstr(buf, "lo:")) == NULL) {
     72 		datastart = strstr(buf, ":");
     73 
     74 		// With thanks to the conky project at http://conky.sourceforge.net/
     75 		sscanf(datastart + 1, "%llu  %*d     %*d  %*d  %*d  %*d   %*d        %*d       %llu",\
     76 		       &receivedacc, &sentacc);
     77 		*receivedabs += receivedacc;
     78 		*sentabs += sentacc;
     79 		rval = 0;
     80 	    }
     81 	}
     82 
     83 	fclose(devfd);
     84 	return rval;
     85 }
     86 
     87 void
     88 calculate_speed(char *speedstr, unsigned long long int newval, unsigned long long int oldval)
     89 {
     90 	double speed;
     91 	speed = (newval - oldval) / 1024.0;
     92 	if (speed > 1024.0) {
     93 	    speed /= 1024.0;
     94 	    sprintf(speedstr, "%.3f MB/s", speed);
     95 	} else {
     96 	    sprintf(speedstr, "%.2f KB/s", speed);
     97 	}
     98 }
     99 
    100 char *
    101 get_netusage(unsigned long long int *rec, unsigned long long int *sent)
    102 {
    103 	unsigned long long int newrec, newsent;
    104 	newrec = newsent = 0;
    105 	char downspeedstr[15], upspeedstr[15];
    106 	static char retstr[42];
    107 	int retval;
    108 
    109 	retval = parse_netdev(&newrec, &newsent);
    110 	if (retval) {
    111 	    fprintf(stdout, "Error when parsing /proc/net/dev file.\n");
    112 	    exit(1);
    113 	}
    114 
    115 	calculate_speed(downspeedstr, newrec, *rec);
    116 	calculate_speed(upspeedstr, newsent, *sent);
    117 
    118 	sprintf(retstr, "down: %s up: %s", downspeedstr, upspeedstr);
    119 
    120 	*rec = newrec;
    121 	*sent = newsent;
    122 	return retstr;
    123 }
    124 
    125 char *
    126 mktimes(char *fmt, char *tzname)
    127 {
    128 	char buf[129];
    129 	time_t tim;
    130 	struct tm *timtm;
    131 
    132 	bzero(buf, sizeof(buf));
    133 	settz(tzname);
    134 	tim = time(NULL);
    135 	timtm = localtime(&tim);
    136 	if (timtm == NULL) {
    137 		perror("localtime");
    138 		exit(1);
    139 	}
    140 
    141 	if (!strftime(buf, sizeof(buf)-1, fmt, timtm)) {
    142 		fprintf(stderr, "strftime == 0\n");
    143 		exit(1);
    144 	}
    145 
    146 	return smprintf("%s", buf);
    147 }
    148 
    149 void
    150 setstatus(char *str)
    151 {
    152 	XStoreName(dpy, DefaultRootWindow(dpy), str);
    153 	XSync(dpy, False);
    154 }
    155 
    156 char *
    157 loadavg(void)
    158 {
    159 	double avgs[3];
    160 
    161 	if (getloadavg(avgs, 3) < 0) {
    162 		perror("getloadavg");
    163 		exit(1);
    164 	}
    165 
    166 	return smprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]);
    167 }
    168 
    169 int
    170 main(void)
    171 {
    172 	char *status;
    173 	char *avgs;
    174 	char *tmar;
    175 	char *tmutc;
    176 	char *tmbln;
    177 	char *netstats;
    178 	static unsigned long long int rec, sent;
    179 
    180 	if (!(dpy = XOpenDisplay(NULL))) {
    181 		fprintf(stderr, "dwmstatus: cannot open display.\n");
    182 		return 1;
    183 	}
    184 
    185 	parse_netdev(&rec, &sent);
    186 	for (;;sleep(1)) {
    187 		avgs = loadavg();
    188 		tmar = mktimes("%H:%M", tzargentina);
    189 		tmutc = mktimes("%H:%M", tzutc);
    190 		tmbln = mktimes("KW %W %a %d %b %H:%M %Z %Y", tzberlin);
    191 		netstats = get_netusage(&rec, &sent);
    192 
    193 		status = smprintf("[L: %s|N: %s|A: %s|U: %s|%s]",
    194 				avgs, netstats, tmar, tmutc, tmbln);
    195 		setstatus(status);
    196 		free(avgs);
    197 		free(tmar);
    198 		free(tmutc);
    199 		free(tmbln);
    200 		free(status);
    201 	}
    202 
    203 	XCloseDisplay(dpy);
    204 
    205 	return 0;
    206 }
    207