- add a colorful "valid HTML 4.01 Transitional" button to be able to check the refere...
[oweals/busybox.git] / 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  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9  */
10
11 #include <signal.h>
12 #include <ctype.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16
17 #include "libbb.h"
18
19 struct signal_name {
20         const char *name;
21         int number;
22 };
23
24 static const struct signal_name signames[] = {
25         /* POSIX signals */
26         { "EXIT",       0 },            /* 0 */
27         { "HUP",        SIGHUP },       /* 1 */
28         { "INT",        SIGINT },       /* 2 */
29         { "QUIT",       SIGQUIT },      /* 3 */
30         { "ILL",        SIGILL },       /* 4 */
31         { "ABRT",       SIGABRT },      /* 6 */
32         { "FPE",        SIGFPE },       /* 8 */
33         { "KILL",       SIGKILL },      /* 9 */
34         { "SEGV",       SIGSEGV },      /* 11 */
35         { "PIPE",       SIGPIPE },      /* 13 */
36         { "ALRM",       SIGALRM },      /* 14 */
37         { "TERM",       SIGTERM },      /* 15 */
38         { "USR1",       SIGUSR1 },      /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */
39         { "USR2",       SIGUSR2 },      /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */
40         { "CHLD",       SIGCHLD },      /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */
41         { "CONT",       SIGCONT },      /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */
42         { "STOP",       SIGSTOP },      /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */
43         { "TSTP",       SIGTSTP },      /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */
44         { "TTIN",       SIGTTIN },      /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */
45         { "TTOU",       SIGTTOU },      /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */
46         /* Miscellaneous other signals */
47 #ifdef SIGTRAP
48         { "TRAP",       SIGTRAP },      /* 5 */
49 #endif
50 #ifdef SIGIOT
51         { "IOT",        SIGIOT },       /* 6, same as SIGABRT */
52 #endif
53 #ifdef SIGEMT
54         { "EMT",        SIGEMT },       /* 7 (mips,alpha,sparc*) */
55 #endif
56 #ifdef SIGBUS
57         { "BUS",        SIGBUS },       /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */
58 #endif
59 #ifdef SIGSYS
60         { "SYS",        SIGSYS },       /* 12 (mips,alpha,sparc*) */
61 #endif
62 #ifdef SIGSTKFLT
63         { "STKFLT",     SIGSTKFLT },    /* 16 (arm,i386,m68k,ppc) */
64 #endif
65 #ifdef SIGURG
66         { "URG",        SIGURG },       /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */
67 #endif
68 #ifdef SIGIO
69         { "IO",         SIGIO },        /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */
70 #endif
71 #ifdef SIGPOLL
72         { "POLL",       SIGPOLL },      /* same as SIGIO */
73 #endif
74 #ifdef SIGCLD
75         { "CLD",        SIGCLD },       /* same as SIGCHLD (mips) */
76 #endif
77 #ifdef SIGXCPU
78         { "XCPU",       SIGXCPU },      /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */
79 #endif
80 #ifdef SIGXFSZ
81         { "XFSZ",       SIGXFSZ },      /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */
82 #endif
83 #ifdef SIGVTALRM
84         { "VTALRM",     SIGVTALRM },    /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */
85 #endif
86 #ifdef SIGPROF
87         { "PROF",       SIGPROF },      /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */
88 #endif
89 #ifdef SIGPWR
90         { "PWR",        SIGPWR },       /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */
91 #endif
92 #ifdef SIGINFO
93         { "INFO",       SIGINFO },      /* 29 (alpha) */
94 #endif
95 #ifdef SIGLOST
96         { "LOST",       SIGLOST },      /* 29 (arm,i386,m68k,ppc,sparc*) */
97 #endif
98 #ifdef SIGWINCH
99         { "WINCH",      SIGWINCH },     /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */
100 #endif
101 #ifdef SIGUNUSED
102         { "UNUSED",     SIGUNUSED },    /* 31 (arm,i386,m68k,ppc) */
103 #endif
104         {0, 0}
105 };
106
107 /*
108         if str_sig == NULL returned signal name [*signo],
109         if str_sig != NULL - set *signo from signal_name,
110                 findings with digit number or with or without SIG-prefix name
111
112         if startnum=0 flag for support finding zero signal,
113                 but str_sig="0" always found, (hmm - standart or realize?)
114         if startnum<0 returned reverse signal_number  <-> signal_name
115         if found error - returned NULL
116
117 */
118
119 const char *
120 u_signal_names(const char *str_sig, int *signo, int startnum)
121 {
122         static char retstr[16];
123         const struct signal_name *s = signames;
124         static const char prefix[] = "SIG";
125         const char *sptr;
126
127         if(startnum)
128                 s++;
129         if(str_sig==NULL) {
130                 while (s->name != 0) {
131                         if(s->number == *signo)
132                                 break;
133                         s++;
134                 }
135         } else {
136                 if (isdigit(((unsigned char)*str_sig))) {
137                         char *endp;
138                         long int sn = strtol(str_sig, &endp, 10);
139                         /* test correct and overflow */
140                         if(*endp == 0 && sn >= 0 && sn < NSIG) {
141                                 *signo = (int)sn;
142                                 /* test for unnamed */
143                                 sptr = u_signal_names(0, signo, 0);
144                                 if(sptr==NULL)
145                                         return NULL;
146                                 if(sn!=0)
147                                         sptr += 3;
148                                 return sptr;
149                         }
150                 } else {
151                         sptr = str_sig;
152                         while (s->name != 0) {
153                                 if (strcasecmp(s->name, sptr) == 0) {
154                                         *signo = s->number;
155                                         if(startnum<0) {
156                                                 sprintf(retstr, "%d", *signo);
157                                                 return retstr;
158                                         }
159                                         break;
160                                 }
161                                 if(s!=signames && sptr == str_sig &&
162                                                 strncasecmp(sptr, prefix, 3) == 0) {
163                                         sptr += 3;      /* strlen(prefix) */
164                                         continue;
165                                 }
166                                 sptr = str_sig;
167                                 s++;
168                         }
169                 }
170         }
171         if(s->name==0)
172                 return NULL;
173         if(s!=signames)
174                 strcpy(retstr, prefix);
175          else
176                 retstr[0] = 0;
177         return strcat(retstr, s->name);
178 }