exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / sig2str.c
blobc6b91e384980d76b34f474bd2367a7698bf98d89
1 /* sig2str.c -- convert between signal names and numbers
3 Copyright (C) 2002, 2004, 2006, 2009-2024 Free Software Foundation, Inc.
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.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Written by Paul Eggert. */
20 #include <config.h>
22 #include <limits.h>
23 #include <signal.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
28 #include "sig2str.h"
30 #ifndef SIGRTMIN
31 # define SIGRTMIN 0
32 # undef SIGRTMAX
33 #endif
34 #ifndef SIGRTMAX
35 # define SIGRTMAX (SIGRTMIN - 1)
36 #endif
38 #define NUMNAME(name) { SIG##name, #name }
40 /* Signal names and numbers. Put the preferred name first. */
41 static struct numname { int num; char const name[8]; } numname_table[] =
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
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
134 /* Unix Version 7. */
135 #ifdef SIGIOT
136 NUMNAME (IOT), /* Older name for ABRT. */
137 #endif
138 #ifdef SIGEMT
139 NUMNAME (EMT),
140 #endif
142 /* USG Unix. */
143 #ifdef SIGPHONE
144 NUMNAME (PHONE),
145 #endif
146 #ifdef SIGWIND
147 NUMNAME (WIND),
148 #endif
150 /* Unix System V. */
151 #ifdef SIGCLD
152 NUMNAME (CLD),
153 #endif
154 #ifdef SIGPWR
155 NUMNAME (PWR),
156 #endif
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
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
192 /* AIX 7. */
193 #ifdef SIGCPUFAIL
194 NUMNAME (CPUFAIL),
195 #endif
197 /* AIX 5L. */
198 #ifdef SIGDANGER
199 NUMNAME (DANGER),
200 #endif
201 #ifdef SIGGRANT
202 NUMNAME (GRANT),
203 #endif
204 #ifdef SIGMIGRATE
205 NUMNAME (MIGRATE),
206 #endif
207 #ifdef SIGMSG
208 NUMNAME (MSG),
209 #endif
210 #ifdef SIGPRE
211 NUMNAME (PRE),
212 #endif
213 #ifdef SIGRETRACT
214 NUMNAME (RETRACT),
215 #endif
216 #ifdef SIGSAK
217 NUMNAME (SAK),
218 #endif
219 #ifdef SIGSOUND
220 NUMNAME (SOUND),
221 #endif
223 /* Older AIX versions. */
224 #ifdef SIGALRM1
225 NUMNAME (ALRM1), /* unknown; taken from Bash 2.05 */
226 #endif
227 #ifdef SIGKAP
228 NUMNAME (KAP), /* Older name for SIGGRANT. */
229 #endif
230 #ifdef SIGVIRT
231 NUMNAME (VIRT), /* unknown; taken from Bash 2.05 */
232 #endif
233 #ifdef SIGWINDOW
234 NUMNAME (WINDOW), /* Older name for SIGWINCH. */
235 #endif
237 /* OpenBSD. */
238 #ifdef SIGTHR
239 NUMNAME (THR),
240 #endif
242 /* BeOS, Haiku */
243 #ifdef SIGKILLTHR
244 NUMNAME (KILLTHR),
245 #endif
247 /* Older HP-UX versions. */
248 #ifdef SIGDIL
249 NUMNAME (DIL),
250 #endif
252 /* native Windows */
253 #ifdef SIGBREAK
254 NUMNAME (BREAK),
255 #endif
257 /* Korn shell and Bash, of uncertain vintage. */
258 { 0, "EXIT" }
261 #define NUMNAME_ENTRIES (sizeof numname_table / sizeof numname_table[0])
263 /* ISDIGIT differs from isdigit, as follows:
264 - Its arg may be any int or unsigned int; it need not be an unsigned char
265 or EOF.
266 - It's typically faster.
267 POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
268 isdigit unless it's important to use the locale's definition
269 of "digit" even when the host does not conform to POSIX. */
270 #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
272 /* Convert the signal name SIGNAME to a signal number. Return the
273 signal number if successful, -1 otherwise. */
275 static int
276 str2signum (char const *signame)
278 if (ISDIGIT (*signame))
280 char *endp;
281 long int n = strtol (signame, &endp, 10);
282 if (! *endp && n <= SIGNUM_BOUND)
283 return n;
285 else
287 unsigned int i;
288 for (i = 0; i < NUMNAME_ENTRIES; i++)
289 if (strcmp (numname_table[i].name, signame) == 0)
290 return numname_table[i].num;
293 char *endp;
294 int rtmin = SIGRTMIN;
295 int rtmax = SIGRTMAX;
297 if (0 < rtmin && strncmp (signame, "RTMIN", 5) == 0)
299 long int n = strtol (signame + 5, &endp, 10);
300 if (! *endp && 0 <= n && n <= rtmax - rtmin)
301 return rtmin + n;
303 else if (0 < rtmax && strncmp (signame, "RTMAX", 5) == 0)
305 long int n = strtol (signame + 5, &endp, 10);
306 if (! *endp && rtmin - rtmax <= n && n <= 0)
307 return rtmax + n;
312 return -1;
315 /* Convert the signal name SIGNAME to the signal number *SIGNUM.
316 Return 0 if successful, -1 otherwise. */
319 str2sig (char const *signame, int *signum)
321 *signum = str2signum (signame);
322 return *signum < 0 ? -1 : 0;
325 /* Convert SIGNUM to a signal name in SIGNAME. SIGNAME must point to
326 a buffer of at least SIG2STR_MAX bytes. Return 0 if successful, -1
327 otherwise. */
330 sig2str (int signum, char *signame)
332 unsigned int i;
333 for (i = 0; i < NUMNAME_ENTRIES; i++)
334 if (numname_table[i].num == signum)
336 strcpy (signame, numname_table[i].name);
337 return 0;
341 int rtmin = SIGRTMIN;
342 int rtmax = SIGRTMAX;
343 int base, delta;
345 if (! (rtmin <= signum && signum <= rtmax))
346 return -1;
348 if (signum <= rtmin + (rtmax - rtmin) / 2)
350 strcpy (signame, "RTMIN");
351 base = rtmin;
353 else
355 strcpy (signame, "RTMAX");
356 base = rtmax;
359 delta = signum - base;
360 if (delta != 0)
361 sprintf (signame + 5, "%+d", delta);
362 return 0;