slstatus.c - slstatus - status monitor
 (HTM) git clone git://git.suckless.org/slstatus
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       slstatus.c (2643B)
       ---
            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                 break;
           62         case '1':
           63                 done = 1;
           64                 /* FALLTHROUGH */
           65         case 's':
           66                 sflag = 1;
           67                 break;
           68         default:
           69                 usage();
           70         } ARGEND
           71 
           72         if (argc)
           73                 usage();
           74 
           75         memset(&act, 0, sizeof(act));
           76         act.sa_handler = terminate;
           77         sigaction(SIGINT,  &act, NULL);
           78         sigaction(SIGTERM, &act, NULL);
           79         act.sa_flags |= SA_RESTART;
           80         sigaction(SIGUSR1, &act, NULL);
           81 
           82         if (!sflag && !(dpy = XOpenDisplay(NULL)))
           83                 die("XOpenDisplay: Failed to open display");
           84 
           85         do {
           86                 if (clock_gettime(CLOCK_MONOTONIC, &start) < 0)
           87                         die("clock_gettime:");
           88 
           89                 status[0] = '\0';
           90                 for (i = len = 0; i < LEN(args); i++) {
           91                         if (!(res = args[i].func(args[i].args)))
           92                                 res = unknown_str;
           93 
           94                         if ((ret = esnprintf(status + len, sizeof(status) - len,
           95                                              args[i].fmt, res)) < 0)
           96                                 break;
           97 
           98                         len += ret;
           99                 }
          100 
          101                 if (sflag) {
          102                         puts(status);
          103                         fflush(stdout);
          104                         if (ferror(stdout))
          105                                 die("puts:");
          106                 } else {
          107                         if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0)
          108                                 die("XStoreName: Allocation failed");
          109                         XFlush(dpy);
          110                 }
          111 
          112                 if (!done) {
          113                         if (clock_gettime(CLOCK_MONOTONIC, &current) < 0)
          114                                 die("clock_gettime:");
          115                         difftimespec(&diff, &current, &start);
          116 
          117                         intspec.tv_sec = interval / 1000;
          118                         intspec.tv_nsec = (interval % 1000) * 1E6;
          119                         difftimespec(&wait, &intspec, &diff);
          120 
          121                         if (wait.tv_sec >= 0 &&
          122                             nanosleep(&wait, NULL) < 0 &&
          123                             errno != EINTR)
          124                                         die("nanosleep:");
          125                 }
          126         } while (!done);
          127 
          128         if (!sflag) {
          129                 XStoreName(dpy, DefaultRootWindow(dpy), NULL);
          130                 if (XCloseDisplay(dpy) < 0)
          131                         die("XCloseDisplay: Failed to close display");
          132         }
          133 
          134         return 0;
          135 }