Xinqi Bao's Git

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