dynamic_info.c - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dynamic_info.c (8861B)
       ---
            1 #define _BSD_SOURCE
            2 #define _GNU_SOURCE
            3 #include <unistd.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 <dirent.h>
           13 #include <sys/statvfs.h>
           14 
           15 
           16 #include <X11/Xlib.h>
           17 
           18 char *tzparis = "Europe/Paris";
           19 
           20 static Display *dpy;
           21 
           22 char *
           23 smprintf(char *fmt, ...)
           24 {
           25         va_list fmtargs;
           26         char *buf = NULL;
           27 
           28         va_start(fmtargs, fmt);
           29         if (vasprintf(&buf, fmt, fmtargs) == -1){
           30                 fprintf(stderr, "malloc vasprintf\n");
           31                 exit(1);
           32     }
           33         va_end(fmtargs);
           34 
           35         return buf;
           36 }
           37 
           38 char*
           39 runcmd(char* cmd) {
           40         FILE* fp = popen(cmd, "r");
           41         if (fp == NULL) return NULL;
           42         char ln[50];
           43         fgets(ln, sizeof(ln)-1, fp);
           44         pclose(fp);
           45         ln[strlen(ln)-1]='\0';
           46         return smprintf("%s", ln);
           47 }
           48 
           49 void
           50 settz(char *tzname)
           51 {
           52         setenv("TZ", tzname, 1);
           53 }
           54 
           55 char *
           56 mktimes(char *fmt, char *tzname)
           57 {
           58         char buf[129];
           59         time_t tim;
           60         struct tm *timtm;
           61 
           62         memset(buf, 0, sizeof(buf));
           63         settz(tzname);
           64         tim = time(NULL);
           65         timtm = localtime(&tim);
           66         if (timtm == NULL) {
           67                 perror("localtime");
           68                 exit(1);
           69         }
           70 
           71         if (!strftime(buf, sizeof(buf)-1, fmt, timtm)) {
           72                 fprintf(stderr, "strftime == 0\n");
           73                 exit(1);
           74         }
           75 
           76         return smprintf(buf);
           77 }
           78 
           79 void
           80 setstatus(char *str)
           81 {
           82         XStoreName(dpy, DefaultRootWindow(dpy), str);
           83         XSync(dpy, False);
           84 }
           85 
           86 char *
           87 loadavg(void)
           88 {
           89         double avgs[3];
           90 
           91         if (getloadavg(avgs, 3) < 0) {
           92                 perror("getloadavg");
           93                 exit(1);
           94         }
           95 
           96         return smprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]);
           97 }
           98 
           99 int
          100 getvolume() {
          101         int volume;
          102         sscanf(runcmd("amixer | grep -A 6 Master | grep 'Mono: Playback'\
          103                         | grep -o '[0-9%]*%'"), "%i%%", &volume);
          104         return volume;
          105 
          106 }
          107 
          108 char *
          109 getmpdstat() {
          110     return runcmd("/home/xavier/.Scripts/xfcebar.sh");
          111 
          112 }
          113 
          114 char *
          115 readfile(char *base, char *file)
          116 {
          117         char *path, line[513];
          118         FILE *fd;
          119 
          120         memset(line, 0, sizeof(line));
          121 
          122         path = smprintf("%s/%s", base, file);
          123         fd = fopen(path, "r");
          124         if (fd == NULL)
          125                 return NULL;
          126         free(path);
          127 
          128         if (fgets(line, sizeof(line)-1, fd) == NULL)
          129                 return NULL;
          130         fclose(fd);
          131 
          132         return smprintf("%s", line);
          133 }
          134 
          135 
          136 char *
          137 tmpinfo()
          138 {
          139     /* usr path as a buffer for any text */
          140     char *path = "/tmp/dwmbuf";
          141     char line[255];
          142     char *toprint = NULL;
          143         FILE *fin;
          144         FILE *fout;
          145         int c = 0;
          146 
          147         fin = fopen(path, "r");
          148         if (fin == NULL)
          149         return(smprintf("%s"," "));
          150 
          151         fout = fopen("/tmp/.dwmbuf.tmp", "w");
          152         if (fout == NULL)
          153     {
          154         fclose(fin);
          155         return(smprintf("%s"," "));
          156     }
          157 
          158     while (fgets(line, sizeof(line), fin))
          159     {
          160         if (c == 0)
          161             line[strlen(line)-1]='\0';
          162             toprint = smprintf("%s",line);
          163         if (c > 0)
          164             fputs(line, fout);
          165         c += 1;
          166     }
          167 
          168     fclose(fin);
          169     fclose(fout);
          170 
          171     rename("/tmp/.dwmbuf.tmp", path);
          172 
          173     if (toprint != NULL)
          174         return(smprintf("%s",toprint));
          175     else
          176         return(smprintf("%s"," "));
          177 }
          178 
          179 /*
          180  * Linux seems to change the filenames after suspend/hibernate
          181  * according to a random scheme. So just check for both possibilities.
          182  */
          183 char *
          184 getbattery(char *base)
          185 {
          186         char *co;
          187         int descap, remcap;
          188 
          189         descap = -1;
          190         remcap = -1;
          191 
          192         co = readfile(base, "present");
          193         if (co == NULL || co[0] != '1') {
          194                 if (co != NULL) free(co);
          195                 return smprintf("?");
          196         }
          197         free(co);
          198 
          199         co = readfile(base, "charge_full_design");
          200         if (co == NULL) {
          201                 co = readfile(base, "energy_full_design");
          202                 if (co == NULL)
          203                         return smprintf("");
          204         }
          205         sscanf(co, "%d", &descap);
          206         free(co);
          207 
          208         co = readfile(base, "charge_now");
          209         if (co == NULL) {
          210                 co = readfile(base, "energy_now");
          211                 if (co == NULL)
          212                         return smprintf("");
          213         }
          214         sscanf(co, "%d", &remcap);
          215         free(co);
          216 
          217         if (remcap < 0 || descap < 0)
          218                 return smprintf("invalid");
          219 
          220         return smprintf("%.0f", ((float)remcap / (float)descap) * 100);
          221 }
          222 
          223 int
          224 parse_netdev(unsigned long long int *receivedabs, unsigned long long int *sentabs)
          225 {
          226         char *buf;
          227         char *eth0start;
          228         static int bufsize;
          229         FILE *devfd;
          230 
          231         buf = (char *) calloc(255, 1);
          232         bufsize = 255;
          233         devfd = fopen("/proc/net/dev", "r");
          234 
          235         // ignore the first two lines of the file
          236         fgets(buf, bufsize, devfd);
          237         fgets(buf, bufsize, devfd);
          238 
          239         while (fgets(buf, bufsize, devfd)) {
          240             if ((eth0start = strstr(buf, "wlan0:")) != NULL) {
          241 
          242                 // With thanks to the conky project at http://conky.sourceforge.net/
          243                 sscanf(eth0start + 6, "%llu  %*d     %*d  %*d  %*d  %*d   %*d        %*d       %llu",\
          244                        receivedabs, sentabs);
          245                 fclose(devfd);
          246                 free(buf);
          247                 return 0;
          248             }
          249         }
          250     fclose(devfd);
          251         free(buf);
          252         return 1;
          253 }
          254 
          255 char *
          256 get_netusage()
          257 {
          258         unsigned long long int oldrec, oldsent, newrec, newsent;
          259         double downspeed, upspeed;
          260         char *downspeedstr, *upspeedstr;
          261         char *retstr;
          262         int retval;
          263 
          264         downspeedstr = (char *) malloc(15);
          265         upspeedstr = (char *) malloc(15);
          266         retstr = (char *) malloc(42);
          267 
          268         retval = parse_netdev(&oldrec, &oldsent);
          269         if (retval) {
          270             fprintf(stdout, "Error when parsing /proc/net/dev file.\n");
          271             exit(1);
          272         }
          273 
          274         sleep(1);
          275         retval = parse_netdev(&newrec, &newsent);
          276         if (retval) {
          277             fprintf(stdout, "Error when parsing /proc/net/dev file.\n");
          278             exit(1);
          279         }
          280 
          281         downspeed = (newrec - oldrec) / 1024.0;
          282         if (downspeed > 1024.0) {
          283             downspeed /= 1024.0;
          284             sprintf(downspeedstr, "%.3f MB/s", downspeed);
          285         } else {
          286             sprintf(downspeedstr, "%.2f KB/s", downspeed);
          287         }
          288 
          289         upspeed = (newsent - oldsent) / 1024.0;
          290         if (upspeed > 1024.0) {
          291             upspeed /= 1024.0;
          292             sprintf(upspeedstr, "%.3f MB/s", upspeed);
          293         } else {
          294             sprintf(upspeedstr, "%.2f KB/s", upspeed);
          295         }
          296         sprintf(retstr, "D: %s U: %s", downspeedstr, upspeedstr);
          297 
          298         free(downspeedstr);
          299         free(upspeedstr);
          300         return retstr;
          301 }
          302 
          303 char *get_nmail(char *directory, char *label)
          304 {
          305     /* directory : Maildir path 
          306     * return label : number_of_new_mails
          307     */
          308     
          309     int n = 0;
          310     DIR* dir = NULL;
          311     struct dirent* rf = NULL;
          312 
          313     dir = opendir(directory); /* try to open directory */
          314     if (dir == NULL)
          315         perror("");
          316 
          317     while ((rf = readdir(dir)) != NULL) /*count number of file*/
          318     {
          319         if (strcmp(rf->d_name, ".") != 0 &&
          320             strcmp(rf->d_name, "..") != 0)
          321             n++;
          322     }
          323     closedir(dir);
          324 
          325     if (n == 0) 
          326        return smprintf("");
          327     else 
          328        return smprintf("%s%d",label, n);
          329 
          330 }
          331 
          332 int runevery(time_t *ltime, int sec){
          333     /* return 1 if sec elapsed since last run
          334      * else return 0 
          335     */
          336     time_t now = time(NULL);
          337     
          338     if ( difftime(now, *ltime ) >= sec)
          339     {
          340         *ltime = now;
          341         return(1);
          342     }
          343     else 
          344         return(0);
          345 }
          346 
          347 char *get_freespace(char *mntpt){
          348     struct statvfs data;
          349     double total, used = 0;
          350 
          351     if ( (statvfs(mntpt, &data)) < 0){
          352                 fprintf(stderr, "can't get info on disk.\n");
          353                 return("?");
          354     }
          355     total = (data.f_blocks * data.f_frsize);
          356     used = (data.f_blocks - data.f_bfree) * data.f_frsize ;
          357     return(smprintf("%.1f", (used/total*100)));
          358 }
          359 
          360 
          361 int
          362 main(void)
          363 {
          364         char *status = NULL;
          365         char *avgs = NULL;
          366         char *tmprs = NULL;
          367     char *bat = NULL;
          368     //char *netstats = NULL;
          369     char *mail_laposte = NULL;
          370     char *mail_fac = NULL;
          371     char *mail_lavabit = NULL;
          372     char *mail_tl = NULL;
          373     char *rootfs = NULL;
          374     char *homefs = NULL;
          375     time_t count5min = 0;
          376     time_t count60 = 0;
          377     time_t count5 = 0;
          378     int volume = 0;
          379     char *mpd = NULL;
          380     char *info = NULL;
          381     
          382         if (!(dpy = XOpenDisplay(NULL))) {
          383                 fprintf(stderr, "dwmstatus: cannot open display.\n");
          384                 return 1;
          385         }
          386 
          387         for (;;sleep(1)) {
          388             /* checks every minutes */
          389             if ( runevery(&count60, 60) )
          390         {
          391             free(tmprs);
          392             free(bat);
          393             free(info);
          394             tmprs = mktimes("%d/%m/%y %H:%M", tzparis);
          395             bat = getbattery("/sys/class/power_supply/BAT0/");
          396             info = tmpinfo();
          397         }
          398         if (runevery(&count5, 5)){
          399             free(homefs);
          400             free(rootfs);
          401             homefs = get_freespace("/home");
          402             rootfs = get_freespace("/");
          403         }
          404         /* checks mail every 5 minutes */
          405         if (runevery(&count5min, 300) )
          406         {
          407             free(mail_laposte);
          408             free(mail_fac);
          409             free(mail_lavabit);
          410             free(mail_tl);
          411             mail_laposte = get_nmail("/home/xavier/Maildir/fac/new", " Fac:");
          412             mail_fac = get_nmail("/home/xavier/Maildir/lavabit/new", " Lavabit:");
          413             mail_lavabit = get_nmail("/home/xavier/Maildir/toilelibre/new", " TL:");
          414             mail_tl = get_nmail("/home/xavier/Maildir/laposte/new", " Laposte:");
          415         }
          416         /* checks every second */
          417                 avgs = loadavg();
          418         //netstats = get_netusage();
          419         volume = getvolume();
          420         mpd = getmpdstat();
          421 
          422                 status = smprintf("%s %s %s%s%s%s | /:%s% /home:%s% | B:%s% | %s | V:%i%% | %s",
          423                          info, mpd,
          424                                  mail_tl, mail_fac, mail_lavabit, mail_laposte,
          425                                  rootfs, homefs, bat, avgs, volume, tmprs);
          426                 setstatus(status);
          427                 free(avgs);
          428         free(mpd);
          429                 free(status);
          430         }
          431 
          432         XCloseDisplay(dpy);
          433 
          434         return 0;
          435 }
          436