Xinqi Bao's Git

got rid of concat.h
[slstatus.git] / slstatus.c
1 /* See LICENSE file for copyright and license details. */
2
3 #include <err.h>
4 #include <fcntl.h>
5 #include <ifaddrs.h>
6 #include <limits.h>
7 #include <linux/wireless.h>
8 #include <locale.h>
9 #include <netdb.h>
10 #include <pwd.h>
11 #include <signal.h>
12 #include <stdarg.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/ioctl.h>
17 #include <sys/stat.h>
18 #include <sys/statvfs.h>
19 #include <sys/socket.h>
20 #include <sys/soundcard.h>
21 #include <sys/sysinfo.h>
22 #include <sys/types.h>
23 #include <sys/utsname.h>
24 #include <time.h>
25 #include <unistd.h>
26 #include <X11/Xlib.h>
27
28 #undef strlcat
29
30 #include "extern/arg.h"
31 #include "extern/strlcat.h"
32
33 struct arg {
34 char *(*func)();
35 const char *fmt;
36 const char *args;
37 };
38
39 static char *smprintf(const char *fmt, ...);
40 static char *battery_perc(const char *bat);
41 static char *battery_state(const char *bat);
42 static char *cpu_perc(void);
43 static char *datetime(const char *fmt);
44 static char *disk_free(const char *mnt);
45 static char *disk_perc(const char *mnt);
46 static char *disk_total(const char *mnt);
47 static char *disk_used(const char *mnt);
48 static char *entropy(void);
49 static char *gid(void);
50 static char *hostname(void);
51 static char *ip(const char *iface);
52 static char *kernel_release(void);
53 static char *load_avg(void);
54 static char *ram_free(void);
55 static char *ram_perc(void);
56 static char *ram_used(void);
57 static char *ram_total(void);
58 static char *run_command(const char *cmd);
59 static char *swap_free(void);
60 static char *swap_perc(void);
61 static char *swap_used(void);
62 static char *swap_total(void);
63 static char *temp(const char *file);
64 static char *uid(void);
65 static char *uptime(void);
66 static char *username(void);
67 static char *vol_perc(const char *card);
68 static char *wifi_perc(const char *iface);
69 static char *wifi_essid(const char *iface);
70 static void sighandler(const int signo);
71 static void usage(const int eval);
72
73 char *argv0;
74 static unsigned short int delay = 0;
75 static unsigned short int done;
76 static unsigned short int dflag, oflag;
77 static Display *dpy;
78
79 #include "config.h"
80
81 static char *
82 smprintf(const char *fmt, ...)
83 {
84 va_list ap;
85 char *ret;
86 int len;
87
88 va_start(ap, fmt);
89 len = vsnprintf(NULL, 0, fmt, ap);
90 va_end(ap);
91
92 ret = malloc(++len);
93 if (ret == NULL) {
94 err(1, "malloc");
95 }
96
97 va_start(ap, fmt);
98 vsnprintf(ret, len, fmt, ap);
99 va_end(ap);
100
101 return ret;
102 }
103
104 static char *
105 battery_perc(const char *bat)
106 {
107 int perc;
108 char path[PATH_MAX];
109 FILE *fp;
110
111 snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/", bat, "/capacity");
112 fp = fopen(path, "r");
113 if (fp == NULL) {
114 warn("Failed to open file %s", path);
115 return smprintf("%s", UNKNOWN_STR);
116 }
117 fscanf(fp, "%i", &perc);
118 fclose(fp);
119
120 return smprintf("%d%%", perc);
121 }
122
123 static char *
124 battery_state(const char *bat)
125 {
126 char path[PATH_MAX];
127 char state[12];
128 FILE *fp;
129
130 snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/", bat, "/status");
131 fp = fopen(path, "r");
132 if (fp == NULL) {
133 warn("Failed to open file %s", path);
134 return smprintf("%s", UNKNOWN_STR);
135 }
136 fscanf(fp, "%12s", state);
137 fclose(fp);
138
139 if (strcmp(state, "Charging") == 0) {
140 return smprintf("+");
141 } else if (strcmp(state, "Discharging") == 0) {
142 return smprintf("-");
143 } else if (strcmp(state, "Full") == 0) {
144 return smprintf("=");
145 } else {
146 return smprintf("?");
147 }
148 }
149
150 static char *
151 cpu_perc(void)
152 {
153 int perc;
154 long double a[4], b[4];
155 FILE *fp;
156
157 fp = fopen("/proc/stat", "r");
158 if (fp == NULL) {
159 warn("Failed to open file /proc/stat");
160 return smprintf("%s", UNKNOWN_STR);
161 }
162 fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &a[0], &a[1], &a[2], &a[3]);
163 fclose(fp);
164
165 delay++;
166 sleep(delay);
167
168 fp = fopen("/proc/stat", "r");
169 if (fp == NULL) {
170 warn("Failed to open file /proc/stat");
171 return smprintf("%s", UNKNOWN_STR);
172 }
173 fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &b[0], &b[1], &b[2], &b[3]);
174 fclose(fp);
175
176 perc = 100 * ((b[0]+b[1]+b[2]) - (a[0]+a[1]+a[2])) / ((b[0]+b[1]+b[2]+b[3]) - (a[0]+a[1]+a[2]+a[3]));
177 return smprintf("%d%%", perc);
178 }
179
180 static char *
181 datetime(const char *fmt)
182 {
183 time_t t;
184 char str[80];
185
186 t = time(NULL);
187 if (strftime(str, sizeof(str), fmt, localtime(&t)) == 0) {
188 return smprintf("%s", UNKNOWN_STR);
189 }
190
191 return smprintf("%s", str);
192 }
193
194 static char *
195 disk_free(const char *mnt)
196 {
197 struct statvfs fs;
198
199 if (statvfs(mnt, &fs) < 0) {
200 warn("Failed to get filesystem info");
201 return smprintf("%s", UNKNOWN_STR);
202 }
203
204 return smprintf("%f", (float)fs.f_bsize * (float)fs.f_bfree / 1024 / 1024 / 1024);
205 }
206
207 static char *
208 disk_perc(const char *mnt)
209 {
210 int perc;
211 struct statvfs fs;
212
213 if (statvfs(mnt, &fs) < 0) {
214 warn("Failed to get filesystem info");
215 return smprintf("%s", UNKNOWN_STR);
216 }
217
218 perc = 100 * (1.0f - ((float)fs.f_bfree / (float)fs.f_blocks));
219
220 return smprintf("%d%%", perc);
221 }
222
223 static char *
224 disk_total(const char *mnt)
225 {
226 struct statvfs fs;
227
228 if (statvfs(mnt, &fs) < 0) {
229 warn("Failed to get filesystem info");
230 return smprintf("%s", UNKNOWN_STR);
231 }
232
233 return smprintf("%f", (float)fs.f_bsize * (float)fs.f_blocks / 1024 / 1024 / 1024);
234 }
235
236 static char *
237 disk_used(const char *mnt)
238 {
239 struct statvfs fs;
240
241 if (statvfs(mnt, &fs) < 0) {
242 warn("Failed to get filesystem info");
243 return smprintf("%s", UNKNOWN_STR);
244 }
245
246 return smprintf("%f", (float)fs.f_bsize * ((float)fs.f_blocks - (float)fs.f_bfree) / 1024 / 1024 / 1024);
247 }
248
249 static char *
250 entropy(void)
251 {
252 int num;
253 FILE *fp;
254
255 fp= fopen("/proc/sys/kernel/random/entropy_avail", "r");
256 if (fp == NULL) {
257 warn("Failed to open file /proc/sys/kernel/random/entropy_avail");
258 return smprintf("%s", UNKNOWN_STR);
259 }
260 fscanf(fp, "%d", &num);
261 fclose(fp);
262
263 return smprintf("%d", num);
264 }
265
266 static char *
267 gid(void)
268 {
269 return smprintf("%d", getgid());
270 }
271
272 static char *
273 hostname(void)
274 {
275 char buf[HOST_NAME_MAX];
276
277 if (gethostname(buf, sizeof(buf)) == -1) {
278 warn("hostname");
279 return smprintf("%s", UNKNOWN_STR);
280 }
281
282 return smprintf("%s", buf);
283 }
284
285 static char *
286 ip(const char *iface)
287 {
288 struct ifaddrs *ifaddr, *ifa;
289 int s;
290 char host[NI_MAXHOST];
291
292 if (getifaddrs(&ifaddr) == -1) {
293 warn("Failed to get IP address for interface %s", iface);
294 return smprintf("%s", UNKNOWN_STR);
295 }
296
297 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
298 if (ifa->ifa_addr == NULL) {
299 continue;
300 }
301 s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
302 if ((strcmp(ifa->ifa_name, iface) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
303 if (s != 0) {
304 warnx("Failed to get IP address for interface %s", iface);
305 return smprintf("%s", UNKNOWN_STR);
306 }
307 return smprintf("%s", host);
308 }
309 }
310
311 freeifaddrs(ifaddr);
312
313 return smprintf("%s", UNKNOWN_STR);
314 }
315
316 static char *
317 kernel_release(void)
318 {
319 struct utsname udata;
320
321 if (uname(&udata) < 0) {
322 return smprintf(UNKNOWN_STR);
323 }
324
325 return smprintf("%s", udata.release);
326 }
327
328 static char *
329 load_avg(void)
330 {
331 double avgs[3];
332
333 if (getloadavg(avgs, 3) < 0) {
334 warnx("Failed to get the load avg");
335 return smprintf("%s", UNKNOWN_STR);
336 }
337
338 return smprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]);
339 }
340
341 static char *
342 ram_free(void)
343 {
344 long free;
345 FILE *fp;
346
347 fp = fopen("/proc/meminfo", "r");
348 if (fp == NULL) {
349 warn("Failed to open file /proc/meminfo");
350 return smprintf("%s", UNKNOWN_STR);
351 }
352 fscanf(fp, "MemFree: %ld kB\n", &free);
353 fclose(fp);
354
355 return smprintf("%f", (float)free / 1024 / 1024);
356 }
357
358 static char *
359 ram_perc(void)
360 {
361 long total, free, buffers, cached;
362 FILE *fp;
363
364 fp = fopen("/proc/meminfo", "r");
365 if (fp == NULL) {
366 warn("Failed to open file /proc/meminfo");
367 return smprintf("%s", UNKNOWN_STR);
368 }
369 fscanf(fp, "MemTotal: %ld kB\n", &total);
370 fscanf(fp, "MemFree: %ld kB\n", &free);
371 fscanf(fp, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers, &buffers);
372 fscanf(fp, "Cached: %ld kB\n", &cached);
373 fclose(fp);
374
375 return smprintf("%d%%", 100 * ((total - free) - (buffers + cached)) / total);
376 }
377
378 static char *
379 ram_total(void)
380 {
381 long total;
382 FILE *fp;
383
384 fp = fopen("/proc/meminfo", "r");
385 if (fp == NULL) {
386 warn("Failed to open file /proc/meminfo");
387 return smprintf("%s", UNKNOWN_STR);
388 }
389 fscanf(fp, "MemTotal: %ld kB\n", &total);
390 fclose(fp);
391
392 return smprintf("%f", (float)total / 1024 / 1024);
393 }
394
395 static char *
396 ram_used(void)
397 {
398 long free, total, buffers, cached;
399 FILE *fp;
400
401 fp = fopen("/proc/meminfo", "r");
402 if (fp == NULL) {
403 warn("Failed to open file /proc/meminfo");
404 return smprintf("%s", UNKNOWN_STR);
405 }
406 fscanf(fp, "MemTotal: %ld kB\n", &total);
407 fscanf(fp, "MemFree: %ld kB\n", &free);
408 fscanf(fp, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers, &buffers);
409 fscanf(fp, "Cached: %ld kB\n", &cached);
410 fclose(fp);
411
412 return smprintf("%f", (float)(total - free - buffers - cached) / 1024 / 1024);
413 }
414
415 static char *
416 run_command(const char *cmd)
417 {
418 char *nlptr;
419 FILE *fp;
420 char buf[1024] = UNKNOWN_STR;
421
422 fp = popen(cmd, "r");
423 if (fp == NULL) {
424 warn("Failed to get command output for %s", cmd);
425 return smprintf("%s", UNKNOWN_STR);
426 }
427 fgets(buf, sizeof(buf), fp);
428 pclose(fp);
429 buf[sizeof(buf)] = '\0';
430
431 if ((nlptr = strstr(buf, "\n")) != NULL) {
432 nlptr[0] = '\0';
433 }
434
435 return smprintf("%s", buf);
436 }
437
438 static char *
439 swap_free(void)
440 {
441 long total, free;
442 FILE *fp;
443 char buf[2048];
444 size_t bytes_read;
445 char *match;
446
447 fp = fopen("/proc/meminfo", "r");
448 if (fp == NULL) {
449 warn("Failed to open file /proc/meminfo");
450 return smprintf("%s", UNKNOWN_STR);
451 }
452
453 if ((bytes_read = fread(buf, sizeof(char), sizeof(buf), fp)) == 0) {
454 warn("swap_free: read error");
455 fclose(fp);
456 return smprintf("%s", UNKNOWN_STR);
457 }
458
459 buf[bytes_read] = '\0';
460 fclose(fp);
461
462 if ((match = strstr(buf, "SwapTotal")) == NULL) {
463 return smprintf("%s", UNKNOWN_STR);
464 }
465 sscanf(match, "SwapTotal: %ld kB\n", &total);
466
467 if ((match = strstr(buf, "SwapFree")) == NULL) {
468 return smprintf("%s", UNKNOWN_STR);
469 }
470 sscanf(match, "SwapFree: %ld kB\n", &free);
471
472 return smprintf("%f", (float)free / 1024 / 1024);
473 }
474
475 static char *
476 swap_perc(void)
477 {
478 long total, free, cached;
479 FILE *fp;
480 char buf[2048];
481 size_t bytes_read;
482 char *match;
483
484 fp = fopen("/proc/meminfo", "r");
485 if (fp == NULL) {
486 warn("Failed to open file /proc/meminfo");
487 return smprintf("%s", UNKNOWN_STR);
488 }
489
490 if ((bytes_read = fread(buf, sizeof(char), sizeof(buf), fp)) == 0) {
491 warn("swap_perc: read error");
492 fclose(fp);
493 return smprintf("%s", UNKNOWN_STR);
494 }
495
496 buf[bytes_read] = '\0';
497 fclose(fp);
498
499 if ((match = strstr(buf, "SwapTotal")) == NULL) {
500 return smprintf("%s", UNKNOWN_STR);
501 }
502 sscanf(match, "SwapTotal: %ld kB\n", &total);
503
504 if ((match = strstr(buf, "SwapCached")) == NULL) {
505 return smprintf("%s", UNKNOWN_STR);
506 }
507 sscanf(match, "SwapCached: %ld kB\n", &cached);
508
509 if ((match = strstr(buf, "SwapFree")) == NULL) {
510 return smprintf("%s", UNKNOWN_STR);
511 }
512 sscanf(match, "SwapFree: %ld kB\n", &free);
513
514 return smprintf("%d%%", 100 * (total - free - cached) / total);
515 }
516
517 static char *
518 swap_total(void)
519 {
520 long total;
521 FILE *fp;
522 char buf[2048];
523 size_t bytes_read;
524 char *match;
525
526 fp = fopen("/proc/meminfo", "r");
527 if (fp == NULL) {
528 warn("Failed to open file /proc/meminfo");
529 return smprintf("%s", UNKNOWN_STR);
530 }
531 if ((bytes_read = fread(buf, sizeof(char), sizeof(buf), fp)) == 0) {
532 warn("swap_total: read error");
533 fclose(fp);
534 return smprintf("%s", UNKNOWN_STR);
535 }
536
537 buf[bytes_read] = '\0';
538 fclose(fp);
539
540 if ((match = strstr(buf, "SwapTotal")) == NULL) {
541 return smprintf("%s", UNKNOWN_STR);
542 }
543 sscanf(match, "SwapTotal: %ld kB\n", &total);
544
545 return smprintf("%f", (float)total / 1024 / 1024);
546 }
547
548 static char *
549 swap_used(void)
550 {
551 long total, free, cached;
552 FILE *fp;
553 char buf[2048];
554 size_t bytes_read;
555 char *match;
556
557 fp = fopen("/proc/meminfo", "r");
558 if (fp == NULL) {
559 warn("Failed to open file /proc/meminfo");
560 return smprintf("%s", UNKNOWN_STR);
561 }
562 if ((bytes_read = fread(buf, sizeof(char), sizeof(buf), fp)) == 0) {
563 warn("swap_used: read error");
564 fclose(fp);
565 return smprintf("%s", UNKNOWN_STR);
566 }
567
568 buf[bytes_read] = '\0';
569 fclose(fp);
570
571 if ((match = strstr(buf, "SwapTotal")) == NULL) {
572 return smprintf("%s", UNKNOWN_STR);
573 }
574 sscanf(match, "SwapTotal: %ld kB\n", &total);
575
576 if ((match = strstr(buf, "SwapCached")) == NULL) {
577 return smprintf("%s", UNKNOWN_STR);
578 }
579 sscanf(match, "SwapCached: %ld kB\n", &cached);
580
581 if ((match = strstr(buf, "SwapFree")) == NULL) {
582 return smprintf("%s", UNKNOWN_STR);
583 }
584 sscanf(match, "SwapFree: %ld kB\n", &free);
585
586 return smprintf("%f", (float)(total - free - cached) / 1024 / 1024);
587 }
588
589 static char *
590 temp(const char *file)
591 {
592 int temp;
593 FILE *fp;
594
595 fp = fopen(file, "r");
596 if (fp == NULL) {
597 warn("Failed to open file %s", file);
598 return smprintf("%s", UNKNOWN_STR);
599 }
600 fscanf(fp, "%d", &temp);
601 fclose(fp);
602
603 return smprintf("%d°C", temp / 1000);
604 }
605
606 static char *
607 uptime(void)
608 {
609 struct sysinfo info;
610 int h = 0;
611 int m = 0;
612
613 sysinfo(&info);
614 h = info.uptime / 3600;
615 m = (info.uptime - h * 3600 ) / 60;
616
617 return smprintf("%dh %dm", h, m);
618 }
619
620 static char *
621 username(void)
622 {
623 uid_t uid = geteuid();
624 struct passwd *pw = getpwuid(uid);
625
626 if (pw == NULL) {
627 warn("Failed to get username");
628 return smprintf("%s", UNKNOWN_STR);
629 }
630
631 return smprintf("%s", pw->pw_name);
632 }
633
634 static char *
635 uid(void)
636 {
637 return smprintf("%d", geteuid());
638 }
639
640
641 static char *
642 vol_perc(const char *card)
643 {
644 unsigned int i;
645 int v, afd, devmask;
646 char *vnames[] = SOUND_DEVICE_NAMES;
647
648 afd = open(card, O_RDONLY);
649 if (afd < 0) {
650 warn("Cannot open %s", card);
651 return smprintf(UNKNOWN_STR);
652 }
653
654 ioctl(afd, MIXER_READ(SOUND_MIXER_DEVMASK), &devmask);
655 for (i = 0; i < (sizeof(vnames) / sizeof((vnames[0]))); i++) {
656 if (devmask & (1 << i)) {
657 if (!strcmp("vol", vnames[i])) {
658 ioctl(afd, MIXER_READ(i), &v);
659 }
660 }
661 }
662
663 close(afd);
664 if (v == 0) {
665 return smprintf("mute");
666 }
667 return smprintf("%d%%", v & 0xff);
668 }
669
670 static char *
671 wifi_perc(const char *iface)
672 {
673 int perc;
674 char buf[255];
675 char *datastart;
676 char path[PATH_MAX];
677 char status[5];
678 FILE *fp;
679
680 snprintf(path, sizeof(path), "%s%s%s", "/sys/class/net/", iface, "/operstate");
681 fp = fopen(path, "r");
682 if (fp == NULL) {
683 warn("Failed to open file %s", path);
684 return smprintf("%s", UNKNOWN_STR);
685 }
686 fgets(status, 5, fp);
687 fclose(fp);
688 if(strcmp(status, "up\n") != 0) {
689 return smprintf("%s", UNKNOWN_STR);
690 }
691
692 fp = fopen("/proc/net/wireless", "r");
693 if (fp == NULL) {
694 warn("Failed to open file /proc/net/wireless");
695 return smprintf("%s", UNKNOWN_STR);
696 }
697
698 fgets(buf, sizeof(buf), fp);
699 fgets(buf, sizeof(buf), fp);
700 fgets(buf, sizeof(buf), fp);
701 fclose(fp);
702
703 if ((datastart = strstr(buf, iface)) == NULL) {
704 return smprintf("%s", UNKNOWN_STR);
705 }
706 datastart = (datastart+(strlen(iface)+1));
707 sscanf(datastart + 1, " %*d %d %*d %*d %*d %*d %*d %*d %*d %*d", &perc);
708
709 return smprintf("%d%%", perc);
710 }
711
712 static char *
713 wifi_essid(const char *iface)
714 {
715 char id[IW_ESSID_MAX_SIZE+1];
716 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
717 struct iwreq wreq;
718
719 memset(&wreq, 0, sizeof(struct iwreq));
720 wreq.u.essid.length = IW_ESSID_MAX_SIZE+1;
721 snprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s", iface);
722
723 if (sockfd == -1) {
724 warn("Failed to get ESSID for interface %s", iface);
725 return smprintf("%s", UNKNOWN_STR);
726 }
727 wreq.u.essid.pointer = id;
728 if (ioctl(sockfd,SIOCGIWESSID, &wreq) == -1) {
729 warn("Failed to get ESSID for interface %s", iface);
730 return smprintf("%s", UNKNOWN_STR);
731 }
732
733 close(sockfd);
734
735 if (strcmp((char *)wreq.u.essid.pointer, "") == 0)
736 return smprintf("%s", UNKNOWN_STR);
737 else
738 return smprintf("%s", (char *)wreq.u.essid.pointer);
739 }
740
741 static void
742 sighandler(const int signo)
743 {
744 if (signo == SIGTERM || signo == SIGINT) {
745 done = 1;
746 }
747 }
748
749 static void
750 usage(const int eval)
751 {
752 fprintf(stderr, "usage: %s [-d] [-o] [-v] [-h]\n", argv0);
753 exit(eval);
754 }
755
756 int
757 main(int argc, char *argv[])
758 {
759 unsigned short int i;
760 char status_string[2048];
761 char *res, *element;
762 struct arg argument;
763 struct sigaction act;
764
765 ARGBEGIN {
766 case 'd':
767 dflag = 1;
768 break;
769 case 'o':
770 oflag = 1;
771 break;
772 case 'v':
773 printf("slstatus (C) 2016-2017 slstatus engineers\n");
774 return 0;
775 case 'h':
776 usage(0);
777 default:
778 usage(1);
779 } ARGEND
780
781 if (dflag && oflag) {
782 usage(1);
783 }
784 if (dflag && daemon(1, 1) < 0) {
785 err(1, "daemon");
786 }
787
788 memset(&act, 0, sizeof(act));
789 act.sa_handler = sighandler;
790 sigaction(SIGINT, &act, 0);
791 sigaction(SIGTERM, &act, 0);
792
793 if (!oflag) {
794 dpy = XOpenDisplay(NULL);
795 }
796
797 setlocale(LC_ALL, "");
798
799 while (!done) {
800 status_string[0] = '\0';
801
802 for (i = 0; i < sizeof(args) / sizeof(args[0]); ++i) {
803 argument = args[i];
804 if (argument.args == NULL) {
805 res = argument.func();
806 } else {
807 res = argument.func(argument.args);
808 }
809 element = smprintf(argument.fmt, res);
810 if (element == NULL) {
811 element = smprintf("%s", UNKNOWN_STR);
812 warnx("Failed to format output");
813 }
814 if (strlcat(status_string, element, sizeof(status_string)) >= sizeof(status_string)) {
815 warnx("Output too long");
816 }
817 free(res);
818 free(element);
819 }
820
821 if (!oflag) {
822 XStoreName(dpy, DefaultRootWindow(dpy), status_string);
823 XSync(dpy, False);
824 } else {
825 printf("%s\n", status_string);
826 }
827
828 if ((UPDATE_INTERVAL - delay) <= 0) {
829 delay = 0;
830 continue;
831 } else {
832 sleep(UPDATE_INTERVAL - delay);
833 delay = 0;
834 }
835 }
836
837 if (!oflag) {
838 XStoreName(dpy, DefaultRootWindow(dpy), NULL);
839 XCloseDisplay(dpy);
840 }
841
842 return 0;
843 }