Xinqi Bao's Git

run_command: strlen() will not function if string is not null terminated
[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 #include "extern/concat.h"
33
34 struct arg {
35 char *(*func)();
36 const char *fmt;
37 const char *args;
38 };
39
40 static char *smprintf(const char *fmt, ...);
41 static char *battery_perc(const char *bat);
42 static char *battery_state(const char *bat);
43 static char *cpu_perc(void);
44 static char *datetime(const char *fmt);
45 static char *disk_free(const char *mnt);
46 static char *disk_perc(const char *mnt);
47 static char *disk_total(const char *mnt);
48 static char *disk_used(const char *mnt);
49 static char *entropy(void);
50 static char *gid(void);
51 static char *hostname(void);
52 static char *ip(const char *iface);
53 static char *kernel_release(void);
54 static char *load_avg(void);
55 static char *ram_free(void);
56 static char *ram_perc(void);
57 static char *ram_used(void);
58 static char *ram_total(void);
59 static char *run_command(const char *cmd);
60 static char *swap_free(void);
61 static char *swap_perc(void);
62 static char *swap_used(void);
63 static char *swap_total(void);
64 static char *temp(const char *file);
65 static char *uid(void);
66 static char *uptime(void);
67 static char *username(void);
68 static char *vol_perc(const char *card);
69 static char *wifi_perc(const char *iface);
70 static char *wifi_essid(const char *iface);
71 static void sighandler(const int signo);
72 static void usage(const int eval);
73
74 char *argv0;
75 char concat[];
76 static unsigned short int delay = 0;
77 static unsigned short int done;
78 static unsigned short int dflag, oflag;
79 static Display *dpy;
80
81 #include "config.h"
82
83 static char *
84 smprintf(const char *fmt, ...)
85 {
86 va_list ap;
87 char *ret;
88 int len;
89
90 va_start(ap, fmt);
91 len = vsnprintf(NULL, 0, fmt, ap);
92 va_end(ap);
93
94 ret = malloc(++len);
95 if (ret == NULL) {
96 err(1, "malloc");
97 }
98
99 va_start(ap, fmt);
100 vsnprintf(ret, len, fmt, ap);
101 va_end(ap);
102
103 return ret;
104 }
105
106 static char *
107 battery_perc(const char *bat)
108 {
109 int perc;
110 FILE *fp;
111
112 ccat(3, "/sys/class/power_supply/", bat, "/capacity");
113 fp = fopen(concat, "r");
114 if (fp == NULL) {
115 warn("Failed to open file %s", concat);
116 return smprintf("%s", UNKNOWN_STR);
117 }
118 fscanf(fp, "%i", &perc);
119 fclose(fp);
120
121 return smprintf("%d%%", perc);
122 }
123
124 static char *
125 battery_state(const char *bat)
126 {
127 char state[12];
128 FILE *fp;
129
130 ccat(3, "/sys/class/power_supply/", bat, "/status");
131 fp = fopen(concat, "r");
132 if (fp == NULL) {
133 warn("Failed to open file %s", concat);
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 status[5];
677 FILE *fp;
678
679 ccat(3, "/sys/class/net/", iface, "/operstate");
680 fp = fopen(concat, "r");
681 if (fp == NULL) {
682 warn("Failed to open file %s", concat);
683 return smprintf("%s", UNKNOWN_STR);
684 }
685 fgets(status, 5, fp);
686 fclose(fp);
687 if(strcmp(status, "up\n") != 0) {
688 return smprintf("%s", UNKNOWN_STR);
689 }
690
691 fp = fopen("/proc/net/wireless", "r");
692 if (fp == NULL) {
693 warn("Failed to open file /proc/net/wireless");
694 return smprintf("%s", UNKNOWN_STR);
695 }
696 ccat(2, iface, ":");
697 fgets(buf, sizeof(buf), fp);
698 fgets(buf, sizeof(buf), fp);
699 fgets(buf, sizeof(buf), fp);
700 fclose(fp);
701
702 if ((datastart = strstr(buf, concat)) == NULL) {
703 return smprintf("%s", UNKNOWN_STR);
704 }
705 datastart = (datastart+(strlen(iface)+1));
706 sscanf(datastart + 1, " %*d %d %*d %*d %*d %*d %*d %*d %*d %*d", &perc);
707
708 return smprintf("%d%%", perc);
709 }
710
711 static char *
712 wifi_essid(const char *iface)
713 {
714 char id[IW_ESSID_MAX_SIZE+1];
715 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
716 struct iwreq wreq;
717
718 memset(&wreq, 0, sizeof(struct iwreq));
719 wreq.u.essid.length = IW_ESSID_MAX_SIZE+1;
720 snprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s", iface);
721
722 if (sockfd == -1) {
723 warn("Failed to get ESSID for interface %s", iface);
724 return smprintf("%s", UNKNOWN_STR);
725 }
726 wreq.u.essid.pointer = id;
727 if (ioctl(sockfd,SIOCGIWESSID, &wreq) == -1) {
728 warn("Failed to get ESSID for interface %s", iface);
729 return smprintf("%s", UNKNOWN_STR);
730 }
731
732 close(sockfd);
733
734 if (strcmp((char *)wreq.u.essid.pointer, "") == 0)
735 return smprintf("%s", UNKNOWN_STR);
736 else
737 return smprintf("%s", (char *)wreq.u.essid.pointer);
738 }
739
740 static void
741 sighandler(const int signo)
742 {
743 if (signo == SIGTERM || signo == SIGINT) {
744 done = 1;
745 }
746 }
747
748 static void
749 usage(const int eval)
750 {
751 fprintf(stderr, "usage: %s [-d] [-o] [-v] [-h]\n", argv0);
752 exit(eval);
753 }
754
755 int
756 main(int argc, char *argv[])
757 {
758 unsigned short int i;
759 char status_string[2048];
760 char *res, *element;
761 struct arg argument;
762 struct sigaction act;
763
764 ARGBEGIN {
765 case 'd':
766 dflag = 1;
767 break;
768 case 'o':
769 oflag = 1;
770 break;
771 case 'v':
772 printf("slstatus (C) 2016 slstatus engineers\n");
773 return 0;
774 case 'h':
775 usage(0);
776 default:
777 usage(1);
778 } ARGEND
779
780 if (dflag && oflag) {
781 usage(1);
782 }
783 if (dflag && daemon(1, 1) < 0) {
784 err(1, "daemon");
785 }
786
787 memset(&act, 0, sizeof(act));
788 act.sa_handler = sighandler;
789 sigaction(SIGINT, &act, 0);
790 sigaction(SIGTERM, &act, 0);
791
792 if (!oflag) {
793 dpy = XOpenDisplay(NULL);
794 }
795
796 setlocale(LC_ALL, "");
797
798 while (!done) {
799 status_string[0] = '\0';
800
801 for (i = 0; i < sizeof(args) / sizeof(args[0]); ++i) {
802 argument = args[i];
803 if (argument.args == NULL) {
804 res = argument.func();
805 } else {
806 res = argument.func(argument.args);
807 }
808 element = smprintf(argument.fmt, res);
809 if (element == NULL) {
810 element = smprintf("%s", UNKNOWN_STR);
811 warnx("Failed to format output");
812 }
813 if (strlcat(status_string, element, sizeof(status_string)) >= sizeof(status_string)) {
814 warnx("Output too long");
815 }
816 free(res);
817 free(element);
818 }
819
820 if (!oflag) {
821 XStoreName(dpy, DefaultRootWindow(dpy), status_string);
822 XSync(dpy, False);
823 } else {
824 printf("%s\n", status_string);
825 }
826
827 if ((UPDATE_INTERVAL - delay) <= 0) {
828 delay = 0;
829 continue;
830 } else {
831 sleep(UPDATE_INTERVAL - delay);
832 delay = 0;
833 }
834 }
835
836 if (!oflag) {
837 XStoreName(dpy, DefaultRootWindow(dpy), NULL);
838 XCloseDisplay(dpy);
839 }
840
841 return 0;
842 }