Xinqi Bao's Git

35bdcd6372002008f8731dde2bc5364d7cdc327b
[slstatus.git] / slstatus.c
1 /* See LICENSE file for copyright and license details. */
2 #include <errno.h>
3 #include <locale.h>
4 #include <signal.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <time.h>
9 #include <X11/Xlib.h>
10
11 #include "arg.h"
12 #include "slstatus.h"
13 #include "util.h"
14
15 struct arg {
16 const char *(*func)();
17 const char *fmt;
18 const char *args;
19 };
20
21 char *argv0;
22 char buf[1024];
23 static int done;
24 static Display *dpy;
25
26 #include "config.h"
27
28 static void
29 terminate(const int signo)
30 {
31 (void)signo;
32
33 done = 1;
34 }
35
36 static void
37 difftimespec(struct timespec *res, struct timespec *a, struct timespec *b)
38 {
39 res->tv_sec = a->tv_sec - b->tv_sec - (a->tv_nsec < b->tv_nsec);
40 res->tv_nsec = a->tv_nsec - b->tv_nsec +
41 (a->tv_nsec < b->tv_nsec) * 1000000000;
42 }
43
44 static void
45 usage(void)
46 {
47 fprintf(stderr, "usage: %s [-s]\n", argv0);
48 exit(1);
49 }
50
51 int
52 main(int argc, char *argv[])
53 {
54 struct sigaction act;
55 struct timespec start, current, diff, intspec, wait;
56 size_t i, len;
57 int sflag, ret;
58 char status[MAXLEN];
59
60 sflag = 0;
61 ARGBEGIN {
62 case 's':
63 sflag = 1;
64 break;
65 default:
66 usage();
67 } ARGEND
68
69 if (argc) {
70 usage();
71 }
72
73 setlocale(LC_ALL, "");
74
75 memset(&act, 0, sizeof(act));
76 act.sa_handler = terminate;
77 sigaction(SIGINT, &act, NULL);
78 sigaction(SIGTERM, &act, NULL);
79
80 if (!sflag && !(dpy = XOpenDisplay(NULL))) {
81 fprintf(stderr, "Cannot open display");
82 return 1;
83 }
84
85 while (!done) {
86 clock_gettime(CLOCK_MONOTONIC, &start);
87
88 status[0] = '\0';
89 for (i = len = 0; i < LEN(args); i++) {
90 const char * res = args[i].func(args[i].args);
91 res = (res == NULL) ? unknown_str : res;
92 if ((ret = snprintf(status + len, sizeof(status) - len,
93 args[i].fmt, res)) < 0) {
94 fprintf(stderr, "snprintf: %s\n",
95 strerror(errno));
96 break;
97 } else if ((size_t)ret >= sizeof(status) - len) {
98 fprintf(stderr, "snprintf: Output truncated\n");
99 break;
100 }
101 len += ret;
102 }
103
104 if (sflag) {
105 printf("%s\n", status);
106 fflush(stdout);
107 } else {
108 XStoreName(dpy, DefaultRootWindow(dpy), status);
109 XSync(dpy, False);
110 }
111
112 if (!done) {
113 clock_gettime(CLOCK_MONOTONIC, &current);
114 difftimespec(&diff, &current, &start);
115
116 intspec.tv_sec = interval / 1000;
117 intspec.tv_nsec = (interval % 1000) * 1000000;
118 difftimespec(&wait, &intspec, &diff);
119
120 if (wait.tv_sec >= 0) {
121 nanosleep(&wait, NULL);
122 }
123 }
124 }
125
126 if (!sflag) {
127 XStoreName(dpy, DefaultRootWindow(dpy), NULL);
128 XCloseDisplay(dpy);
129 }
130
131 return 0;
132 }