dwmblocks

Kris's build of dwmblocks
git clone git clone https://git.krisyotam.com/krisyotam/dwmblocks.git
Log | Files | Refs | README | LICENSE

signal-handler.c (3536B)


      1 #include "signal-handler.h"
      2 
      3 #include <signal.h>
      4 #include <stdint.h>
      5 #include <stdio.h>
      6 #include <sys/signalfd.h>
      7 #include <sys/types.h>
      8 #include <unistd.h>
      9 
     10 #include "block.h"
     11 #include "main.h"
     12 #include "timer.h"
     13 
     14 typedef struct signalfd_siginfo signal_info;
     15 
     16 signal_handler signal_handler_new(
     17     block *const blocks, const unsigned short block_count,
     18     const signal_refresh_callback refresh_callback,
     19     const signal_timer_callback timer_callback) {
     20     signal_handler handler = {
     21         .refresh_callback = refresh_callback,
     22         .timer_callback = timer_callback,
     23 
     24         .blocks = blocks,
     25         .block_count = block_count,
     26     };
     27 
     28     return handler;
     29 }
     30 
     31 int signal_handler_init(signal_handler *const handler) {
     32     signal_set set;
     33     (void)sigemptyset(&set);
     34 
     35     // Handle user-generated signal for refreshing the status.
     36     (void)sigaddset(&set, REFRESH_SIGNAL);
     37 
     38     // Handle SIGALRM generated by the timer.
     39     (void)sigaddset(&set, TIMER_SIGNAL);
     40 
     41     // Handle termination signals.
     42     (void)sigaddset(&set, SIGINT);
     43     (void)sigaddset(&set, SIGTERM);
     44 
     45     for (unsigned short i = 0; i < handler->block_count; ++i) {
     46         const block *const block = &handler->blocks[i];
     47         if (block->signal > 0) {
     48             if (sigaddset(&set, SIGRTMIN + block->signal) != 0) {
     49                 (void)fprintf(
     50                     stderr,
     51                     "error: invalid or unsupported signal specified for "
     52                     "\"%s\" block\n",
     53                     block->command);
     54                 return 1;
     55             }
     56         }
     57     }
     58 
     59     // Create a signal file descriptor for epoll to watch.
     60     handler->fd = signalfd(-1, &set, 0);
     61     if (handler->fd == -1) {
     62         (void)fprintf(stderr,
     63                       "error: could not create file descriptor for signals\n");
     64         return 1;
     65     }
     66 
     67     // Block all realtime and handled signals.
     68     for (int i = SIGRTMIN; i <= SIGRTMAX; ++i) {
     69         (void)sigaddset(&set, i);
     70     }
     71     (void)sigprocmask(SIG_BLOCK, &set, NULL);
     72 
     73     return 0;
     74 }
     75 
     76 int signal_handler_deinit(signal_handler *const handler) {
     77     if (close(handler->fd) != 0) {
     78         (void)fprintf(stderr,
     79                       "error: could not close signal file descriptor\n");
     80         return 1;
     81     }
     82 
     83     return 0;
     84 }
     85 
     86 int signal_handler_process(signal_handler *const handler, timer *const timer) {
     87     signal_info info;
     88     const ssize_t bytes_read = read(handler->fd, &info, sizeof(info));
     89     if (bytes_read == -1) {
     90         (void)fprintf(stderr, "error: could not read info of incoming signal");
     91         return 1;
     92     }
     93 
     94     const int signal = (int)info.ssi_signo;
     95     switch (signal) {
     96         case TIMER_SIGNAL:
     97             if (handler->timer_callback(handler->blocks, handler->block_count,
     98                                         timer) != 0) {
     99                 return 1;
    100             }
    101             return 0;
    102         case REFRESH_SIGNAL:
    103             if (handler->refresh_callback(handler->blocks,
    104                                           handler->block_count) != 0) {
    105                 return 1;
    106             }
    107             return 0;
    108         case SIGTERM:
    109             // fall through
    110         case SIGINT:
    111             return 1;
    112         default:
    113             break;
    114     }
    115 
    116     for (unsigned short i = 0; i < handler->block_count; ++i) {
    117         block *const block = &handler->blocks[i];
    118         if (block->signal == signal - SIGRTMIN) {
    119             const uint8_t button = (uint8_t)info.ssi_int;
    120             block_execute(block, button);
    121             break;
    122         }
    123     }
    124 
    125     return 0;
    126 }