dynamic_info.c - 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… | |
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.sour… | |
243 sscanf(eth0start + 6, "%llu %*d %*d %*d %*d %*d … | |
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", " F… | |
412 mail_fac = get_nmail("/home/xavier/Maildir/lavabit/new", " L… | |
413 mail_lavabit = get_nmail("/home/xavier/Maildir/toilelibre/ne… | |
414 mail_tl = get_nmail("/home/xavier/Maildir/laposte/new", " La… | |
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:… | |
423 info, mpd, | |
424 mail_tl, mail_fac, mail_lavabit, mail_l… | |
425 rootfs, homefs, bat, avgs, volume, tmpr… | |
426 setstatus(status); | |
427 free(avgs); | |
428 free(mpd); | |
429 free(status); | |
430 } | |
431 | |
432 XCloseDisplay(dpy); | |
433 | |
434 return 0; | |
435 } | |
436 |