|
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 |
}
|