This commit was manufactured by cvs2svn to create tag 'busybox_1_00'.
[oweals/busybox.git] / busybox / libbb / u_signal_names.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) many different people.
6  * If you wrote this, please acknowledge your work.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21  * USA
22  */
23
24 #include <signal.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29
30 struct signal_name {
31         const char *name;
32         int number;
33 };
34
35 static const struct signal_name signames[] = {
36         /* POSIX signals */
37         { "EXIT",       0 },            /* 0 */
38         { "HUP",        SIGHUP },       /* 1 */
39         { "INT",        SIGINT },       /* 2 */
40         { "QUIT",       SIGQUIT },      /* 3 */
41         { "ILL",        SIGILL },       /* 4 */
42         { "ABRT",       SIGABRT },      /* 6 */
43         { "FPE",        SIGFPE },       /* 8 */
44         { "KILL",       SIGKILL },      /* 9 */
45         { "SEGV",       SIGSEGV },      /* 11 */
46         { "PIPE",       SIGPIPE },      /* 13 */
47         { "ALRM",       SIGALRM },      /* 14 */
48         { "TERM",       SIGTERM },      /* 15 */
49         { "USR1",       SIGUSR1 },      /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */
50         { "USR2",       SIGUSR2 },      /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */
51         { "CHLD",       SIGCHLD },      /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */
52         { "CONT",       SIGCONT },      /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */
53         { "STOP",       SIGSTOP },      /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */
54         { "TSTP",       SIGTSTP },      /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */
55         { "TTIN",       SIGTTIN },      /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */
56         { "TTOU",       SIGTTOU },      /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */
57         /* Miscellaneous other signals */
58 #ifdef SIGTRAP
59         { "TRAP",       SIGTRAP },      /* 5 */
60 #endif
61 #ifdef SIGIOT
62         { "IOT",        SIGIOT },       /* 6, same as SIGABRT */
63 #endif
64 #ifdef SIGEMT
65         { "EMT",        SIGEMT },       /* 7 (mips,alpha,sparc*) */
66 #endif
67 #ifdef SIGBUS
68         { "BUS",        SIGBUS },       /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */
69 #endif
70 #ifdef SIGSYS
71         { "SYS",        SIGSYS },       /* 12 (mips,alpha,sparc*) */
72 #endif
73 #ifdef SIGSTKFLT
74         { "STKFLT",     SIGSTKFLT },    /* 16 (arm,i386,m68k,ppc) */
75 #endif
76 #ifdef SIGURG
77         { "URG",        SIGURG },       /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */
78 #endif
79 #ifdef SIGIO
80         { "IO",         SIGIO },        /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */
81 #endif
82 #ifdef SIGPOLL
83         { "POLL",       SIGPOLL },      /* same as SIGIO */
84 #endif
85 #ifdef SIGCLD
86         { "CLD",        SIGCLD },       /* same as SIGCHLD (mips) */
87 #endif
88 #ifdef SIGXCPU
89         { "XCPU",       SIGXCPU },      /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */
90 #endif
91 #ifdef SIGXFSZ
92         { "XFSZ",       SIGXFSZ },      /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */
93 #endif
94 #ifdef SIGVTALRM
95         { "VTALRM",     SIGVTALRM },    /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */
96 #endif
97 #ifdef SIGPROF
98         { "PROF",       SIGPROF },      /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */
99 #endif
100 #ifdef SIGPWR
101         { "PWR",        SIGPWR },       /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */
102 #endif
103 #ifdef SIGINFO
104         { "INFO",       SIGINFO },      /* 29 (alpha) */
105 #endif
106 #ifdef SIGLOST
107         { "LOST",       SIGLOST },      /* 29 (arm,i386,m68k,ppc,sparc*) */
108 #endif
109 #ifdef SIGWINCH
110         { "WINCH",      SIGWINCH },     /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */
111 #endif
112 #ifdef SIGUNUSED
113         { "UNUSED",     SIGUNUSED },    /* 31 (arm,i386,m68k,ppc) */
114 #endif
115         {0, 0}
116 };
117
118 /*
119         if str_sig == NULL returned signal name [*signo],
120         if str_sig != NULL - set *signo from signal_name,
121                 findings with digit number or with or without SIG-prefix name
122
123         if startnum=0 flag for support finding zero signal,
124                 but str_sig="0" always found, (hmm - standart or realize?)
125         if startnum<0 returned reverse signal_number  <-> signal_name
126         if found error - returned NULL
127
128 */
129
130 const char *
131 u_signal_names(const char *str_sig, int *signo, int startnum)
132 {
133         static char retstr[16];
134         const struct signal_name *s = signames;
135         static const char prefix[] = "SIG";
136         const char *sptr;
137
138         if(startnum)
139                 s++;
140         if(str_sig==NULL) {
141                 while (s->name != 0) {
142                         if(s->number == *signo)
143                                 break;
144                         s++;
145                 }
146         } else {
147                 if (isdigit(((unsigned char)*str_sig))) {
148                         char *endp;
149                         long int sn = strtol(str_sig, &endp, 10);
150                         /* test correct and overflow */
151                         if(*endp == 0 && sn >= 0 && sn < NSIG) {
152                                 *signo = (int)sn;
153                                 /* test for unnamed */
154                                 sptr = u_signal_names(0, signo, 0);
155                                 if(sptr==NULL)
156                                         return NULL;
157                                 if(sn!=0)
158                                         sptr += 3;
159                                 return sptr;
160                         }
161                 } else {
162                         sptr = str_sig;
163                         while (s->name != 0) {
164                                 if (strcasecmp(s->name, sptr) == 0) {
165                                         *signo = s->number;
166                                         if(startnum<0) {
167                                                 sprintf(retstr, "%d", *signo);
168                                                 return retstr;
169                                         }
170                                         break;
171                                 }
172                                 if(s!=signames && sptr == str_sig &&
173                                                 strncasecmp(sptr, prefix, 3) == 0) {
174                                         sptr += 3;      /* strlen(prefix) */
175                                         continue;
176                                 }
177                                 sptr = str_sig;
178                                 s++;
179                         }
180                 }
181         }
182         if(s->name==0)
183                 return NULL;
184         if(s!=signames)
185                 strcpy(retstr, prefix);
186          else
187                 retstr[0] = 0;
188         return strcat(retstr, s->name);
189 }