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