[PATCH 1/1] libc: Added implementation for sig2str/str2sig.
Joel Sherrill
joel@rtems.org
Sun Aug 1 17:03:27 GMT 2021
I think this is OK. There was a lot of discussion to incorporate so
others need to concur.
On Sat, Jul 31, 2021 at 8:22 AM Matt Joyce <mfjoyce2004@gmail.com> wrote:
>
> Added implementations for sig2str() and str2sig() in libc/signal
> in order to improve POSIX compliance. Added fucntion prototypes
> in libc/include/sys/signal.h.
> ---
> newlib/libc/include/sys/signal.h | 17 ++
> newlib/libc/signal/Makefile.am | 4 +-
> newlib/libc/signal/sig2str.c | 298 +++++++++++++++++++++++++++++++
> 3 files changed, 317 insertions(+), 2 deletions(-)
> create mode 100644 newlib/libc/signal/sig2str.c
>
> diff --git a/newlib/libc/include/sys/signal.h b/newlib/libc/include/sys/signal.h
> index 45cc0366c..9c1c0e3c2 100644
> --- a/newlib/libc/include/sys/signal.h
> +++ b/newlib/libc/include/sys/signal.h
> @@ -12,6 +12,7 @@ extern "C" {
> #include <sys/types.h>
> #include <sys/_sigset.h>
> #include <sys/_timespec.h>
> +#include <stdint.h>
>
> #if !defined(_SIGSET_T_DECLARED)
> #define _SIGSET_T_DECLARED
> @@ -238,6 +239,22 @@ int sigqueue (pid_t, int, const union sigval);
>
> #endif /* __POSIX_VISIBLE >= 199309 */
>
> +/* Using __MISC_VISIBLE until POSIX Issue 8 is officially released */
> +#if __MISC_VISIBLE
> +
> +/* POSIX Issue 8 adds sig2str() and str2sig() */
> +
> +#if __STDINT_EXP(INT_MAX) > 0x7fff
> +#define SIG2STR_MAX (sizeof("RTMAX+") + sizeof("4294967295") - 1)
> +#else
> +#define SIG2STR_MAX (sizeof("RTMAX+") + sizeof("65535") - 1)
> +#endif
> +
> +int sig2str(int, char *);
> +int str2sig(const char *__restrict, int *__restrict);
> +
> +#endif /* __MISC_VISIBLE */
> +
> #if defined(___AM29K__)
> /* These all need to be defined for ANSI C, but I don't think they are
> meaningful. */
> diff --git a/newlib/libc/signal/Makefile.am b/newlib/libc/signal/Makefile.am
> index a93dba7a9..89db26113 100644
> --- a/newlib/libc/signal/Makefile.am
> +++ b/newlib/libc/signal/Makefile.am
> @@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = cygnus
>
> INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
>
> -LIB_SOURCES = psignal.c raise.c signal.c
> +LIB_SOURCES = psignal.c raise.c signal.c sig2str.c
>
> libsignal_la_LDFLAGS = -Xcompiler -nostdlib
>
> @@ -21,6 +21,6 @@ endif # USE_LIBTOOL
>
> include $(srcdir)/../../Makefile.shared
>
> -CHEWOUT_FILES = psignal.def raise.def signal.def
> +CHEWOUT_FILES = psignal.def raise.def signal.def sig2str.def
>
> CHAPTERS = signal.tex
> diff --git a/newlib/libc/signal/sig2str.c b/newlib/libc/signal/sig2str.c
> new file mode 100644
> index 000000000..c02fcacbd
> --- /dev/null
> +++ b/newlib/libc/signal/sig2str.c
> @@ -0,0 +1,298 @@
> +/* 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>>---translate between signal number and name
> +<<str2sig>>---translate between signal name and number
> +
> +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 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;
> + }
> +
> + /* 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;
> +
> + /* 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;
> + }
> + }
> +
> + /*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 <= SIGRTMAX) {
> + *pnum = is_valid_decimal;
> + return 0;
> + }
> + return -1;
> +}
> --
> 2.31.1
>
More information about the Newlib
mailing list