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