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 #define _DEFAULT_SOURCE
63 #include <signal.h>
64 #include <string.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67
68 #define SPACES_TO_N 6 /* Allows indexing to RT Signal number in str2sig */
69 #define NUM_OF_SIGS (sizeof(sig_array) / sizeof(sig_name_and_num))
70
71 typedef struct sig_name_and_num {
72 const char sig_name[8];
73 const int sig_num;
74 } sig_name_and_num;
75
76 static const sig_name_and_num sig_array[] = {
77 { "EXIT", 0 },
78 #ifdef SIGHUP
79 { "HUP", SIGHUP },
80 #endif
81 #ifdef SIGINT
82 { "INT", SIGINT },
83 #endif
84 #ifdef SIGQUIT
85 { "QUIT", SIGQUIT },
86 #endif
87 #ifdef SIGILL
88 { "ILL", SIGILL },
89 #endif
90 #ifdef SIGTRAP
91 { "TRAP", SIGTRAP },
92 #endif
93 #ifdef SIGABRT
94 { "ABRT", SIGABRT },
95 #endif
96 #ifdef SIGIOT
97 { "IOT", SIGIOT},
98 #endif
99 #ifdef SIGEMT
100 { "EMT", SIGEMT },
101 #endif
102 #ifdef SIGFPE
103 { "FPE", SIGFPE },
104 #endif
105 #ifdef SIGKILL
106 { "KILL", SIGKILL },
107 #endif
108 #ifdef SIGBUS
109 { "BUS", SIGBUS },
110 #endif
111 #ifdef SIGSEGV
112 { "SEGV", SIGSEGV },
113 #endif
114 #ifdef SIGSYS
115 { "SYS", SIGSYS },
116 #endif
117 #ifdef SIGPIPE
118 { "PIPE", SIGPIPE },
119 #endif
120 #ifdef SIGALRM
121 { "ALRM", SIGALRM },
122 #endif
123 #ifdef SIGTERM
124 { "TERM", SIGTERM },
125 #endif
126 #ifdef SIGURG
127 { "URG", SIGURG },
128 #endif
129 #ifdef SIGSTOP
130 { "STOP", SIGSTOP },
131 #endif
132 #ifdef SIGTSTP
133 { "TSTP", SIGTSTP },
134 #endif
135 #ifdef SIGCONT
136 { "CONT", SIGCONT },
137 #endif
138 #ifdef SIGCHLD
139 { "CHLD", SIGCHLD },
140 #endif
141 #ifdef SIGCLD
142 { "CLD", SIGCLD },
143 #endif
144 #ifdef SIGTTIN
145 { "TTIN", SIGTTIN },
146 #endif
147 #ifdef SIGTTOU
148 { "TTOU", SIGTTOU },
149 #endif
150 #ifdef SIGIO
151 { "IO", SIGIO },
152 #endif
153 #ifdef SIGPOLL
154 { "POLL", SIGPOLL },
155 #endif
156 #ifdef SIGWINCH
157 { "WINCH", SIGWINCH },
158 #endif
159 #ifdef SIGUSR1
160 { "USR1", SIGUSR1 },
161 #endif
162 #ifdef SIGUSR2
163 { "USR2", SIGUSR2 },
164 #endif
165 #ifdef SIGPWR
166 { "PWR", SIGPWR },
167 #endif
168 #ifdef SIGXCPU
169 { "XCPU", SIGXCPU },
170 #endif
171 #ifdef SIGXFSZ
172 { "XFSZ", SIGXFSZ },
173 #endif
174 #ifdef SIGVTALRM
175 { "VTALRM", SIGVTALRM },
176 #endif
177 #ifdef SIGPROF
178 { "PROF", SIGPROF },
179 #endif
180 #ifdef SIGLOST
181 { "LOST", SIGLOST },
182 #endif
183 /* The Issue 8 standard requires that SIGRTMIN and SIGRTMAX be included
184 * as valid results to be saved from calls to sig2str/str2sig. */
185 #ifdef SIGRTMIN
186 { "RTMIN", SIGRTMIN },
187 #endif
188 #ifdef SIGRTMAX
189 { "RTMAX", SIGRTMAX }
190 #endif
191 };
192
193 int
sig2str(int signum,char * str)194 sig2str(int signum, char *str)
195 {
196 const sig_name_and_num *sptr;
197
198 #if defined (SIGRTMIN) && defined (SIGRTMAX)
199 /* If signum falls in lower half of the real time signals range, define
200 * the saved str value as "RTMIN+n" according to the Issue 8 standard */
201 if ((SIGRTMIN + 1) <= signum &&
202 signum <= (SIGRTMIN + SIGRTMAX) / 2) {
203 sprintf(str, "RTMIN+%d", (signum-SIGRTMIN));
204 return 0;
205 }
206
207 /* If signum falls in upper half of the real time signals range, define
208 * the saved str value as "RTMAX-m" according to the Issue 8 standard */
209 if ((((SIGRTMIN + SIGRTMAX) / 2) + 1) <= signum &&
210 signum <= (SIGRTMAX - 1)) {
211 sprintf(str, "RTMAX-%d", (SIGRTMAX - signum));
212 return 0;
213 }
214 #endif
215
216 /* Otherwise, search for signal matching signum in sig_array. If found,
217 * save its string value in str. */
218 for (sptr = sig_array; sptr < &sig_array[NUM_OF_SIGS]; sptr++) {
219 if (sptr->sig_num == signum) {
220 strcpy(str, sptr->sig_name);
221 return 0;
222 }
223 }
224
225 /* If signum is not a recognized signal number, return -1 */
226 return -1;
227 }
228
229 int
str2sig(const char * __restrict str,int * __restrict pnum)230 str2sig(const char *__restrict str, int *__restrict pnum)
231 {
232 char *endp;
233 const sig_name_and_num *sptr;
234 unsigned long is_valid_decimal;
235
236 #if defined (SIGRTMIN) && defined (SIGRTMAX)
237 /* i686 Cygwin only supports one RT signal. For this case, skip checks
238 * for "RTMIN+n" and "RTMAX-m". */
239 if (SIGRTMIN != SIGRTMAX) {
240
241 /* If str is in RT signal range, get number of of RT signal, save it as an
242 * integer. */
243 if (strncmp(str, "RTMIN+", SPACES_TO_N) == 0) {
244 unsigned long j = strtoul(&str[SPACES_TO_N], &endp, 10);
245
246 /* If number is valid, save it in pnum. */
247 if (*endp == '\0') {
248 if (1 <= j &&
249 j <= ((SIGRTMAX - SIGRTMIN)-1)) {
250 *pnum = (SIGRTMIN + j);
251 return 0;
252 }
253 return -1;
254 }
255 return -1;
256 }
257
258 /* If str is in RT signal range, get number of of RT signal, save it as an
259 * integer. */
260 if (strncmp(str, "RTMAX-", SPACES_TO_N) == 0) {
261 unsigned long j = strtoul(&str[SPACES_TO_N], &endp, 10); // and endptr null check
262
263 /* If number is valid, save it in pnum. */
264 if (*endp == '\0') {
265 if (1 <= j &&
266 j <= ((SIGRTMAX - SIGRTMIN)-1)) {
267 *pnum = (SIGRTMAX - j);
268 return 0;
269 }
270 return -1;
271 }
272 return -1;
273 }
274 }
275 #endif
276
277 /*If str is a valid signal name, save its corresponding number in pnum. */
278 for (sptr = sig_array; sptr < &sig_array[NUM_OF_SIGS]; sptr++) {
279 if (strcmp(sptr->sig_name, str) == 0) {
280 *pnum = sptr->sig_num;
281 return 0;
282 }
283 }
284
285 /* str was not found in sig_array. Check whether str is a string
286 * representation of a valid integer. */
287 is_valid_decimal = strtoul(str, &endp, 10);
288
289 if (*endp != '\0') {
290 return -1;
291 }
292
293 /* If str is a representation of a decimal value, save its integer value
294 * in pnum. */
295 if (1 <= is_valid_decimal &&
296 is_valid_decimal <= (_NSIG - 1)) {
297 *pnum = is_valid_decimal;
298 return 0;
299 }
300
301 return -1;
302 }
303