• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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