.
[coreutils.git] / lib / sig2str.c
blobf1eec22bf94c061df81bf7e2cf1fe72a595ee35e
1 /* sig2str.c -- convert between signal names and numbers
3 Copyright (C) 2002 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 2, or (at your option)
8 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, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 /* Written by Paul Eggert. */
21 #if HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #include <limits.h>
26 #include <signal.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
31 #include "sig2str.h"
33 #ifndef SIGRTMIN
34 # define SIGRTMIN 0
35 # undef SIGRTMAX
36 #endif
37 #ifndef SIGRTMAX
38 # define SIGRTMAX (SIGRTMIN - 1)
39 #endif
41 #define NUMNAME(name) { SIG##name, #name }
43 /* Signal names and numbers. Put the preferred name first. */
44 static struct numname { int num; char const name[8]; } numname_table[] =
46 /* Signals required by POSIX 1003.1-2001 base, listed in
47 traditional numeric order. */
48 #ifdef SIGHUP
49 NUMNAME (HUP),
50 #endif
51 #ifdef SIGINT
52 NUMNAME (INT),
53 #endif
54 #ifdef SIGQUIT
55 NUMNAME (QUIT),
56 #endif
57 #ifdef SIGILL
58 NUMNAME (ILL),
59 #endif
60 #ifdef SIGTRAP
61 NUMNAME (TRAP),
62 #endif
63 #ifdef SIGABRT
64 NUMNAME (ABRT),
65 #endif
66 #ifdef SIGFPE
67 NUMNAME (FPE),
68 #endif
69 #ifdef SIGKILL
70 NUMNAME (KILL),
71 #endif
72 #ifdef SIGBUS
73 NUMNAME (BUS),
74 #endif
75 #ifdef SIGSEGV
76 NUMNAME (SEGV),
77 #endif
78 #ifdef SIGPIPE
79 NUMNAME (PIPE),
80 #endif
81 #ifdef SIGALRM
82 NUMNAME (ALRM),
83 #endif
84 #ifdef SIGTERM
85 NUMNAME (TERM),
86 #endif
87 #ifdef SIGUSR1
88 NUMNAME (USR1),
89 #endif
90 #ifdef SIGUSR2
91 NUMNAME (USR2),
92 #endif
93 #ifdef SIGCHLD
94 NUMNAME (CHLD),
95 #endif
96 #ifdef SIGURG
97 NUMNAME (URG),
98 #endif
99 #ifdef SIGSTOP
100 NUMNAME (STOP),
101 #endif
102 #ifdef SIGTSTP
103 NUMNAME (TSTP),
104 #endif
105 #ifdef SIGCONT
106 NUMNAME (CONT),
107 #endif
108 #ifdef SIGTTIN
109 NUMNAME (TTIN),
110 #endif
111 #ifdef SIGTTOU
112 NUMNAME (TTOU),
113 #endif
115 /* Signals required by POSIX 1003.1-2001 with the XSI extension. */
116 #ifdef SIGSYS
117 NUMNAME (SYS),
118 #endif
119 #ifdef SIGPOLL
120 NUMNAME (POLL),
121 #endif
122 #ifdef SIGVTALRM
123 NUMNAME (VTALRM),
124 #endif
125 #ifdef SIGPROF
126 NUMNAME (PROF),
127 #endif
128 #ifdef SIGXCPU
129 NUMNAME (XCPU),
130 #endif
131 #ifdef SIGXFSZ
132 NUMNAME (XFSZ),
133 #endif
135 /* Unix Version 7. */
136 #ifdef SIGIOT
137 NUMNAME (IOT), /* Older name for ABRT. */
138 #endif
139 #ifdef SIGEMT
140 NUMNAME (EMT),
141 #endif
143 /* USG Unix. */
144 #ifdef SIGPHONE
145 NUMNAME (PHONE),
146 #endif
147 #ifdef SIGWIND
148 NUMNAME (WIND),
149 #endif
151 /* Unix System V. */
152 #ifdef SIGCLD
153 NUMNAME (CLD),
154 #endif
155 #ifdef SIGPWR
156 NUMNAME (PWR),
157 #endif
159 /* GNU/Linux 2.2 and Solaris 8. */
160 #ifdef SIGCANCEL
161 NUMNAME (CANCEL),
162 #endif
163 #ifdef SIGLWP
164 NUMNAME (LWP),
165 #endif
166 #ifdef SIGWAITING
167 NUMNAME (WAITING),
168 #endif
169 #ifdef SIGFREEZE
170 NUMNAME (FREEZE),
171 #endif
172 #ifdef SIGTHAW
173 NUMNAME (THAW),
174 #endif
175 #ifdef SIGLOST
176 NUMNAME (LOST),
177 #endif
178 #ifdef SIGWINCH
179 NUMNAME (WINCH),
180 #endif
182 /* GNU/Linux 2.2. */
183 #ifdef SIGINFO
184 NUMNAME (INFO),
185 #endif
186 #ifdef SIGIO
187 NUMNAME (IO),
188 #endif
189 #ifdef SIGSTKFLT
190 NUMNAME (STKFLT),
191 #endif
193 /* AIX 5L. */
194 #ifdef SIGDANGER
195 NUMNAME (DANGER),
196 #endif
197 #ifdef SIGGRANT
198 NUMNAME (GRANT),
199 #endif
200 #ifdef SIGMIGRATE
201 NUMNAME (MIGRATE),
202 #endif
203 #ifdef SIGMSG
204 NUMNAME (MSG),
205 #endif
206 #ifdef SIGPRE
207 NUMNAME (PRE),
208 #endif
209 #ifdef SIGRETRACT
210 NUMNAME (RETRACT),
211 #endif
212 #ifdef SIGSAK
213 NUMNAME (SAK),
214 #endif
215 #ifdef SIGSOUND
216 NUMNAME (SOUND),
217 #endif
219 /* Older AIX versions. */
220 #ifdef SIGALRM1
221 NUMNAME (ALRM1), /* unknown; taken from Bash 2.05 */
222 #endif
223 #ifdef SIGKAP
224 NUMNAME (KAP), /* Older name for SIGGRANT. */
225 #endif
226 #ifdef SIGVIRT
227 NUMNAME (VIRT), /* unknown; taken from Bash 2.05 */
228 #endif
229 #ifdef SIGWINDOW
230 NUMNAME (WINDOW), /* Older name for SIGWINCH. */
231 #endif
233 /* BeOS */
234 #ifdef SIGKILLTHR
235 NUMNAME (KILLTHR),
236 #endif
238 /* Older HP-UX versions. */
239 #ifdef SIGDIL
240 NUMNAME (DIL),
241 #endif
243 /* Korn shell and Bash, of uncertain vintage. */
244 { 0, "EXIT" }
247 #define NUMNAME_ENTRIES (sizeof numname_table / sizeof numname_table[0])
249 /* ISDIGIT differs from isdigit, as follows:
250 - Its arg may be any int or unsigned int; it need not be an unsigned char.
251 - It's guaranteed to evaluate its argument exactly once.
252 - It's typically faster.
253 POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
254 ISDIGIT_LOCALE unless it's important to use the locale's definition
255 of `digit' even when the host does not conform to POSIX. */
256 #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
258 /* Convert the signal name SIGNAME to a signal number. Return the
259 signal number if successful, -1 otherwise. */
261 static int
262 str2signum (char const *signame)
264 if (ISDIGIT (*signame))
266 char *endp;
267 long int n = strtol (signame, &endp, 10);
268 if (! *endp && n <= SIGNUM_BOUND)
269 return n;
271 else
273 unsigned i;
274 for (i = 0; i < NUMNAME_ENTRIES; i++)
275 if (strcmp (numname_table[i].name, signame) == 0)
276 return numname_table[i].num;
279 char *endp;
280 int rtmin = SIGRTMIN;
281 int rtmax = SIGRTMAX;
283 if (0 < rtmin && strncmp (signame, "RTMIN", 5) == 0)
285 long int n = strtol (signame + 5, &endp, 10);
286 if (! *endp && 0 <= n && n <= rtmax - rtmin)
287 return rtmin + n;
289 else if (0 < rtmax && strncmp (signame, "RTMAX", 5) == 0)
291 long int n = strtol (signame + 5, &endp, 10);
292 if (! *endp && rtmin - rtmax <= n && n <= 0)
293 return rtmax + n;
298 return -1;
301 /* Convert the signal name SIGNAME to the signal number *SIGNUM.
302 Return 0 if successful, -1 otherwise. */
305 str2sig (char const *signame, int *signum)
307 *signum = str2signum (signame);
308 return *signum < 0 ? -1 : 0;
311 /* Convert SIGNUM to a signal name in SIGNAME. SIGNAME must point to
312 a buffer of at least SIG2STR_MAX bytes. Return 0 if successful, -1
313 otherwise. */
316 sig2str (int signum, char *signame)
318 unsigned i;
319 for (i = 0; i < NUMNAME_ENTRIES; i++)
320 if (numname_table[i].num == signum)
322 strcpy (signame, numname_table[i].name);
323 return 0;
327 int rtmin = SIGRTMIN;
328 int rtmax = SIGRTMAX;
330 if (! (rtmin <= signum && signum <= rtmax))
331 return -1;
333 if (signum <= rtmin + (rtmax - rtmin) / 2)
335 int delta = signum - rtmin;
336 sprintf (signame, delta ? "RTMIN+%d" : "RTMIN", delta);
338 else
340 int delta = rtmax - signum;
341 sprintf (signame, delta ? "RTMAX-%d" : "RTMAX", delta);
344 return 0;