(root)/
coreutils-9.4/
lib/
strsignal.c
       1  /* Copyright (C) 1991, 1994-2002, 2005, 2008-2023 Free Software Foundation,
       2     Inc.
       3     This file is part of the GNU C Library.
       4  
       5     This file is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     This file is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #ifndef _LIBC
      19  # include <config.h>
      20  #endif
      21  
      22  /* Specification.  */
      23  #include <string.h>
      24  
      25  #include <signal.h>
      26  #include <stdio.h>
      27  #include <stdlib.h>
      28  
      29  #ifdef _LIBC
      30  # include <libintl.h>
      31  #else /* !_LIBC */
      32  # include "gettext.h"
      33  # define _(msgid) gettext (msgid)
      34  # define N_(msgid) gettext_noop (msgid)
      35  #endif /* _LIBC */
      36  
      37  #ifdef _LIBC
      38  # include <bits/libc-lock.h>
      39  #else /* !_LIBC */
      40  # include "glthread/lock.h"
      41  # include "glthread/tls.h"
      42  # define __libc_once_define(CLASS, NAME) gl_once_define (CLASS, NAME)
      43  # define __libc_once(NAME, INIT) gl_once ((NAME), (INIT))
      44  # define __libc_key_t gl_tls_key_t
      45  # define __libc_getspecific(NAME) gl_tls_get ((NAME))
      46  # define __libc_setspecific(NAME, POINTER) gl_tls_set ((NAME), (POINTER))
      47  # define __snprintf snprintf
      48  #endif /* _LIBC */
      49  
      50  #ifdef _LIBC
      51  
      52  /* Defined in siglist.c.  */
      53  extern const char *const _sys_siglist[];
      54  extern const char *const _sys_siglist_internal[] attribute_hidden;
      55  
      56  #else /* !_LIBC */
      57  
      58  /* NetBSD declares sys_siglist in unistd.h. */
      59  # if HAVE_UNISTD_H
      60  #  include <unistd.h>
      61  # endif
      62  
      63  # define INTUSE(x) (x)
      64  
      65  # if HAVE_DECL_SYS_SIGLIST
      66  #  undef _sys_siglist
      67  #  define _sys_siglist sys_siglist
      68  # else /* !HAVE_DECL_SYS_SIGLIST */
      69  #  ifndef NSIG
      70  #   define NSIG 32
      71  #  endif /* NSIG */
      72  #  if !HAVE_DECL__SYS_SIGLIST
      73  static const char *_sys_siglist[NSIG];
      74  #  endif
      75  # endif /* !HAVE_DECL_SYS_SIGLIST */
      76  
      77  #endif /* _LIBC */
      78  
      79  static __libc_key_t key;
      80  
      81  /* If nonzero the key allocation failed and we should better use a
      82     static buffer than fail.  */
      83  #define BUFFERSIZ       100
      84  static char local_buf[BUFFERSIZ];
      85  static char *static_buf;
      86  
      87  /* Destructor for the thread-specific data.  */
      88  static void init (void);
      89  static void free_key_mem (void *mem);
      90  static char *getbuffer (void);
      91  
      92  
      93  /* Return a string describing the meaning of the signal number SIGNUM.  */
      94  char *
      95  strsignal (int signum)
      96  {
      97    const char *desc;
      98    __libc_once_define (static, once);
      99  
     100    /* If we have not yet initialized the buffer do it now.  */
     101    __libc_once (once, init);
     102  
     103    if (
     104  #ifdef SIGRTMIN
     105        (signum >= SIGRTMIN && signum <= SIGRTMAX) ||
     106  #endif
     107        signum < 0 || signum >= NSIG
     108        || (desc = INTUSE(_sys_siglist)[signum]) == NULL)
     109      {
     110        char *buffer = getbuffer ();
     111        int len;
     112  #ifdef SIGRTMIN
     113        if (signum >= SIGRTMIN && signum <= SIGRTMAX)
     114          len = __snprintf (buffer, BUFFERSIZ - 1, _("Real-time signal %d"),
     115                            signum - (int) SIGRTMIN);
     116        else
     117  #endif
     118          len = __snprintf (buffer, BUFFERSIZ - 1, _("Unknown signal %d"),
     119                            signum);
     120        if (len >= BUFFERSIZ)
     121          buffer = NULL;
     122        else
     123          buffer[len] = '\0';
     124  
     125        return buffer;
     126      }
     127  
     128    return (char *) _(desc);
     129  }
     130  
     131  
     132  /* Initialize buffer.  */
     133  static void
     134  init (void)
     135  {
     136  #ifdef _LIBC
     137    if (__libc_key_create (&key, free_key_mem))
     138      /* Creating the key failed.  This means something really went
     139         wrong.  In any case use a static buffer which is better than
     140         nothing.  */
     141      static_buf = local_buf;
     142  #else /* !_LIBC */
     143    gl_tls_key_init (key, free_key_mem);
     144  
     145  # if !HAVE_DECL_SYS_SIGLIST
     146    memset (_sys_siglist, 0, NSIG * sizeof *_sys_siglist);
     147  
     148    /* No need to use a do {} while (0) here since init_sig(...) must expand
     149       to a complete statement.  (We cannot use the ISO C99 designated array
     150       initializer syntax since it is not supported by ANSI C compilers and
     151       since some signal numbers might exceed NSIG.)  */
     152  #  define init_sig(sig, abbrev, desc) \
     153    if (sig >= 0 && sig < NSIG) \
     154      _sys_siglist[sig] = desc;
     155  
     156  #  include "siglist.h"
     157  
     158  #  undef init_sig
     159  
     160  # endif /* !HAVE_DECL_SYS_SIGLIST */
     161  #endif /* !_LIBC */
     162  }
     163  
     164  
     165  /* Free the thread specific data, this is done if a thread terminates.  */
     166  static void
     167  free_key_mem (void *mem)
     168  {
     169    free (mem);
     170    __libc_setspecific (key, NULL);
     171  }
     172  
     173  
     174  /* Return the buffer to be used.  */
     175  static char *
     176  getbuffer (void)
     177  {
     178    char *result;
     179  
     180    if (static_buf != NULL)
     181      result = static_buf;
     182    else
     183      {
     184        /* We don't use the static buffer and so we have a key.  Use it
     185           to get the thread-specific buffer.  */
     186        result = __libc_getspecific (key);
     187        if (result == NULL)
     188          {
     189            /* No buffer allocated so far.  */
     190            result = malloc (BUFFERSIZ);
     191            if (result == NULL)
     192              /* No more memory available.  We use the static buffer.  */
     193              result = local_buf;
     194            else
     195              __libc_setspecific (key, result);
     196          }
     197      }
     198  
     199    return result;
     200  }