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