LCOV - code coverage report
Current view: top level - basic - signal-util.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 94 116 81.0 %
Date: 2019-08-22 15:41:25 Functions: 12 14 85.7 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <stdarg.h>
       5             : #include <stdio.h>
       6             : 
       7             : #include "macro.h"
       8             : #include "parse-util.h"
       9             : #include "signal-util.h"
      10             : #include "stdio-util.h"
      11             : #include "string-table.h"
      12             : #include "string-util.h"
      13             : 
      14           7 : int reset_all_signal_handlers(void) {
      15             :         static const struct sigaction sa = {
      16             :                 .sa_handler = SIG_DFL,
      17             :                 .sa_flags = SA_RESTART,
      18             :         };
      19           7 :         int sig, r = 0;
      20             : 
      21         455 :         for (sig = 1; sig < _NSIG; sig++) {
      22             : 
      23             :                 /* These two cannot be caught... */
      24         448 :                 if (IN_SET(sig, SIGKILL, SIGSTOP))
      25          14 :                         continue;
      26             : 
      27             :                 /* On Linux the first two RT signals are reserved by
      28             :                  * glibc, and sigaction() will return EINVAL for them. */
      29         434 :                 if ((sigaction(sig, &sa, NULL) < 0))
      30          14 :                         if (errno != EINVAL && r >= 0)
      31           0 :                                 r = -errno;
      32             :         }
      33             : 
      34           7 :         return r;
      35             : }
      36             : 
      37           7 : int reset_signal_mask(void) {
      38             :         sigset_t ss;
      39             : 
      40           7 :         if (sigemptyset(&ss) < 0)
      41           0 :                 return -errno;
      42             : 
      43           7 :         if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
      44           0 :                 return -errno;
      45             : 
      46           7 :         return 0;
      47             : }
      48             : 
      49           3 : static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) {
      50           3 :         int r = 0;
      51             : 
      52             :         /* negative signal ends the list. 0 signal is skipped. */
      53             : 
      54           3 :         if (sig < 0)
      55           0 :                 return 0;
      56             : 
      57           3 :         if (sig > 0) {
      58           3 :                 if (sigaction(sig, sa, NULL) < 0)
      59           0 :                         r = -errno;
      60             :         }
      61             : 
      62          10 :         while ((sig = va_arg(ap, int)) >= 0) {
      63             : 
      64           7 :                 if (sig == 0)
      65           0 :                         continue;
      66             : 
      67           7 :                 if (sigaction(sig, sa, NULL) < 0) {
      68           0 :                         if (r >= 0)
      69           0 :                                 r = -errno;
      70             :                 }
      71             :         }
      72             : 
      73           3 :         return r;
      74             : }
      75             : 
      76           0 : int sigaction_many(const struct sigaction *sa, ...) {
      77             :         va_list ap;
      78             :         int r;
      79             : 
      80           0 :         va_start(ap, sa);
      81           0 :         r = sigaction_many_ap(sa, 0, ap);
      82           0 :         va_end(ap);
      83             : 
      84           0 :         return r;
      85             : }
      86             : 
      87           2 : int ignore_signals(int sig, ...) {
      88             : 
      89             :         static const struct sigaction sa = {
      90             :                 .sa_handler = SIG_IGN,
      91             :                 .sa_flags = SA_RESTART,
      92             :         };
      93             : 
      94             :         va_list ap;
      95             :         int r;
      96             : 
      97           2 :         va_start(ap, sig);
      98           2 :         r = sigaction_many_ap(&sa, sig, ap);
      99           2 :         va_end(ap);
     100             : 
     101           2 :         return r;
     102             : }
     103             : 
     104           1 : int default_signals(int sig, ...) {
     105             : 
     106             :         static const struct sigaction sa = {
     107             :                 .sa_handler = SIG_DFL,
     108             :                 .sa_flags = SA_RESTART,
     109             :         };
     110             : 
     111             :         va_list ap;
     112             :         int r;
     113             : 
     114           1 :         va_start(ap, sig);
     115           1 :         r = sigaction_many_ap(&sa, sig, ap);
     116           1 :         va_end(ap);
     117             : 
     118           1 :         return r;
     119             : }
     120             : 
     121          17 : static int sigset_add_many_ap(sigset_t *ss, va_list ap) {
     122          17 :         int sig, r = 0;
     123             : 
     124          17 :         assert(ss);
     125             : 
     126         334 :         while ((sig = va_arg(ap, int)) >= 0) {
     127             : 
     128         317 :                 if (sig == 0)
     129           0 :                         continue;
     130             : 
     131         317 :                 if (sigaddset(ss, sig) < 0) {
     132           0 :                         if (r >= 0)
     133           0 :                                 r = -errno;
     134             :                 }
     135             :         }
     136             : 
     137          17 :         return r;
     138             : }
     139             : 
     140          11 : int sigset_add_many(sigset_t *ss, ...) {
     141             :         va_list ap;
     142             :         int r;
     143             : 
     144          11 :         va_start(ap, ss);
     145          11 :         r = sigset_add_many_ap(ss, ap);
     146          11 :         va_end(ap);
     147             : 
     148          11 :         return r;
     149             : }
     150             : 
     151           6 : int sigprocmask_many(int how, sigset_t *old, ...) {
     152             :         va_list ap;
     153             :         sigset_t ss;
     154             :         int r;
     155             : 
     156           6 :         if (sigemptyset(&ss) < 0)
     157           0 :                 return -errno;
     158             : 
     159           6 :         va_start(ap, old);
     160           6 :         r = sigset_add_many_ap(&ss, ap);
     161           6 :         va_end(ap);
     162             : 
     163           6 :         if (r < 0)
     164           0 :                 return r;
     165             : 
     166           6 :         if (sigprocmask(how, &ss, old) < 0)
     167           0 :                 return -errno;
     168             : 
     169           6 :         return 0;
     170             : }
     171             : 
     172             : static const char *const __signal_table[] = {
     173             :         [SIGHUP] = "HUP",
     174             :         [SIGINT] = "INT",
     175             :         [SIGQUIT] = "QUIT",
     176             :         [SIGILL] = "ILL",
     177             :         [SIGTRAP] = "TRAP",
     178             :         [SIGABRT] = "ABRT",
     179             :         [SIGBUS] = "BUS",
     180             :         [SIGFPE] = "FPE",
     181             :         [SIGKILL] = "KILL",
     182             :         [SIGUSR1] = "USR1",
     183             :         [SIGSEGV] = "SEGV",
     184             :         [SIGUSR2] = "USR2",
     185             :         [SIGPIPE] = "PIPE",
     186             :         [SIGALRM] = "ALRM",
     187             :         [SIGTERM] = "TERM",
     188             : #ifdef SIGSTKFLT
     189             :         [SIGSTKFLT] = "STKFLT",  /* Linux on SPARC doesn't know SIGSTKFLT */
     190             : #endif
     191             :         [SIGCHLD] = "CHLD",
     192             :         [SIGCONT] = "CONT",
     193             :         [SIGSTOP] = "STOP",
     194             :         [SIGTSTP] = "TSTP",
     195             :         [SIGTTIN] = "TTIN",
     196             :         [SIGTTOU] = "TTOU",
     197             :         [SIGURG] = "URG",
     198             :         [SIGXCPU] = "XCPU",
     199             :         [SIGXFSZ] = "XFSZ",
     200             :         [SIGVTALRM] = "VTALRM",
     201             :         [SIGPROF] = "PROF",
     202             :         [SIGWINCH] = "WINCH",
     203             :         [SIGIO] = "IO",
     204             :         [SIGPWR] = "PWR",
     205             :         [SIGSYS] = "SYS"
     206             : };
     207             : 
     208         433 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
     209             : 
     210         362 : const char *signal_to_string(int signo) {
     211             :         static thread_local char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1];
     212             :         const char *name;
     213             : 
     214         362 :         name = __signal_to_string(signo);
     215         362 :         if (name)
     216         356 :                 return name;
     217             : 
     218           6 :         if (signo >= SIGRTMIN && signo <= SIGRTMAX)
     219           6 :                 xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
     220             :         else
     221           0 :                 xsprintf(buf, "%d", signo);
     222             : 
     223           6 :         return buf;
     224             : }
     225             : 
     226          76 : int signal_from_string(const char *s) {
     227             :         const char *p;
     228             :         int signo, r;
     229             : 
     230             :         /* Check that the input is a signal number. */
     231          76 :         if (safe_atoi(s, &signo) >= 0) {
     232           5 :                 if (SIGNAL_VALID(signo))
     233           3 :                         return signo;
     234             :                 else
     235           2 :                         return -ERANGE;
     236             :         }
     237             : 
     238             :         /* Drop "SIG" prefix. */
     239          71 :         if (startswith(s, "SIG"))
     240          38 :                 s += 3;
     241             : 
     242             :         /* Check that the input is a signal name. */
     243          71 :         signo = __signal_from_string(s);
     244          71 :         if (signo > 0)
     245           4 :                 return signo;
     246             : 
     247             :         /* Check that the input is RTMIN or
     248             :          * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
     249          67 :         p = startswith(s, "RTMIN");
     250          67 :         if (p) {
     251          32 :                 if (*p == '\0')
     252           2 :                         return SIGRTMIN;
     253          30 :                 if (*p != '+')
     254          10 :                         return -EINVAL;
     255             : 
     256          20 :                 r = safe_atoi(p, &signo);
     257          20 :                 if (r < 0)
     258           8 :                         return r;
     259             : 
     260          12 :                 if (signo < 0 || signo > SIGRTMAX - SIGRTMIN)
     261           4 :                         return -ERANGE;
     262             : 
     263           8 :                 return signo + SIGRTMIN;
     264             :         }
     265             : 
     266             :         /* Check that the input is RTMAX or
     267             :          * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
     268          35 :         p = startswith(s, "RTMAX");
     269          35 :         if (p) {
     270          24 :                 if (*p == '\0')
     271           2 :                         return SIGRTMAX;
     272          22 :                 if (*p != '-')
     273           8 :                         return -EINVAL;
     274             : 
     275          14 :                 r = safe_atoi(p, &signo);
     276          14 :                 if (r < 0)
     277           8 :                         return r;
     278             : 
     279           6 :                 if (signo > 0 || signo < SIGRTMIN - SIGRTMAX)
     280           4 :                         return -ERANGE;
     281             : 
     282           2 :                 return signo + SIGRTMAX;
     283             :         }
     284             : 
     285          11 :         return -EINVAL;
     286             : }
     287             : 
     288           0 : void nop_signal_handler(int sig) {
     289             :         /* nothing here */
     290           0 : }

Generated by: LCOV version 1.14