slstatus.c - slstatus - status monitor
git clone git://git.suckless.org/slstatus
Log
Files
Refs
README
LICENSE
---
slstatus.c (2634B)
---
     1 /* See LICENSE file for copyright and license details. */
     2 #include 
     3 #include 
     4 #include 
     5 #include 
     6 #include 
     7 #include 
     8 #include 
     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, ¤t) < 0)
   113                                 die("clock_gettime:");
   114                         difftimespec(&diff, ¤t, &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 }