Xinqi Bao's Git

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