sites

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

diskspace_timechk.c (7336B)


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