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