slstatus-signals-1.0.patch (5036B)
1 From 8eaf9e1d101d93c784b12902eb71d5b2985a6985 Mon Sep 17 00:00:00 2001 2 From: sewn <sewn@disroot.org> 3 Date: Sat, 12 Oct 2024 20:45:16 +0300 4 Subject: [PATCH] implement signals & turns 5 6 --- 7 config.def.h | 11 ++++-- 8 slstatus.c | 108 ++++++++++++++++++++++++++++++++------------------- 9 2 files changed, 75 insertions(+), 44 deletions(-) 10 11 diff --git a/config.def.h b/config.def.h 12 index d805331..a89127b 100644 13 --- a/config.def.h 14 +++ b/config.def.h 15 @@ -6,8 +6,8 @@ const unsigned int interval = 1000; 16 /* text to show if no value can be retrieved */ 17 static const char unknown_str[] = "n/a"; 18 19 -/* maximum output string length */ 20 -#define MAXLEN 2048 21 +/* maximum command output length */ 22 +#define CMDLEN 128 23 24 /* 25 * function description argument (example) 26 @@ -64,6 +64,9 @@ static const char unknown_str[] = "n/a"; 27 * wifi_perc WiFi signal in percent interface name (wlan0) 28 */ 29 static const struct arg args[] = { 30 - /* function format argument */ 31 - { datetime, "%s", "%F %T" }, 32 + /* function format argument turn signal */ 33 + { datetime, "%s", "%F %T", 1, -1 }, 34 }; 35 + 36 +/* maximum output string length */ 37 +#define MAXLEN CMDLEN * LEN(args) 38 diff --git a/slstatus.c b/slstatus.c 39 index fd31313..d5efd35 100644 40 --- a/slstatus.c 41 +++ b/slstatus.c 42 @@ -15,20 +15,19 @@ struct arg { 43 const char *(*func)(const char *); 44 const char *fmt; 45 const char *args; 46 + unsigned int turn; 47 + int signal; 48 }; 49 50 char buf[1024]; 51 -static volatile sig_atomic_t done; 52 +static int sflag = 0; 53 +static volatile sig_atomic_t done, upsigno; 54 static Display *dpy; 55 56 #include "config.h" 57 +#define MAXLEN CMDLEN * LEN(args) 58 59 -static void 60 -terminate(const int signo) 61 -{ 62 - if (signo != SIGUSR1) 63 - done = 1; 64 -} 65 +static char statuses[LEN(args)][CMDLEN] = {0}; 66 67 static void 68 difftimespec(struct timespec *res, struct timespec *a, struct timespec *b) 69 @@ -44,17 +43,61 @@ usage(void) 70 die("usage: %s [-v] [-s] [-1]", argv0); 71 } 72 73 +static void 74 +printstatus(unsigned int iter) 75 +{ 76 + size_t i; 77 + char status[MAXLEN]; 78 + const char *res; 79 + 80 + for (i = 0; i < LEN(args); i++) { 81 + if (!((!iter && !upsigno) || upsigno == SIGUSR1 || 82 + (!upsigno && args[i].turn > 0 && !(iter % args[i].turn)) || 83 + (args[i].signal >= 0 && upsigno - SIGRTMIN == args[i].signal))) 84 + continue; 85 + 86 + if (!(res = args[i].func(args[i].args))) 87 + res = unknown_str; 88 + 89 + if (esnprintf(statuses[i], sizeof(statuses[i]), args[i].fmt, res) < 0) 90 + break; 91 + } 92 + 93 + status[0] = '\0'; 94 + for (i = 0; i < LEN(args); i++) 95 + strcat(status, statuses[i]); 96 + status[strlen(status)] = '\0'; 97 + 98 + if (sflag) { 99 + puts(status); 100 + fflush(stdout); 101 + if (ferror(stdout)) 102 + die("puts:"); 103 + } else { 104 + if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) 105 + die("XStoreName: Allocation failed"); 106 + XFlush(dpy); 107 + } 108 +} 109 + 110 + 111 +static void 112 +sighandler(const int signo) 113 +{ 114 + if ((signo <= SIGRTMAX && signo >= SIGRTMIN) || signo == SIGUSR1) 115 + upsigno = signo; 116 + else 117 + done = 1; 118 +} 119 + 120 int 121 main(int argc, char *argv[]) 122 { 123 struct sigaction act; 124 struct timespec start, current, diff, intspec, wait; 125 - size_t i, len; 126 - int sflag, ret; 127 - char status[MAXLEN]; 128 - const char *res; 129 + unsigned int iter = 0; 130 + int i, ret; 131 132 - sflag = 0; 133 ARGBEGIN { 134 case 'v': 135 die("slstatus-"VERSION); 136 @@ -72,11 +115,12 @@ main(int argc, char *argv[]) 137 usage(); 138 139 memset(&act, 0, sizeof(act)); 140 - act.sa_handler = terminate; 141 + act.sa_handler = sighandler; 142 sigaction(SIGINT, &act, NULL); 143 sigaction(SIGTERM, &act, NULL); 144 - act.sa_flags |= SA_RESTART; 145 sigaction(SIGUSR1, &act, NULL); 146 + for (i = SIGRTMIN; i <= SIGRTMAX; i++) 147 + sigaction(i, &act, NULL); 148 149 if (!sflag && !(dpy = XOpenDisplay(NULL))) 150 die("XOpenDisplay: Failed to open display"); 151 @@ -85,28 +129,7 @@ main(int argc, char *argv[]) 152 if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) 153 die("clock_gettime:"); 154 155 - status[0] = '\0'; 156 - for (i = len = 0; i < LEN(args); i++) { 157 - if (!(res = args[i].func(args[i].args))) 158 - res = unknown_str; 159 - 160 - if ((ret = esnprintf(status + len, sizeof(status) - len, 161 - args[i].fmt, res)) < 0) 162 - break; 163 - 164 - len += ret; 165 - } 166 - 167 - if (sflag) { 168 - puts(status); 169 - fflush(stdout); 170 - if (ferror(stdout)) 171 - die("puts:"); 172 - } else { 173 - if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) 174 - die("XStoreName: Allocation failed"); 175 - XFlush(dpy); 176 - } 177 + printstatus(iter++); 178 179 if (!done) { 180 if (clock_gettime(CLOCK_MONOTONIC, ¤t) < 0) 181 @@ -117,10 +140,15 @@ main(int argc, char *argv[]) 182 intspec.tv_nsec = (interval % 1000) * 1E6; 183 difftimespec(&wait, &intspec, &diff); 184 185 - if (wait.tv_sec >= 0 && 186 - nanosleep(&wait, NULL) < 0 && 187 - errno != EINTR) 188 - die("nanosleep:"); 189 + do { 190 + if (errno == EINTR) { 191 + printstatus(0); 192 + errno = upsigno = 0; 193 + } 194 + ret = nanosleep(&wait, &wait); 195 + } while (wait.tv_sec >= 0 && ret < 0 && !done); 196 + if (ret < 0 && errno != EINTR) 197 + die("nanosleep:"); 198 } 199 } while (!done); 200 201 -- 202 2.46.2 203