chiark / gitweb /
util: split out signal-util.[ch] from util.[ch]
[elogind.git] / src / shared / signal-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2015 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "util.h"
23 #include "signal-util.h"
24
25 int reset_all_signal_handlers(void) {
26         int sig, r = 0;
27
28         for (sig = 1; sig < _NSIG; sig++) {
29                 static const struct sigaction sa = {
30                         .sa_handler = SIG_DFL,
31                         .sa_flags = SA_RESTART,
32                 };
33
34                 /* These two cannot be caught... */
35                 if (sig == SIGKILL || sig == SIGSTOP)
36                         continue;
37
38                 /* On Linux the first two RT signals are reserved by
39                  * glibc, and sigaction() will return EINVAL for them. */
40                 if ((sigaction(sig, &sa, NULL) < 0))
41                         if (errno != EINVAL && r == 0)
42                                 r = -errno;
43         }
44
45         return r;
46 }
47
48 int reset_signal_mask(void) {
49         sigset_t ss;
50
51         if (sigemptyset(&ss) < 0)
52                 return -errno;
53
54         if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
55                 return -errno;
56
57         return 0;
58 }
59
60 int sigaction_many(const struct sigaction *sa, ...) {
61         va_list ap;
62         int r = 0, sig;
63
64         va_start(ap, sa);
65         while ((sig = va_arg(ap, int)) > 0)
66                 if (sigaction(sig, sa, NULL) < 0)
67                         r = -errno;
68         va_end(ap);
69
70         return r;
71 }
72
73 int ignore_signals(int sig, ...) {
74         static const struct sigaction sa = {
75                 .sa_handler = SIG_IGN,
76                 .sa_flags = SA_RESTART,
77         };
78         va_list ap;
79         int r = 0;
80
81         if (sigaction(sig, &sa, NULL) < 0)
82                 r = -errno;
83
84         va_start(ap, sig);
85         while ((sig = va_arg(ap, int)) > 0)
86                 if (sigaction(sig, &sa, NULL) < 0)
87                         r = -errno;
88         va_end(ap);
89
90         return r;
91 }
92
93 int default_signals(int sig, ...) {
94         static const struct sigaction sa = {
95                 .sa_handler = SIG_DFL,
96                 .sa_flags = SA_RESTART,
97         };
98         va_list ap;
99         int r = 0;
100
101         if (sigaction(sig, &sa, NULL) < 0)
102                 r = -errno;
103
104         va_start(ap, sig);
105         while ((sig = va_arg(ap, int)) > 0)
106                 if (sigaction(sig, &sa, NULL) < 0)
107                         r = -errno;
108         va_end(ap);
109
110         return r;
111 }
112
113 void sigset_add_many(sigset_t *ss, ...) {
114         va_list ap;
115         int sig;
116
117         assert(ss);
118
119         va_start(ap, ss);
120         while ((sig = va_arg(ap, int)) > 0)
121                 assert_se(sigaddset(ss, sig) == 0);
122         va_end(ap);
123 }
124
125 int sigprocmask_many(int how, ...) {
126         va_list ap;
127         sigset_t ss;
128         int sig;
129
130         assert_se(sigemptyset(&ss) == 0);
131
132         va_start(ap, how);
133         while ((sig = va_arg(ap, int)) > 0)
134                 assert_se(sigaddset(&ss, sig) == 0);
135         va_end(ap);
136
137         if (sigprocmask(how, &ss, NULL) < 0)
138                 return -errno;
139
140         return 0;
141 }
142
143 static const char *const __signal_table[] = {
144         [SIGHUP] = "HUP",
145         [SIGINT] = "INT",
146         [SIGQUIT] = "QUIT",
147         [SIGILL] = "ILL",
148         [SIGTRAP] = "TRAP",
149         [SIGABRT] = "ABRT",
150         [SIGBUS] = "BUS",
151         [SIGFPE] = "FPE",
152         [SIGKILL] = "KILL",
153         [SIGUSR1] = "USR1",
154         [SIGSEGV] = "SEGV",
155         [SIGUSR2] = "USR2",
156         [SIGPIPE] = "PIPE",
157         [SIGALRM] = "ALRM",
158         [SIGTERM] = "TERM",
159 #ifdef SIGSTKFLT
160         [SIGSTKFLT] = "STKFLT",  /* Linux on SPARC doesn't know SIGSTKFLT */
161 #endif
162         [SIGCHLD] = "CHLD",
163         [SIGCONT] = "CONT",
164         [SIGSTOP] = "STOP",
165         [SIGTSTP] = "TSTP",
166         [SIGTTIN] = "TTIN",
167         [SIGTTOU] = "TTOU",
168         [SIGURG] = "URG",
169         [SIGXCPU] = "XCPU",
170         [SIGXFSZ] = "XFSZ",
171         [SIGVTALRM] = "VTALRM",
172         [SIGPROF] = "PROF",
173         [SIGWINCH] = "WINCH",
174         [SIGIO] = "IO",
175         [SIGPWR] = "PWR",
176         [SIGSYS] = "SYS"
177 };
178
179 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
180
181 const char *signal_to_string(int signo) {
182         static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
183         const char *name;
184
185         name = __signal_to_string(signo);
186         if (name)
187                 return name;
188
189         if (signo >= SIGRTMIN && signo <= SIGRTMAX)
190                 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
191         else
192                 snprintf(buf, sizeof(buf), "%d", signo);
193
194         return buf;
195 }
196
197 int signal_from_string(const char *s) {
198         int signo;
199         int offset = 0;
200         unsigned u;
201
202         signo = __signal_from_string(s);
203         if (signo > 0)
204                 return signo;
205
206         if (startswith(s, "RTMIN+")) {
207                 s += 6;
208                 offset = SIGRTMIN;
209         }
210         if (safe_atou(s, &u) >= 0) {
211                 signo = (int) u + offset;
212                 if (signo > 0 && signo < _NSIG)
213                         return signo;
214         }
215         return -EINVAL;
216 }
217
218 int signal_from_string_try_harder(const char *s) {
219         int signo;
220         assert(s);
221
222         signo = signal_from_string(s);
223         if (signo <= 0)
224                 if (startswith(s, "SIG"))
225                         return signal_from_string(s+3);
226
227         return signo;
228 }