Commit | Line | Data |
---|---|---|
d983a10b PE |
1 | /* sig2str.c -- convert between signal names and numbers |
2 | ||
9ff99d22 | 3 | Copyright (C) 2002, 2004, 2006, 2009-2013 Free Software Foundation, Inc. |
d983a10b PE |
4 | |
5 | This program is free software: you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 3 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
17 | ||
18 | /* Written by Paul Eggert. */ | |
19 | ||
20 | #include <config.h> | |
21 | ||
22 | #include <limits.h> | |
23 | #include <signal.h> | |
24 | #include <stdlib.h> | |
25 | #include <stdio.h> | |
26 | #include <string.h> | |
27 | ||
28 | #include "sig2str.h" | |
29 | ||
30 | #ifndef SIGRTMIN | |
31 | # define SIGRTMIN 0 | |
32 | # undef SIGRTMAX | |
33 | #endif | |
34 | #ifndef SIGRTMAX | |
35 | # define SIGRTMAX (SIGRTMIN - 1) | |
36 | #endif | |
37 | ||
38 | #define NUMNAME(name) { SIG##name, #name } | |
39 | ||
40 | /* Signal names and numbers. Put the preferred name first. */ | |
41 | static struct numname { int num; char const name[8]; } numname_table[] = | |
42 | { | |
43 | /* Signals required by POSIX 1003.1-2001 base, listed in | |
44 | traditional numeric order where possible. */ | |
45 | #ifdef SIGHUP | |
46 | NUMNAME (HUP), | |
47 | #endif | |
48 | #ifdef SIGINT | |
49 | NUMNAME (INT), | |
50 | #endif | |
51 | #ifdef SIGQUIT | |
52 | NUMNAME (QUIT), | |
53 | #endif | |
54 | #ifdef SIGILL | |
55 | NUMNAME (ILL), | |
56 | #endif | |
57 | #ifdef SIGTRAP | |
58 | NUMNAME (TRAP), | |
59 | #endif | |
60 | #ifdef SIGABRT | |
61 | NUMNAME (ABRT), | |
62 | #endif | |
63 | #ifdef SIGFPE | |
64 | NUMNAME (FPE), | |
65 | #endif | |
66 | #ifdef SIGKILL | |
67 | NUMNAME (KILL), | |
68 | #endif | |
69 | #ifdef SIGSEGV | |
70 | NUMNAME (SEGV), | |
71 | #endif | |
72 | /* On Haiku, SIGSEGV == SIGBUS, but we prefer SIGSEGV to match | |
73 | strsignal.c output, so SIGBUS must be listed second. */ | |
74 | #ifdef SIGBUS | |
75 | NUMNAME (BUS), | |
76 | #endif | |
77 | #ifdef SIGPIPE | |
78 | NUMNAME (PIPE), | |
79 | #endif | |
80 | #ifdef SIGALRM | |
81 | NUMNAME (ALRM), | |
82 | #endif | |
83 | #ifdef SIGTERM | |
84 | NUMNAME (TERM), | |
85 | #endif | |
86 | #ifdef SIGUSR1 | |
87 | NUMNAME (USR1), | |
88 | #endif | |
89 | #ifdef SIGUSR2 | |
90 | NUMNAME (USR2), | |
91 | #endif | |
92 | #ifdef SIGCHLD | |
93 | NUMNAME (CHLD), | |
94 | #endif | |
95 | #ifdef SIGURG | |
96 | NUMNAME (URG), | |
97 | #endif | |
98 | #ifdef SIGSTOP | |
99 | NUMNAME (STOP), | |
100 | #endif | |
101 | #ifdef SIGTSTP | |
102 | NUMNAME (TSTP), | |
103 | #endif | |
104 | #ifdef SIGCONT | |
105 | NUMNAME (CONT), | |
106 | #endif | |
107 | #ifdef SIGTTIN | |
108 | NUMNAME (TTIN), | |
109 | #endif | |
110 | #ifdef SIGTTOU | |
111 | NUMNAME (TTOU), | |
112 | #endif | |
113 | ||
114 | /* Signals required by POSIX 1003.1-2001 with the XSI extension. */ | |
115 | #ifdef SIGSYS | |
116 | NUMNAME (SYS), | |
117 | #endif | |
118 | #ifdef SIGPOLL | |
119 | NUMNAME (POLL), | |
120 | #endif | |
121 | #ifdef SIGVTALRM | |
122 | NUMNAME (VTALRM), | |
123 | #endif | |
124 | #ifdef SIGPROF | |
125 | NUMNAME (PROF), | |
126 | #endif | |
127 | #ifdef SIGXCPU | |
128 | NUMNAME (XCPU), | |
129 | #endif | |
130 | #ifdef SIGXFSZ | |
131 | NUMNAME (XFSZ), | |
132 | #endif | |
133 | ||
134 | /* Unix Version 7. */ | |
135 | #ifdef SIGIOT | |
136 | NUMNAME (IOT), /* Older name for ABRT. */ | |
137 | #endif | |
138 | #ifdef SIGEMT | |
139 | NUMNAME (EMT), | |
140 | #endif | |
141 | ||
142 | /* USG Unix. */ | |
143 | #ifdef SIGPHONE | |
144 | NUMNAME (PHONE), | |
145 | #endif | |
146 | #ifdef SIGWIND | |
147 | NUMNAME (WIND), | |
148 | #endif | |
149 | ||
150 | /* Unix System V. */ | |
151 | #ifdef SIGCLD | |
152 | NUMNAME (CLD), | |
153 | #endif | |
154 | #ifdef SIGPWR | |
155 | NUMNAME (PWR), | |
156 | #endif | |
157 | ||
158 | /* GNU/Linux 2.2 and Solaris 8. */ | |
159 | #ifdef SIGCANCEL | |
160 | NUMNAME (CANCEL), | |
161 | #endif | |
162 | #ifdef SIGLWP | |
163 | NUMNAME (LWP), | |
164 | #endif | |
165 | #ifdef SIGWAITING | |
166 | NUMNAME (WAITING), | |
167 | #endif | |
168 | #ifdef SIGFREEZE | |
169 | NUMNAME (FREEZE), | |
170 | #endif | |
171 | #ifdef SIGTHAW | |
172 | NUMNAME (THAW), | |
173 | #endif | |
174 | #ifdef SIGLOST | |
175 | NUMNAME (LOST), | |
176 | #endif | |
177 | #ifdef SIGWINCH | |
178 | NUMNAME (WINCH), | |
179 | #endif | |
180 | ||
181 | /* GNU/Linux 2.2. */ | |
182 | #ifdef SIGINFO | |
183 | NUMNAME (INFO), | |
184 | #endif | |
185 | #ifdef SIGIO | |
186 | NUMNAME (IO), | |
187 | #endif | |
188 | #ifdef SIGSTKFLT | |
189 | NUMNAME (STKFLT), | |
190 | #endif | |
191 | ||
192 | /* AIX 5L. */ | |
193 | #ifdef SIGDANGER | |
194 | NUMNAME (DANGER), | |
195 | #endif | |
196 | #ifdef SIGGRANT | |
197 | NUMNAME (GRANT), | |
198 | #endif | |
199 | #ifdef SIGMIGRATE | |
200 | NUMNAME (MIGRATE), | |
201 | #endif | |
202 | #ifdef SIGMSG | |
203 | NUMNAME (MSG), | |
204 | #endif | |
205 | #ifdef SIGPRE | |
206 | NUMNAME (PRE), | |
207 | #endif | |
208 | #ifdef SIGRETRACT | |
209 | NUMNAME (RETRACT), | |
210 | #endif | |
211 | #ifdef SIGSAK | |
212 | NUMNAME (SAK), | |
213 | #endif | |
214 | #ifdef SIGSOUND | |
215 | NUMNAME (SOUND), | |
216 | #endif | |
217 | ||
218 | /* Older AIX versions. */ | |
219 | #ifdef SIGALRM1 | |
220 | NUMNAME (ALRM1), /* unknown; taken from Bash 2.05 */ | |
221 | #endif | |
222 | #ifdef SIGKAP | |
223 | NUMNAME (KAP), /* Older name for SIGGRANT. */ | |
224 | #endif | |
225 | #ifdef SIGVIRT | |
226 | NUMNAME (VIRT), /* unknown; taken from Bash 2.05 */ | |
227 | #endif | |
228 | #ifdef SIGWINDOW | |
229 | NUMNAME (WINDOW), /* Older name for SIGWINCH. */ | |
230 | #endif | |
231 | ||
232 | /* BeOS */ | |
233 | #ifdef SIGKILLTHR | |
234 | NUMNAME (KILLTHR), | |
235 | #endif | |
236 | ||
237 | /* Older HP-UX versions. */ | |
238 | #ifdef SIGDIL | |
239 | NUMNAME (DIL), | |
240 | #endif | |
241 | ||
242 | /* Korn shell and Bash, of uncertain vintage. */ | |
243 | { 0, "EXIT" } | |
244 | }; | |
245 | ||
246 | #define NUMNAME_ENTRIES (sizeof numname_table / sizeof numname_table[0]) | |
247 | ||
248 | /* ISDIGIT differs from isdigit, as follows: | |
249 | - Its arg may be any int or unsigned int; it need not be an unsigned char | |
250 | or EOF. | |
251 | - It's typically faster. | |
252 | POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to | |
253 | isdigit unless it's important to use the locale's definition | |
254 | of "digit" even when the host does not conform to POSIX. */ | |
255 | #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) | |
256 | ||
257 | /* Convert the signal name SIGNAME to a signal number. Return the | |
258 | signal number if successful, -1 otherwise. */ | |
259 | ||
260 | static int | |
261 | str2signum (char const *signame) | |
262 | { | |
263 | if (ISDIGIT (*signame)) | |
264 | { | |
265 | char *endp; | |
266 | long int n = strtol (signame, &endp, 10); | |
267 | if (! *endp && n <= SIGNUM_BOUND) | |
268 | return n; | |
269 | } | |
270 | else | |
271 | { | |
272 | unsigned int i; | |
273 | for (i = 0; i < NUMNAME_ENTRIES; i++) | |
274 | if (strcmp (numname_table[i].name, signame) == 0) | |
275 | return numname_table[i].num; | |
276 | ||
277 | { | |
278 | char *endp; | |
279 | int rtmin = SIGRTMIN; | |
280 | int rtmax = SIGRTMAX; | |
281 | ||
282 | if (0 < rtmin && strncmp (signame, "RTMIN", 5) == 0) | |
283 | { | |
284 | long int n = strtol (signame + 5, &endp, 10); | |
285 | if (! *endp && 0 <= n && n <= rtmax - rtmin) | |
286 | return rtmin + n; | |
287 | } | |
288 | else if (0 < rtmax && strncmp (signame, "RTMAX", 5) == 0) | |
289 | { | |
290 | long int n = strtol (signame + 5, &endp, 10); | |
291 | if (! *endp && rtmin - rtmax <= n && n <= 0) | |
292 | return rtmax + n; | |
293 | } | |
294 | } | |
295 | } | |
296 | ||
297 | return -1; | |
298 | } | |
299 | ||
300 | /* Convert the signal name SIGNAME to the signal number *SIGNUM. | |
301 | Return 0 if successful, -1 otherwise. */ | |
302 | ||
303 | int | |
304 | str2sig (char const *signame, int *signum) | |
305 | { | |
306 | *signum = str2signum (signame); | |
307 | return *signum < 0 ? -1 : 0; | |
308 | } | |
309 | ||
310 | /* Convert SIGNUM to a signal name in SIGNAME. SIGNAME must point to | |
311 | a buffer of at least SIG2STR_MAX bytes. Return 0 if successful, -1 | |
312 | otherwise. */ | |
313 | ||
314 | int | |
315 | sig2str (int signum, char *signame) | |
316 | { | |
317 | unsigned int i; | |
318 | for (i = 0; i < NUMNAME_ENTRIES; i++) | |
319 | if (numname_table[i].num == signum) | |
320 | { | |
321 | strcpy (signame, numname_table[i].name); | |
322 | return 0; | |
323 | } | |
324 | ||
325 | { | |
326 | int rtmin = SIGRTMIN; | |
327 | int rtmax = SIGRTMAX; | |
328 | ||
329 | if (! (rtmin <= signum && signum <= rtmax)) | |
330 | return -1; | |
331 | ||
332 | if (signum <= rtmin + (rtmax - rtmin) / 2) | |
333 | { | |
334 | int delta = signum - rtmin; | |
335 | sprintf (signame, delta ? "RTMIN+%d" : "RTMIN", delta); | |
336 | } | |
337 | else | |
338 | { | |
339 | int delta = rtmax - signum; | |
340 | sprintf (signame, delta ? "RTMAX-%d" : "RTMAX", delta); | |
341 | } | |
342 | ||
343 | return 0; | |
344 | } | |
345 | } |