slstatus-signals-1.0.patch - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       slstatus-signals-1.0.patch (5019B)
       ---
            1 From fabec4fb9f3cb749f33dc97188106c73a20ca7db Mon Sep 17 00:00:00 2001
            2 From: sewn <sewn@disroot.org>
            3 Date: Wed, 5 Feb 2025 16:00:52 +0300
            4 Subject: [PATCH] implement signals & turns
            5 
            6 ---
            7  config.def.h |  11 ++++--
            8  slstatus.c   | 107 ++++++++++++++++++++++++++++++++-------------------
            9  2 files changed, 74 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..b3dbae8 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, &current) < 0)
          181 @@ -117,10 +140,14 @@ 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 +                        while(wait.tv_sec >= 0 &&
          190 +                              (ret = nanosleep(&wait, &wait)) < 0 &&
          191 +                              errno == EINTR && !done) {
          192 +                                printstatus(0);
          193 +                                errno = upsigno = 0;
          194 +                        }
          195 +                        if (ret < 0 && errno != EINTR)
          196 +                                die("nanosleep:");
          197                  }
          198          } while (!done);
          199  
          200 -- 
          201 2.47.1
          202