Coverage Report

Created: 2019-06-19 13:33

/src/systemd/src/basic/signal-util.c
Line
Count
Source (jump to first uncovered line)
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
0
int reset_all_signal_handlers(void) {
15
0
        static const struct sigaction sa = {
16
0
                .sa_handler = SIG_DFL,
17
0
                .sa_flags = SA_RESTART,
18
0
        };
19
0
        int sig, r = 0;
20
0
21
0
        for (sig = 1; sig < _NSIG; sig++) {
22
0
23
0
                /* These two cannot be caught... */
24
0
                if (IN_SET(sig, SIGKILL, SIGSTOP))
25
0
                        continue;
26
0
27
0
                /* On Linux the first two RT signals are reserved by
28
0
                 * glibc, and sigaction() will return EINVAL for them. */
29
0
                if ((sigaction(sig, &sa, NULL) < 0))
30
0
                        if (errno != EINVAL && r >= 0)
31
0
                                r = -errno;
32
0
        }
33
0
34
0
        return r;
35
0
}
36
37
0
int reset_signal_mask(void) {
38
0
        sigset_t ss;
39
0
40
0
        if (sigemptyset(&ss) < 0)
41
0
                return -errno;
42
0
43
0
        if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
44
0
                return -errno;
45
0
46
0
        return 0;
47
0
}
48
49
0
static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) {
50
0
        int r = 0;
51
0
52
0
        /* negative signal ends the list. 0 signal is skipped. */
53
0
54
0
        if (sig < 0)
55
0
                return 0;
56
0
57
0
        if (sig > 0) {
58
0
                if (sigaction(sig, sa, NULL) < 0)
59
0
                        r = -errno;
60
0
        }
61
0
62
0
        while ((sig = va_arg(ap, int)) >= 0) {
63
0
64
0
                if (sig == 0)
65
0
                        continue;
66
0
67
0
                if (sigaction(sig, sa, NULL) < 0) {
68
0
                        if (r >= 0)
69
0
                                r = -errno;
70
0
                }
71
0
        }
72
0
73
0
        return r;
74
0
}
75
76
0
int sigaction_many(const struct sigaction *sa, ...) {
77
0
        va_list ap;
78
0
        int r;
79
0
80
0
        va_start(ap, sa);
81
0
        r = sigaction_many_ap(sa, 0, ap);
82
0
        va_end(ap);
83
0
84
0
        return r;
85
0
}
86
87
0
int ignore_signals(int sig, ...) {
88
0
89
0
        static const struct sigaction sa = {
90
0
                .sa_handler = SIG_IGN,
91
0
                .sa_flags = SA_RESTART,
92
0
        };
93
0
94
0
        va_list ap;
95
0
        int r;
96
0
97
0
        va_start(ap, sig);
98
0
        r = sigaction_many_ap(&sa, sig, ap);
99
0
        va_end(ap);
100
0
101
0
        return r;
102
0
}
103
104
0
int default_signals(int sig, ...) {
105
0
106
0
        static const struct sigaction sa = {
107
0
                .sa_handler = SIG_DFL,
108
0
                .sa_flags = SA_RESTART,
109
0
        };
110
0
111
0
        va_list ap;
112
0
        int r;
113
0
114
0
        va_start(ap, sig);
115
0
        r = sigaction_many_ap(&sa, sig, ap);
116
0
        va_end(ap);
117
0
118
0
        return r;
119
0
}
120
121
0
static int sigset_add_many_ap(sigset_t *ss, va_list ap) {
122
0
        int sig, r = 0;
123
0
124
0
        assert(ss);
125
0
126
0
        while ((sig = va_arg(ap, int)) >= 0) {
127
0
128
0
                if (sig == 0)
129
0
                        continue;
130
0
131
0
                if (sigaddset(ss, sig) < 0) {
132
0
                        if (r >= 0)
133
0
                                r = -errno;
134
0
                }
135
0
        }
136
0
137
0
        return r;
138
0
}
139
140
0
int sigset_add_many(sigset_t *ss, ...) {
141
0
        va_list ap;
142
0
        int r;
143
0
144
0
        va_start(ap, ss);
145
0
        r = sigset_add_many_ap(ss, ap);
146
0
        va_end(ap);
147
0
148
0
        return r;
149
0
}
150
151
0
int sigprocmask_many(int how, sigset_t *old, ...) {
152
0
        va_list ap;
153
0
        sigset_t ss;
154
0
        int r;
155
0
156
0
        if (sigemptyset(&ss) < 0)
157
0
                return -errno;
158
0
159
0
        va_start(ap, old);
160
0
        r = sigset_add_many_ap(&ss, ap);
161
0
        va_end(ap);
162
0
163
0
        if (r < 0)
164
0
                return r;
165
0
166
0
        if (sigprocmask(how, &ss, old) < 0)
167
0
                return -errno;
168
0
169
0
        return 0;
170
0
}
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
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
209
210
16
const char *signal_to_string(int signo) {
211
16
        static thread_local char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1];
212
16
        const char *name;
213
16
214
16
        name = __signal_to_string(signo);
215
16
        if (name)
216
16
                return name;
217
0
218
0
        if (signo >= SIGRTMIN && signo <= SIGRTMAX)
219
0
                xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
220
0
        else
221
0
                xsprintf(buf, "%d", signo);
222
0
223
0
        return buf;
224
0
}
225
226
13.3k
int signal_from_string(const char *s) {
227
13.3k
        const char *p;
228
13.3k
        int signo, r;
229
13.3k
230
13.3k
        /* Check that the input is a signal number. */
231
13.3k
        if (safe_atoi(s, &signo) >= 0) {
232
1.34k
                if (SIGNAL_VALID(signo))
233
420
                        return signo;
234
922
                else
235
922
                        return -ERANGE;
236
12.0k
        }
237
12.0k
238
12.0k
        /* Drop "SIG" prefix. */
239
12.0k
        if (startswith(s, "SIG"))
240
499
                s += 3;
241
12.0k
242
12.0k
        /* Check that the input is a signal name. */
243
12.0k
        signo = __signal_from_string(s);
244
12.0k
        if (signo > 0)
245
399
                return signo;
246
11.6k
247
11.6k
        /* Check that the input is RTMIN or
248
11.6k
         * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
249
11.6k
        p = startswith(s, "RTMIN");
250
11.6k
        if (p) {
251
4.90k
                if (*p == '\0')
252
398
                        return SIGRTMIN;
253
4.50k
                if (*p != '+')
254
3.15k
                        return -EINVAL;
255
1.35k
256
1.35k
                r = safe_atoi(p, &signo);
257
1.35k
                if (r < 0)
258
456
                        return r;
259
895
260
895
                if (signo < 0 || signo > SIGRTMAX - SIGRTMIN)
261
895
                        return -ERANGE;
262
400
263
400
                return signo + SIGRTMIN;
264
400
        }
265
6.73k
266
6.73k
        /* Check that the input is RTMAX or
267
6.73k
         * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
268
6.73k
        p = startswith(s, "RTMAX");
269
6.73k
        if (p) {
270
2.33k
                if (*p == '\0')
271
645
                        return SIGRTMAX;
272
1.68k
                if (*p != '-')
273
403
                        return -EINVAL;
274
1.28k
275
1.28k
                r = safe_atoi(p, &signo);
276
1.28k
                if (r < 0)
277
408
                        return r;
278
874
279
874
                if (signo > 0 || signo < SIGRTMIN - SIGRTMAX)
280
874
                        return -ERANGE;
281
402
282
402
                return signo + SIGRTMAX;
283
402
        }
284
4.40k
285
4.40k
        return -EINVAL;
286
4.40k
}
287
288
0
void nop_signal_handler(int sig) {
289
0
        /* nothing here */
290
0
}