Xinqi Bao's Git

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