From 8eaf9e1d101d93c784b12902eb71d5b2985a6985 Mon Sep 17 00:00:00 2001 From: sewn Date: Sat, 12 Oct 2024 20:45:16 +0300 Subject: [PATCH] implement signals & turns --- config.def.h | 11 ++++-- slstatus.c | 108 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 75 insertions(+), 44 deletions(-) diff --git a/config.def.h b/config.def.h index d805331..a89127b 100644 --- a/config.def.h +++ b/config.def.h @@ -6,8 +6,8 @@ const unsigned int interval = 1000; /* text to show if no value can be retrieved */ static const char unknown_str[] = "n/a"; -/* maximum output string length */ -#define MAXLEN 2048 +/* maximum command output length */ +#define CMDLEN 128 /* * function description argument (example) @@ -64,6 +64,9 @@ static const char unknown_str[] = "n/a"; * wifi_perc WiFi signal in percent interface name (wlan0) */ static const struct arg args[] = { - /* function format argument */ - { datetime, "%s", "%F %T" }, + /* function format argument turn signal */ + { datetime, "%s", "%F %T", 1, -1 }, }; + +/* maximum output string length */ +#define MAXLEN CMDLEN * LEN(args) diff --git a/slstatus.c b/slstatus.c index fd31313..d5efd35 100644 --- a/slstatus.c +++ b/slstatus.c @@ -15,20 +15,19 @@ struct arg { const char *(*func)(const char *); const char *fmt; const char *args; + unsigned int turn; + int signal; }; char buf[1024]; -static volatile sig_atomic_t done; +static int sflag = 0; +static volatile sig_atomic_t done, upsigno; static Display *dpy; #include "config.h" +#define MAXLEN CMDLEN * LEN(args) -static void -terminate(const int signo) -{ - if (signo != SIGUSR1) - done = 1; -} +static char statuses[LEN(args)][CMDLEN] = {0}; static void difftimespec(struct timespec *res, struct timespec *a, struct timespec *b) @@ -44,17 +43,61 @@ usage(void) die("usage: %s [-v] [-s] [-1]", argv0); } +static void +printstatus(unsigned int iter) +{ + size_t i; + char status[MAXLEN]; + const char *res; + + for (i = 0; i < LEN(args); i++) { + if (!((!iter && !upsigno) || upsigno == SIGUSR1 || + (!upsigno && args[i].turn > 0 && !(iter % args[i].turn)) || + (args[i].signal >= 0 && upsigno - SIGRTMIN == args[i].signal))) + continue; + + if (!(res = args[i].func(args[i].args))) + res = unknown_str; + + if (esnprintf(statuses[i], sizeof(statuses[i]), args[i].fmt, res) < 0) + break; + } + + status[0] = '\0'; + for (i = 0; i < LEN(args); i++) + strcat(status, statuses[i]); + status[strlen(status)] = '\0'; + + if (sflag) { + puts(status); + fflush(stdout); + if (ferror(stdout)) + die("puts:"); + } else { + if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) + die("XStoreName: Allocation failed"); + XFlush(dpy); + } +} + + +static void +sighandler(const int signo) +{ + if ((signo <= SIGRTMAX && signo >= SIGRTMIN) || signo == SIGUSR1) + upsigno = signo; + else + done = 1; +} + int main(int argc, char *argv[]) { struct sigaction act; struct timespec start, current, diff, intspec, wait; - size_t i, len; - int sflag, ret; - char status[MAXLEN]; - const char *res; + unsigned int iter = 0; + int i, ret; - sflag = 0; ARGBEGIN { case 'v': die("slstatus-"VERSION); @@ -72,11 +115,12 @@ main(int argc, char *argv[]) usage(); memset(&act, 0, sizeof(act)); - act.sa_handler = terminate; + act.sa_handler = sighandler; sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); - act.sa_flags |= SA_RESTART; sigaction(SIGUSR1, &act, NULL); + for (i = SIGRTMIN; i <= SIGRTMAX; i++) + sigaction(i, &act, NULL); if (!sflag && !(dpy = XOpenDisplay(NULL))) die("XOpenDisplay: Failed to open display"); @@ -85,28 +129,7 @@ main(int argc, char *argv[]) if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) die("clock_gettime:"); - status[0] = '\0'; - for (i = len = 0; i < LEN(args); i++) { - if (!(res = args[i].func(args[i].args))) - res = unknown_str; - - if ((ret = esnprintf(status + len, sizeof(status) - len, - args[i].fmt, res)) < 0) - break; - - len += ret; - } - - if (sflag) { - puts(status); - fflush(stdout); - if (ferror(stdout)) - die("puts:"); - } else { - if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) - die("XStoreName: Allocation failed"); - XFlush(dpy); - } + printstatus(iter++); if (!done) { if (clock_gettime(CLOCK_MONOTONIC, ¤t) < 0) @@ -117,10 +140,15 @@ main(int argc, char *argv[]) intspec.tv_nsec = (interval % 1000) * 1E6; difftimespec(&wait, &intspec, &diff); - if (wait.tv_sec >= 0 && - nanosleep(&wait, NULL) < 0 && - errno != EINTR) - die("nanosleep:"); + do { + if (errno == EINTR) { + printstatus(0); + errno = upsigno = 0; + } + ret = nanosleep(&wait, &wait); + } while (wait.tv_sec >= 0 && ret < 0 && !done); + if (ret < 0 && errno != EINTR) + die("nanosleep:"); } } while (!done); -- 2.46.2