Xinqi Bao's Git

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