1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * Copyright (C) 2021 Matthew Joyce
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 /*
28 FUNCTION
29 <<sig2str>>, <<str2sig>>---Translate between signal number and name
30
31 INDEX
32 sig2str
33 INDEX
34 str2sig
35
36 SYNOPSIS
37 #include <signal.h>
38 int sig2str(int <[signum]>, char *<[str]>);
39
40 int str2sig(const char *restrict <[str]>, int *restrict <[pnum]>);
41
42 DESCRIPTION
43 The <<sig2str>> function translates the signal number specified by <[signum]> to
44 a signal name and stores this string in the location specified by <[str]>. The
45 application must ensure that <[str]> points to a location that can store the
46 string including the terminating null byte. The symbolic constant
47 <[SIG2STR_MAX]> defined in `<<signal.h>>' gives the maximum number of bytes
48 required.
49
50 The <<str2sig>> function translates the signal name in the string pointed to by
51 <[str]> to a signal number and stores this value in the location specified by
52 <[pnum]>.
53
54 RETURNS
55 <<sig2str>> returns <<0>> if <[signum]>> is a valid, supported signal number.
56 Otherwise, it returns <<-1>>.
57
58 <<str2sig>> returns <<0>> if it stores a value in the location pointed to by
59 <[pnum]>. Otherwise it returns <<-1>>.
60 */
61
62 #include <signal.h>
63 #include <string.h>
64 #include <stdio.h>
65 #include <stdlib.h>
66
67 #define SPACES_TO_N 6 /* Allows indexing to RT Signal number in str2sig */
68 #define NUM_OF_SIGS (sizeof(sig_array) / sizeof(sig_name_and_num))
69
70 typedef struct sig_name_and_num {
71 const char sig_name[8];
72 const int sig_num;
73 } sig_name_and_num;
74
75 static const sig_name_and_num sig_array[] = {
76 { "EXIT", 0 },
77 #ifdef SIGHUP
78 { "HUP", SIGHUP },
79 #endif
80 #ifdef SIGINT
81 { "INT", SIGINT },
82 #endif
83 #ifdef SIGQUIT
84 { "QUIT", SIGQUIT },
85 #endif
86 #ifdef SIGILL
87 { "ILL", SIGILL },
88 #endif
89 #ifdef SIGTRAP
90 { "TRAP", SIGTRAP },
91 #endif
92 #ifdef SIGABRT
93 { "ABRT", SIGABRT },
94 #endif
95 #ifdef SIGIOT
96 { "IOT", SIGIOT},
97 #endif
98 #ifdef SIGEMT
99 { "EMT", SIGEMT },
100 #endif
101 #ifdef SIGFPE
102 { "FPE", SIGFPE },
103 #endif
104 #ifdef SIGKILL
105 { "KILL", SIGKILL },
106 #endif
107 #ifdef SIGBUS
108 { "BUS", SIGBUS },
109 #endif
110 #ifdef SIGSEGV
111 { "SEGV", SIGSEGV },
112 #endif
113 #ifdef SIGSYS
114 { "SYS", SIGSYS },
115 #endif
116 #ifdef SIGPIPE
117 { "PIPE", SIGPIPE },
118 #endif
119 #ifdef SIGALRM
120 { "ALRM", SIGALRM },
121 #endif
122 #ifdef SIGTERM
123 { "TERM", SIGTERM },
124 #endif
125 #ifdef SIGURG
126 { "URG", SIGURG },
127 #endif
128 #ifdef SIGSTOP
129 { "STOP", SIGSTOP },
130 #endif
131 #ifdef SIGTSTP
132 { "TSTP", SIGTSTP },
133 #endif
134 #ifdef SIGCONT
135 { "CONT", SIGCONT },
136 #endif
137 #ifdef SIGCHLD
138 { "CHLD", SIGCHLD },
139 #endif
140 #ifdef SIGCLD
141 { "CLD", SIGCLD },
142 #endif
143 #ifdef SIGTTIN
144 { "TTIN", SIGTTIN },
145 #endif
146 #ifdef SIGTTOU
147 { "TTOU", SIGTTOU },
148 #endif
149 #ifdef SIGIO
150 { "IO", SIGIO },
151 #endif
152 #ifdef SIGPOLL
153 { "POLL", SIGPOLL },
154 #endif
155 #ifdef SIGWINCH
156 { "WINCH", SIGWINCH },
157 #endif
158 #ifdef SIGUSR1
159 { "USR1", SIGUSR1 },
160 #endif
161 #ifdef SIGUSR2
162 { "USR2", SIGUSR2 },
163 #endif
164 #ifdef SIGPWR
165 { "PWR", SIGPWR },
166 #endif
167 #ifdef SIGXCPU
168 { "XCPU", SIGXCPU },
169 #endif
170 #ifdef SIGXFSZ
171 { "XFSZ", SIGXFSZ },
172 #endif
173 #ifdef SIGVTALRM
174 { "VTALRM", SIGVTALRM },
175 #endif
176 #ifdef SIGPROF
177 { "PROF", SIGPROF },
178 #endif
179 #ifdef SIGLOST
180 { "LOST", SIGLOST },
181 #endif
182 /* The Issue 8 standard requires that SIGRTMIN and SIGRTMAX be included
183 * as valid results to be saved from calls to sig2str/str2sig. */
184 #ifdef SIGRTMIN
185 { "RTMIN", SIGRTMIN },
186 #endif
187 #ifdef SIGRTMAX
188 { "RTMAX", SIGRTMAX }
189 #endif
190 };
191
192 int
sig2str(int signum,char * str)193 sig2str(int signum, char *str)
194 {
195 const sig_name_and_num *sptr;
196
197 #if defined (SIGRTMIN) && defined (SIGRTMAX)
198 /* If signum falls in lower half of the real time signals range, define
199 * the saved str value as "RTMIN+n" according to the Issue 8 standard */
200 if ((SIGRTMIN + 1) <= signum &&
201 signum <= (SIGRTMIN + SIGRTMAX) / 2) {
202 sprintf(str, "RTMIN+%d", (signum-SIGRTMIN));
203 return 0;
204 }
205
206 /* If signum falls in upper half of the real time signals range, define
207 * the saved str value as "RTMAX-m" according to the Issue 8 standard */
208 if ((((SIGRTMIN + SIGRTMAX) / 2) + 1) <= signum &&
209 signum <= (SIGRTMAX - 1)) {
210 sprintf(str, "RTMAX-%d", (SIGRTMAX - signum));
211 return 0;
212 }
213 #endif
214
215 /* Otherwise, search for signal matching signum in sig_array. If found,
216 * save its string value in str. */
217 for (sptr = sig_array; sptr < &sig_array[NUM_OF_SIGS]; sptr++) {
218 if (sptr->sig_num == signum) {
219 strcpy(str, sptr->sig_name);
220 return 0;
221 }
222 }
223
224 /* If signum is not a recognized signal number, return -1 */
225 return -1;
226 }
227
228 int
str2sig(const char * __restrict str,int * __restrict pnum)229 str2sig(const char *__restrict str, int *__restrict pnum)
230 {
231 char *endp;
232 const sig_name_and_num *sptr;
233 unsigned long is_valid_decimal;
234
235 #if defined (SIGRTMIN) && defined (SIGRTMAX)
236 /* i686 Cygwin only supports one RT signal. For this case, skip checks
237 * for "RTMIN+n" and "RTMAX-m". */
238 if (SIGRTMIN != SIGRTMAX) {
239
240 /* If str is in RT signal range, get number of of RT signal, save it as an
241 * integer. */
242 if (strncmp(str, "RTMIN+", SPACES_TO_N) == 0) {
243 unsigned long j = strtoul(&str[SPACES_TO_N], &endp, 10);
244
245 /* If number is valid, save it in pnum. */
246 if (*endp == '\0') {
247 if (1 <= j &&
248 j <= ((SIGRTMAX - SIGRTMIN)-1)) {
249 *pnum = (SIGRTMIN + j);
250 return 0;
251 }
252 return -1;
253 }
254 return -1;
255 }
256
257 /* If str is in RT signal range, get number of of RT signal, save it as an
258 * integer. */
259 if (strncmp(str, "RTMAX-", SPACES_TO_N) == 0) {
260 unsigned long j = strtoul(&str[SPACES_TO_N], &endp, 10); // and endptr null check
261
262 /* If number is valid, save it in pnum. */
263 if (*endp == '\0') {
264 if (1 <= j &&
265 j <= ((SIGRTMAX - SIGRTMIN)-1)) {
266 *pnum = (SIGRTMAX - j);
267 return 0;
268 }
269 return -1;
270 }
271 return -1;
272 }
273 }
274 #endif
275
276 /*If str is a valid signal name, save its corresponding number in pnum. */
277 for (sptr = sig_array; sptr < &sig_array[NUM_OF_SIGS]; sptr++) {
278 if (strcmp(sptr->sig_name, str) == 0) {
279 *pnum = sptr->sig_num;
280 return 0;
281 }
282 }
283
284 /* str was not found in sig_array. Check whether str is a string
285 * representation of a valid integer. */
286 is_valid_decimal = strtoul(str, &endp, 10);
287
288 if (*endp != '\0') {
289 return -1;
290 }
291
292 /* If str is a representation of a decimal value, save its integer value
293 * in pnum. */
294 if (1 <= is_valid_decimal &&
295 is_valid_decimal <= (NSIG - 1)) {
296 *pnum = is_valid_decimal;
297 return 0;
298 }
299
300 return -1;
301 }
302