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