Xinqi Bao's Git

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