Blame shared/systemd/src/basic/signal-util.c

Packit 5756e2
/* SPDX-License-Identifier: LGPL-2.1+ */
Packit 5756e2
Packit 5756e2
#include "nm-sd-adapt-shared.h"
Packit 5756e2
Packit 5756e2
#include <errno.h>
Packit 5756e2
#include <stdarg.h>
Packit 5756e2
Packit 5756e2
#include "macro.h"
Packit 5756e2
#include "parse-util.h"
Packit 5756e2
#include "signal-util.h"
Packit 5756e2
#include "stdio-util.h"
Packit 5756e2
#include "string-table.h"
Packit 5756e2
#include "string-util.h"
Packit 5756e2
Packit 5756e2
#if 0 /* NM_IGNORED */
Packit 5756e2
int reset_all_signal_handlers(void) {
Packit 5756e2
        static const struct sigaction sa = {
Packit 5756e2
                .sa_handler = SIG_DFL,
Packit 5756e2
                .sa_flags = SA_RESTART,
Packit 5756e2
        };
Packit 5756e2
        int sig, r = 0;
Packit 5756e2
Packit 5756e2
        for (sig = 1; sig < _NSIG; sig++) {
Packit 5756e2
Packit 5756e2
                /* These two cannot be caught... */
Packit 5756e2
                if (IN_SET(sig, SIGKILL, SIGSTOP))
Packit 5756e2
                        continue;
Packit 5756e2
Packit 5756e2
                /* On Linux the first two RT signals are reserved by
Packit 5756e2
                 * glibc, and sigaction() will return EINVAL for them. */
Packit 5756e2
                if (sigaction(sig, &sa, NULL) < 0)
Packit 5756e2
                        if (errno != EINVAL && r >= 0)
Packit 5756e2
                                r = -errno;
Packit 5756e2
        }
Packit 5756e2
Packit 5756e2
        return r;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
int reset_signal_mask(void) {
Packit 5756e2
        sigset_t ss;
Packit 5756e2
Packit 5756e2
        if (sigemptyset(&ss) < 0)
Packit 5756e2
                return -errno;
Packit 5756e2
Packit 5756e2
        if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
Packit 5756e2
                return -errno;
Packit 5756e2
Packit 5756e2
        return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) {
Packit 5756e2
        int r = 0;
Packit 5756e2
Packit 5756e2
        /* negative signal ends the list. 0 signal is skipped. */
Packit 5756e2
Packit 5756e2
        if (sig < 0)
Packit 5756e2
                return 0;
Packit 5756e2
Packit 5756e2
        if (sig > 0) {
Packit 5756e2
                if (sigaction(sig, sa, NULL) < 0)
Packit 5756e2
                        r = -errno;
Packit 5756e2
        }
Packit 5756e2
Packit 5756e2
        while ((sig = va_arg(ap, int)) >= 0) {
Packit 5756e2
Packit 5756e2
                if (sig == 0)
Packit 5756e2
                        continue;
Packit 5756e2
Packit 5756e2
                if (sigaction(sig, sa, NULL) < 0) {
Packit 5756e2
                        if (r >= 0)
Packit 5756e2
                                r = -errno;
Packit 5756e2
                }
Packit 5756e2
        }
Packit 5756e2
Packit 5756e2
        return r;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
int sigaction_many(const struct sigaction *sa, ...) {
Packit 5756e2
        va_list ap;
Packit 5756e2
        int r;
Packit 5756e2
Packit 5756e2
        va_start(ap, sa);
Packit 5756e2
        r = sigaction_many_ap(sa, 0, ap);
Packit 5756e2
        va_end(ap);
Packit 5756e2
Packit 5756e2
        return r;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
int ignore_signals(int sig, ...) {
Packit 5756e2
Packit 5756e2
        static const struct sigaction sa = {
Packit 5756e2
                .sa_handler = SIG_IGN,
Packit 5756e2
                .sa_flags = SA_RESTART,
Packit 5756e2
        };
Packit 5756e2
Packit 5756e2
        va_list ap;
Packit 5756e2
        int r;
Packit 5756e2
Packit 5756e2
        va_start(ap, sig);
Packit 5756e2
        r = sigaction_many_ap(&sa, sig, ap);
Packit 5756e2
        va_end(ap);
Packit 5756e2
Packit 5756e2
        return r;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
int default_signals(int sig, ...) {
Packit 5756e2
Packit 5756e2
        static const struct sigaction sa = {
Packit 5756e2
                .sa_handler = SIG_DFL,
Packit 5756e2
                .sa_flags = SA_RESTART,
Packit 5756e2
        };
Packit 5756e2
Packit 5756e2
        va_list ap;
Packit 5756e2
        int r;
Packit 5756e2
Packit 5756e2
        va_start(ap, sig);
Packit 5756e2
        r = sigaction_many_ap(&sa, sig, ap);
Packit 5756e2
        va_end(ap);
Packit 5756e2
Packit 5756e2
        return r;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int sigset_add_many_ap(sigset_t *ss, va_list ap) {
Packit 5756e2
        int sig, r = 0;
Packit 5756e2
Packit 5756e2
        assert(ss);
Packit 5756e2
Packit 5756e2
        while ((sig = va_arg(ap, int)) >= 0) {
Packit 5756e2
Packit 5756e2
                if (sig == 0)
Packit 5756e2
                        continue;
Packit 5756e2
Packit 5756e2
                if (sigaddset(ss, sig) < 0) {
Packit 5756e2
                        if (r >= 0)
Packit 5756e2
                                r = -errno;
Packit 5756e2
                }
Packit 5756e2
        }
Packit 5756e2
Packit 5756e2
        return r;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
int sigset_add_many(sigset_t *ss, ...) {
Packit 5756e2
        va_list ap;
Packit 5756e2
        int r;
Packit 5756e2
Packit 5756e2
        va_start(ap, ss);
Packit 5756e2
        r = sigset_add_many_ap(ss, ap);
Packit 5756e2
        va_end(ap);
Packit 5756e2
Packit 5756e2
        return r;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
int sigprocmask_many(int how, sigset_t *old, ...) {
Packit 5756e2
        va_list ap;
Packit 5756e2
        sigset_t ss;
Packit 5756e2
        int r;
Packit 5756e2
Packit 5756e2
        if (sigemptyset(&ss) < 0)
Packit 5756e2
                return -errno;
Packit 5756e2
Packit 5756e2
        va_start(ap, old);
Packit 5756e2
        r = sigset_add_many_ap(&ss, ap);
Packit 5756e2
        va_end(ap);
Packit 5756e2
Packit 5756e2
        if (r < 0)
Packit 5756e2
                return r;
Packit 5756e2
Packit 5756e2
        if (sigprocmask(how, &ss, old) < 0)
Packit 5756e2
                return -errno;
Packit 5756e2
Packit 5756e2
        return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static const char *const __signal_table[] = {
Packit 5756e2
        [SIGHUP] = "HUP",
Packit 5756e2
        [SIGINT] = "INT",
Packit 5756e2
        [SIGQUIT] = "QUIT",
Packit 5756e2
        [SIGILL] = "ILL",
Packit 5756e2
        [SIGTRAP] = "TRAP",
Packit 5756e2
        [SIGABRT] = "ABRT",
Packit 5756e2
        [SIGBUS] = "BUS",
Packit 5756e2
        [SIGFPE] = "FPE",
Packit 5756e2
        [SIGKILL] = "KILL",
Packit 5756e2
        [SIGUSR1] = "USR1",
Packit 5756e2
        [SIGSEGV] = "SEGV",
Packit 5756e2
        [SIGUSR2] = "USR2",
Packit 5756e2
        [SIGPIPE] = "PIPE",
Packit 5756e2
        [SIGALRM] = "ALRM",
Packit 5756e2
        [SIGTERM] = "TERM",
Packit 5756e2
#ifdef SIGSTKFLT
Packit 5756e2
        [SIGSTKFLT] = "STKFLT",  /* Linux on SPARC doesn't know SIGSTKFLT */
Packit 5756e2
#endif
Packit 5756e2
        [SIGCHLD] = "CHLD",
Packit 5756e2
        [SIGCONT] = "CONT",
Packit 5756e2
        [SIGSTOP] = "STOP",
Packit 5756e2
        [SIGTSTP] = "TSTP",
Packit 5756e2
        [SIGTTIN] = "TTIN",
Packit 5756e2
        [SIGTTOU] = "TTOU",
Packit 5756e2
        [SIGURG] = "URG",
Packit 5756e2
        [SIGXCPU] = "XCPU",
Packit 5756e2
        [SIGXFSZ] = "XFSZ",
Packit 5756e2
        [SIGVTALRM] = "VTALRM",
Packit 5756e2
        [SIGPROF] = "PROF",
Packit 5756e2
        [SIGWINCH] = "WINCH",
Packit 5756e2
        [SIGIO] = "IO",
Packit 5756e2
        [SIGPWR] = "PWR",
Packit 5756e2
        [SIGSYS] = "SYS"
Packit 5756e2
};
Packit 5756e2
Packit 5756e2
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
Packit 5756e2
Packit 5756e2
const char *signal_to_string(int signo) {
Packit 5756e2
        static thread_local char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1];
Packit 5756e2
        const char *name;
Packit 5756e2
Packit 5756e2
        name = __signal_to_string(signo);
Packit 5756e2
        if (name)
Packit 5756e2
                return name;
Packit 5756e2
Packit 5756e2
        if (signo >= SIGRTMIN && signo <= SIGRTMAX)
Packit 5756e2
                xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
Packit 5756e2
        else
Packit 5756e2
                xsprintf(buf, "%d", signo);
Packit 5756e2
Packit 5756e2
        return buf;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
int signal_from_string(const char *s) {
Packit 5756e2
        const char *p;
Packit 5756e2
        int signo, r;
Packit 5756e2
Packit 5756e2
        /* Check that the input is a signal number. */
Packit 5756e2
        if (safe_atoi(s, &signo) >= 0) {
Packit 5756e2
                if (SIGNAL_VALID(signo))
Packit 5756e2
                        return signo;
Packit 5756e2
                else
Packit 5756e2
                        return -ERANGE;
Packit 5756e2
        }
Packit 5756e2
Packit 5756e2
        /* Drop "SIG" prefix. */
Packit 5756e2
        if (startswith(s, "SIG"))
Packit 5756e2
                s += 3;
Packit 5756e2
Packit 5756e2
        /* Check that the input is a signal name. */
Packit 5756e2
        signo = __signal_from_string(s);
Packit 5756e2
        if (signo > 0)
Packit 5756e2
                return signo;
Packit 5756e2
Packit 5756e2
        /* Check that the input is RTMIN or
Packit 5756e2
         * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
Packit 5756e2
        p = startswith(s, "RTMIN");
Packit 5756e2
        if (p) {
Packit 5756e2
                if (*p == '\0')
Packit 5756e2
                        return SIGRTMIN;
Packit 5756e2
                if (*p != '+')
Packit 5756e2
                        return -EINVAL;
Packit 5756e2
Packit 5756e2
                r = safe_atoi(p, &signo);
Packit 5756e2
                if (r < 0)
Packit 5756e2
                        return r;
Packit 5756e2
Packit 5756e2
                if (signo < 0 || signo > SIGRTMAX - SIGRTMIN)
Packit 5756e2
                        return -ERANGE;
Packit 5756e2
Packit 5756e2
                return signo + SIGRTMIN;
Packit 5756e2
        }
Packit 5756e2
Packit 5756e2
        /* Check that the input is RTMAX or
Packit 5756e2
         * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
Packit 5756e2
        p = startswith(s, "RTMAX");
Packit 5756e2
        if (p) {
Packit 5756e2
                if (*p == '\0')
Packit 5756e2
                        return SIGRTMAX;
Packit 5756e2
                if (*p != '-')
Packit 5756e2
                        return -EINVAL;
Packit 5756e2
Packit 5756e2
                r = safe_atoi(p, &signo);
Packit 5756e2
                if (r < 0)
Packit 5756e2
                        return r;
Packit 5756e2
Packit 5756e2
                if (signo > 0 || signo < SIGRTMIN - SIGRTMAX)
Packit 5756e2
                        return -ERANGE;
Packit 5756e2
Packit 5756e2
                return signo + SIGRTMAX;
Packit 5756e2
        }
Packit 5756e2
Packit 5756e2
        return -EINVAL;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
void nop_signal_handler(int sig) {
Packit 5756e2
        /* nothing here */
Packit 5756e2
}
Packit 5756e2
#endif /* NM_IGNORED */
Packit 5756e2
Packit 5756e2
int signal_is_blocked(int sig) {
Packit 5756e2
        sigset_t ss;
Packit 5756e2
        int r;
Packit 5756e2
Packit 5756e2
        r = pthread_sigmask(SIG_SETMASK, NULL, &ss);
Packit 5756e2
        if (r != 0)
Packit 5756e2
                return -r;
Packit 5756e2
Packit 5756e2
        r = sigismember(&ss, sig);
Packit 5756e2
        if (r < 0)
Packit 5756e2
                return -errno;
Packit 5756e2
Packit 5756e2
        return r;
Packit 5756e2
}