sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | 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