| /* Copyright (C) 1991, 1994-2002, 2005, 2008-2026 Free Software Foundation, | |
| Inc. | |
| This file is part of the GNU C Library. | |
| This file is free software: you can redistribute it and/or modify | |
| it under the terms of the GNU Lesser General Public License as | |
| published by the Free Software Foundation; either version 2.1 of the | |
| License, or (at your option) any later version. | |
| This file is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU Lesser General Public License for more details. | |
| You should have received a copy of the GNU Lesser General Public License | |
| along with this program. If not, see <https://www.gnu.org/licenses/>. */ | |
| #ifndef _LIBC | |
| # include <config.h> | |
| #endif | |
| /* Specification. */ | |
| #include <string.h> | |
| #include <signal.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #ifdef _LIBC | |
| # include <libintl.h> | |
| #else /* !_LIBC */ | |
| # include "gettext.h" | |
| # define _(msgid) dgettext (GNULIB_TEXT_DOMAIN, msgid) | |
| # define N_(msgid) gettext_noop (msgid) | |
| #endif /* _LIBC */ | |
| #ifdef _LIBC | |
| # include <bits/libc-lock.h> | |
| #else /* !_LIBC */ | |
| # include "glthread/once.h" | |
| # include "glthread/tls.h" | |
| # define __libc_once_define(CLASS, NAME) gl_once_define (CLASS, NAME) | |
| # define __libc_once(NAME, INIT) gl_once ((NAME), (INIT)) | |
| # define __libc_key_t gl_tls_key_t | |
| # define __libc_getspecific(NAME) gl_tls_get ((NAME)) | |
| # define __libc_setspecific(NAME, POINTER) gl_tls_set ((NAME), (POINTER)) | |
| # define __snprintf snprintf | |
| #endif /* _LIBC */ | |
| #ifdef _LIBC | |
| /* Defined in siglist.c. */ | |
| extern const char *const _sys_siglist[]; | |
| extern const char *const _sys_siglist_internal[] attribute_hidden; | |
| #else /* !_LIBC */ | |
| /* NetBSD declares sys_siglist in unistd.h. */ | |
| # if HAVE_UNISTD_H | |
| # include <unistd.h> | |
| # endif | |
| # define INTUSE(x) (x) | |
| # if HAVE_DECL_SYS_SIGLIST | |
| # undef _sys_siglist | |
| # define _sys_siglist sys_siglist | |
| # else /* !HAVE_DECL_SYS_SIGLIST */ | |
| # ifndef NSIG | |
| # define NSIG 32 | |
| # endif /* NSIG */ | |
| # if !HAVE_DECL__SYS_SIGLIST | |
| static const char *_sys_siglist[NSIG]; | |
| # endif | |
| # endif /* !HAVE_DECL_SYS_SIGLIST */ | |
| #endif /* _LIBC */ | |
| static __libc_key_t key; | |
| /* If nonzero the key allocation failed and we should better use a | |
| static buffer than fail. */ | |
| #define BUFFERSIZ 100 | |
| static char local_buf[BUFFERSIZ]; | |
| static char *static_buf; | |
| /* Destructor for the thread-specific data. */ | |
| static void init (void); | |
| static void free_key_mem (void *mem); | |
| static char *getbuffer (void); | |
| /* Return a string describing the meaning of the signal number SIGNUM. */ | |
| char * | |
| strsignal (int signum) | |
| { | |
| __libc_once_define (static, once); | |
| /* If we have not yet initialized the buffer do it now. */ | |
| __libc_once (once, init); | |
| const char *desc; | |
| if ( | |
| #ifdef SIGRTMIN | |
| (signum >= SIGRTMIN && signum <= SIGRTMAX) || | |
| #endif | |
| signum < 0 || signum >= NSIG | |
| || (desc = INTUSE(_sys_siglist)[signum]) == NULL) | |
| { | |
| char *buffer = getbuffer (); | |
| int len; | |
| #ifdef SIGRTMIN | |
| if (signum >= SIGRTMIN && signum <= SIGRTMAX) | |
| len = __snprintf (buffer, BUFFERSIZ - 1, _("Real-time signal %d"), | |
| signum - (int) SIGRTMIN); | |
| else | |
| #endif | |
| len = __snprintf (buffer, BUFFERSIZ - 1, _("Unknown signal %d"), | |
| signum); | |
| if (len >= BUFFERSIZ) | |
| buffer = NULL; | |
| else | |
| buffer[len] = '\0'; | |
| return buffer; | |
| } | |
| return (char *) _(desc); | |
| } | |
| /* Initialize buffer. */ | |
| static void | |
| init (void) | |
| { | |
| #ifdef _LIBC | |
| if (__libc_key_create (&key, free_key_mem)) | |
| /* Creating the key failed. This means something really went | |
| wrong. In any case use a static buffer which is better than | |
| nothing. */ | |
| static_buf = local_buf; | |
| #else /* !_LIBC */ | |
| gl_tls_key_init (key, free_key_mem); | |
| # if !HAVE_DECL_SYS_SIGLIST | |
| memset (_sys_siglist, 0, NSIG * sizeof *_sys_siglist); | |
| /* No need to use a do {} while (0) here since init_sig(...) must expand | |
| to a complete statement. (We cannot use the ISO C99 designated array | |
| initializer syntax since it is not supported by ANSI C compilers and | |
| since some signal numbers might exceed NSIG.) */ | |
| # define init_sig(sig, abbrev, desc) \ | |
| if (sig >= 0 && sig < NSIG) \ | |
| _sys_siglist[sig] = desc; | |
| # include "siglist.h" | |
| # undef init_sig | |
| # endif /* !HAVE_DECL_SYS_SIGLIST */ | |
| #endif /* !_LIBC */ | |
| } | |
| /* Free the thread specific data, this is done if a thread terminates. */ | |
| static void | |
| free_key_mem (void *mem) | |
| { | |
| free (mem); | |
| __libc_setspecific (key, NULL); | |
| } | |
| /* Return the buffer to be used. */ | |
| static char * | |
| getbuffer (void) | |
| { | |
| char *result; | |
| if (static_buf != NULL) | |
| result = static_buf; | |
| else | |
| { | |
| /* We don't use the static buffer and so we have a key. Use it | |
| to get the thread-specific buffer. */ | |
| result = __libc_getspecific (key); | |
| if (result == NULL) | |
| { | |
| /* No buffer allocated so far. */ | |
| result = malloc (BUFFERSIZ); | |
| if (result == NULL) | |
| /* No more memory available. We use the static buffer. */ | |
| result = local_buf; | |
| else | |
| __libc_setspecific (key, result); | |
| } | |
| } | |
| return result; | |
| } |