dwmstatus-netusage.c - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) 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