newlib-cygwin/newlib/libc/signal/sig2str.c

303 lines
8.0 KiB
C

/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (C) 2021 Matthew Joyce
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
FUNCTION
<<sig2str>>, <<str2sig>>---Translate between signal number and name
INDEX
sig2str
INDEX
str2sig
SYNOPSIS
#include <signal.h>
int sig2str(int <[signum]>, char *<[str]>);
int str2sig(const char *restrict <[str]>, int *restrict <[pnum]>);
DESCRIPTION
The <<sig2str>> function translates the signal number specified by <[signum]> to
a signal name and stores this string in the location specified by <[str]>. The
application must ensure that <[str]> points to a location that can store the
string including the terminating null byte. The symbolic constant
<[SIG2STR_MAX]> defined in `<<signal.h>>' gives the maximum number of bytes
required.
The <<str2sig>> function translates the signal name in the string pointed to by
<[str]> to a signal number and stores this value in the location specified by
<[pnum]>.
RETURNS
<<sig2str>> returns <<0>> if <[signum]>> is a valid, supported signal number.
Otherwise, it returns <<-1>>.
<<str2sig>> returns <<0>> if it stores a value in the location pointed to by
<[pnum]>. Otherwise it returns <<-1>>.
*/
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define SPACES_TO_N 6 /* Allows indexing to RT Signal number in str2sig */
#define NUM_OF_SIGS (sizeof(sig_array) / sizeof(sig_name_and_num))
typedef struct sig_name_and_num {
const char *sig_name;
const int sig_num;
} sig_name_and_num;
static const sig_name_and_num sig_array[] = {
{ "EXIT", 0 },
#ifdef SIGHUP
{ "HUP", SIGHUP },
#endif
#ifdef SIGINT
{ "INT", SIGINT },
#endif
#ifdef SIGQUIT
{ "QUIT", SIGQUIT },
#endif
#ifdef SIGILL
{ "ILL", SIGILL },
#endif
#ifdef SIGTRAP
{ "TRAP", SIGTRAP },
#endif
#ifdef SIGABRT
{ "ABRT", SIGABRT },
#endif
#ifdef SIGIOT
{ "IOT", SIGIOT},
#endif
#ifdef SIGEMT
{ "EMT", SIGEMT },
#endif
#ifdef SIGFPE
{ "FPE", SIGFPE },
#endif
#ifdef SIGKILL
{ "KILL", SIGKILL },
#endif
#ifdef SIGBUS
{ "BUS", SIGBUS },
#endif
#ifdef SIGSEGV
{ "SEGV", SIGSEGV },
#endif
#ifdef SIGSYS
{ "SYS", SIGSYS },
#endif
#ifdef SIGPIPE
{ "PIPE", SIGPIPE },
#endif
#ifdef SIGALRM
{ "ALRM", SIGALRM },
#endif
#ifdef SIGTERM
{ "TERM", SIGTERM },
#endif
#ifdef SIGURG
{ "URG", SIGURG },
#endif
#ifdef SIGSTOP
{ "STOP", SIGSTOP },
#endif
#ifdef SIGTSTP
{ "TSTP", SIGTSTP },
#endif
#ifdef SIGCONT
{ "CONT", SIGCONT },
#endif
#ifdef SIGCHLD
{ "CHLD", SIGCHLD },
#endif
#ifdef SIGCLD
{ "CLD", SIGCLD },
#endif
#ifdef SIGTTIN
{ "TTIN", SIGTTIN },
#endif
#ifdef SIGTTOU
{ "TTOU", SIGTTOU },
#endif
#ifdef SIGIO
{ "IO", SIGIO },
#endif
#ifdef SIGPOLL
{ "POLL", SIGPOLL },
#endif
#ifdef SIGWINCH
{ "WINCH", SIGWINCH },
#endif
#ifdef SIGUSR1
{ "USR1", SIGUSR1 },
#endif
#ifdef SIGUSR2
{ "USR2", SIGUSR2 },
#endif
#ifdef SIGPWR
{ "PWR", SIGPWR },
#endif
#ifdef SIGXCPU
{ "XCPU", SIGXCPU },
#endif
#ifdef SIGXFSZ
{ "XFSZ", SIGXFSZ },
#endif
#ifdef SIGVTALRM
{ "VTALRM", SIGVTALRM },
#endif
#ifdef SIGPROF
{ "PROF", SIGPROF },
#endif
#ifdef SIGLOST
{ "LOST", SIGLOST },
#endif
/* The Issue 8 standard requires that SIGRTMIN and SIGRTMAX be included
* as valid results to be saved from calls to sig2str/str2sig. */
#ifdef SIGRTMIN
{ "RTMIN", SIGRTMIN },
#endif
#ifdef SIGRTMAX
{ "RTMAX", SIGRTMAX }
#endif
};
int
sig2str(int signum, char *str)
{
const sig_name_and_num *sptr;
#if defined (SIGRTMIN) && defined (SIGRTMAX)
/* If signum falls in lower half of the real time signals range, define
* the saved str value as "RTMIN+n" according to the Issue 8 standard */
if ((SIGRTMIN + 1) <= signum &&
signum <= (SIGRTMIN + SIGRTMAX) / 2) {
sprintf(str, "RTMIN+%d", (signum-SIGRTMIN));
return 0;
}
/* If signum falls in upper half of the real time signals range, define
* the saved str value as "RTMAX-m" according to the Issue 8 standard */
if ((((SIGRTMIN + SIGRTMAX) / 2) + 1) <= signum &&
signum <= (SIGRTMAX - 1)) {
sprintf(str, "RTMAX-%d", (SIGRTMAX - signum));
return 0;
}
#endif
/* Otherwise, search for signal matching signum in sig_array. If found,
* save its string value in str. */
for (sptr = sig_array; sptr < &sig_array[NUM_OF_SIGS]; sptr++) {
if (sptr->sig_num == signum) {
strcpy(str, sptr->sig_name);
return 0;
}
}
/* If signum is not a recognized signal number, return -1 */
return -1;
}
int
str2sig(const char *__restrict str, int *__restrict pnum)
{
unsigned long j = 0;
char *endp;
const sig_name_and_num *sptr;
unsigned long is_valid_decimal;
#if defined (SIGRTMIN) && defined (SIGRTMAX)
/* i686 Cygwin only supports one RT signal. For this case, skip checks
* for "RTMIN+n" and "RTMAX-m". */
if (SIGRTMIN != SIGRTMAX) {
/* If str is in RT signal range, get number of of RT signal, save it as an
* integer. */
if (strncmp(str, "RTMIN+", SPACES_TO_N) == 0) {
j = strtoul(&str[SPACES_TO_N], &endp, 10);
/* If number is valid, save it in pnum. */
if (*endp == '\0') {
if (1 <= j &&
j <= ((SIGRTMAX - SIGRTMIN)-1)) {
*pnum = (SIGRTMIN + j);
return 0;
}
return -1;
}
return -1;
}
/* If str is in RT signal range, get number of of RT signal, save it as an
* integer. */
if (strncmp(str, "RTMAX-", SPACES_TO_N) == 0) {
j = strtoul(&str[SPACES_TO_N], &endp, 10); // and endptr null check
/* If number is valid, save it in pnum. */
if (*endp == '\0') {
if (1 <= j &&
j <= ((SIGRTMAX - SIGRTMIN)-1)) {
*pnum = (SIGRTMAX - j);
return 0;
}
return -1;
}
return -1;
}
}
#endif
/*If str is a valid signal name, save its corresponding number in pnum. */
for (sptr = sig_array; sptr < &sig_array[NUM_OF_SIGS]; sptr++) {
if (strcmp(sptr->sig_name, str) == 0) {
*pnum = sptr->sig_num;
return 0;
}
}
/* str was not found in sig_array. Check whether str is a string
* representation of a valid integer. */
is_valid_decimal = strtoul(str, &endp, 10);
if (*endp != '\0') {
return -1;
}
/* If str is a representation of a decimal value, save its integer value
* in pnum. */
if (1 <= is_valid_decimal &&
is_valid_decimal <= (NSIG - 1)) {
*pnum = is_valid_decimal;
return 0;
}
return -1;
}