1 /*
2 * Copyright 1998-2002 by Albert Cahalan; all rights resered.
3 * This file may be used subject to the terms and conditions of the
4 * GNU Library General Public License Version 2, or any later version
5 * at your option, as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU Library General Public License for more details.
10 */
11 #include <signal.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include "sig.h"
16
17 /* Linux signals:
18 *
19 * SIGSYS is required by Unix98.
20 * SIGEMT is part of SysV, BSD, and ancient UNIX tradition.
21 *
22 * They are provided by these Linux ports: alpha, mips, sparc, and sparc64.
23 * You get SIGSTKFLT and SIGUNUSED instead on i386, m68k, ppc, and arm.
24 * (this is a Linux & libc bug -- both must be fixed)
25 *
26 * Total garbage: SIGIO SIGINFO SIGIOT SIGLOST SIGCLD
27 * (popular ones are handled as aliases)
28 * Nearly garbage: SIGSTKFLT SIGUNUSED (nothing else to fill slots)
29 */
30
31 /* Linux 2.3.29 replaces SIGUNUSED with the standard SIGSYS signal */
32 #ifndef SIGSYS
33 #warning Standards require that <signal.h> define SIGSYS
34 #define SIGSYS SIGUNUSED
35 #endif
36
37 /* If we see both, it is likely SIGSTKFLT (junk) was replaced. */
38 #ifdef SIGEMT
39 #undef SIGSTKFLT
40 #endif
41
42 #ifndef SIGRTMIN
43 #warning Standards require that <signal.h> define SIGRTMIN; assuming 32
44 #define SIGRTMIN 32
45 #endif
46
47 /* It seems the SPARC libc does not know the kernel supports SIGPWR. */
48 #ifndef SIGPWR
49 #warning Your header files lack SIGPWR. (assuming it is number 29)
50 #define SIGPWR 29
51 #endif
52
53 typedef struct mapstruct {
54 const char *name;
55 int num;
56 } mapstruct;
57
58 static const mapstruct sigtable[] = {
59 {"ABRT", SIGABRT}, /* IOT */
60 {"ALRM", SIGALRM},
61 {"BUS", SIGBUS},
62 {"CHLD", SIGCHLD}, /* CLD */
63 {"CONT", SIGCONT},
64 #ifdef SIGEMT
65 {"EMT", SIGEMT},
66 #endif
67 {"FPE", SIGFPE},
68 {"HUP", SIGHUP},
69 {"ILL", SIGILL},
70 {"INT", SIGINT},
71 {"KILL", SIGKILL},
72 {"PIPE", SIGPIPE},
73 {"POLL", SIGPOLL}, /* IO */
74 {"PROF", SIGPROF},
75 {"PWR", SIGPWR},
76 {"QUIT", SIGQUIT},
77 {"SEGV", SIGSEGV},
78 #ifdef SIGSTKFLT
79 {"STKFLT", SIGSTKFLT},
80 #endif
81 {"STOP", SIGSTOP},
82 {"SYS", SIGSYS}, /* UNUSED */
83 {"TERM", SIGTERM},
84 {"TRAP", SIGTRAP},
85 {"TSTP", SIGTSTP},
86 {"TTIN", SIGTTIN},
87 {"TTOU", SIGTTOU},
88 {"URG", SIGURG},
89 {"USR1", SIGUSR1},
90 {"USR2", SIGUSR2},
91 {"VTALRM", SIGVTALRM},
92 {"WINCH", SIGWINCH},
93 {"XCPU", SIGXCPU},
94 {"XFSZ", SIGXFSZ}
95 };
96
97 static const int number_of_signals = sizeof(sigtable) / sizeof(mapstruct);
98
compare_signal_names(const void * a,const void * b)99 static int compare_signal_names(const void *a, const void *b)
100 {
101 return strcasecmp(((const mapstruct *)a)->name,
102 ((const mapstruct *)b)->name);
103 }
104
105 /* return -1 on failure */
signal_name_to_number(const char * restrict name)106 int signal_name_to_number(const char *restrict name)
107 {
108 long val;
109 int offset;
110
111 /* clean up name */
112 if (!strncasecmp(name, "SIG", 3))
113 name += 3;
114
115 if (!strcasecmp(name, "CLD"))
116 return SIGCHLD;
117 if (!strcasecmp(name, "IO"))
118 return SIGPOLL;
119 if (!strcasecmp(name, "IOT"))
120 return SIGABRT;
121
122 /* search the table */
123 {
124 const mapstruct ms = { name, 0 };
125 const mapstruct *restrict const ptr = bsearch(&ms,
126 sigtable,
127 number_of_signals,
128 sizeof(mapstruct),
129 compare_signal_names);
130 if (ptr)
131 return ptr->num;
132 }
133
134 if (!strcasecmp(name, "RTMIN"))
135 return SIGRTMIN;
136 if (!strcasecmp(name, "EXIT"))
137 return 0;
138 if (!strcasecmp(name, "NULL"))
139 return 0;
140
141 offset = 0;
142 if (!strncasecmp(name, "RTMIN+", 6)) {
143 name += 6;
144 offset = SIGRTMIN;
145 }
146
147 /* not found, so try as a number */
148 {
149 char *endp;
150 val = strtol(name, &endp, 10);
151 if (*endp || endp == name)
152 return -1; /* not valid */
153 }
154 if (val + SIGRTMIN > 127)
155 return -1; /* not valid */
156 return val + offset;
157 }
158
signal_number_to_name(int signo)159 static const char *signal_number_to_name(int signo)
160 {
161 static char buf[32];
162 int n = number_of_signals;
163 signo &= 0x7f; /* need to process exit values too */
164 while (n--) {
165 if (sigtable[n].num == signo)
166 return sigtable[n].name;
167 }
168 if (signo == SIGRTMIN)
169 return "RTMIN";
170 if (signo)
171 sprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
172 else
173 strcpy(buf, "0"); /* AIX has NULL; Solaris has EXIT */
174 return buf;
175 }
176
print_given_signals(int argc,const char * restrict const * restrict argv,int max_line)177 int print_given_signals(int argc, const char *restrict const *restrict argv,
178 int max_line)
179 {
180 char buf[1280]; /* 128 signals, "RTMIN+xx" is largest */
181 int ret = 0; /* to be used as exit code by caller */
182 int place = 0; /* position on this line */
183 int amt;
184 if (argc > 128)
185 return 1;
186 while (argc--) {
187 char tmpbuf[16];
188 const char *restrict const txt = *argv;
189 if (*txt >= '0' && *txt <= '9') {
190 long val;
191 char *endp;
192 val = strtol(txt, &endp, 10);
193 if (*endp) {
194 fprintf(stderr, "Signal \"%s\" not known.\n",
195 txt);
196 ret = 1;
197 goto end;
198 }
199 amt = sprintf(tmpbuf, "%s", signal_number_to_name(val));
200 } else {
201 int sno;
202 sno = signal_name_to_number(txt);
203 if (sno == -1) {
204 fprintf(stderr, "Signal \"%s\" not known.\n",
205 txt);
206 ret = 1;
207 goto end;
208 }
209 amt = sprintf(tmpbuf, "%d", sno);
210 }
211
212 if (!place) {
213 strcpy(buf, tmpbuf);
214 place = amt;
215 goto end;
216 }
217 if (amt + place + 1 > max_line) {
218 printf("%s\n", buf);
219 strcpy(buf, tmpbuf);
220 place = amt;
221 goto end;
222 }
223 sprintf(buf + place, " %s", tmpbuf);
224 place += amt + 1;
225 end:
226 argv++;
227 }
228 if (place)
229 printf("%s\n", buf);
230 return ret;
231 }
232
pretty_print_signals(void)233 void pretty_print_signals(void)
234 {
235 int i = 0;
236 while (++i <= number_of_signals) {
237 int n;
238 n = printf("%2d %s", i, signal_number_to_name(i));
239 if (i % 7)
240 printf
241 (" \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
242 + n);
243 else
244 printf("\n");
245 }
246 if ((i - 1) % 7)
247 printf("\n");
248 }
249
unix_print_signals(void)250 void unix_print_signals(void)
251 {
252 int pos = 0;
253 int i = 0;
254 while (++i <= number_of_signals) {
255 if (i - 1)
256 printf("%c",
257 (pos > 73) ? (pos = 0, '\n') : (pos++, ' '));
258 pos += printf("%s", signal_number_to_name(i));
259 }
260 printf("\n");
261 }
262
263 /* sanity check */
264 static int init_signal_list(void) __attribute__ ((constructor));
init_signal_list(void)265 static int init_signal_list(void)
266 {
267 if (number_of_signals != 31) {
268 fprintf(stderr,
269 "WARNING: %d signals -- adjust and recompile.\n",
270 number_of_signals);
271 }
272 return 0;
273 }
274