(root)/
coreutils-9.4/
lib/
sig2str.c
       1  /* sig2str.c -- convert between signal names and numbers
       2  
       3     Copyright (C) 2002, 2004, 2006, 2009-2023 Free Software Foundation, Inc.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation, either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program 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 General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  /* Written by Paul Eggert.  */
      19  
      20  #include <config.h>
      21  
      22  #include <limits.h>
      23  #include <signal.h>
      24  #include <stdlib.h>
      25  #include <stdio.h>
      26  #include <string.h>
      27  
      28  #include "sig2str.h"
      29  
      30  #ifndef SIGRTMIN
      31  # define SIGRTMIN 0
      32  # undef SIGRTMAX
      33  #endif
      34  #ifndef SIGRTMAX
      35  # define SIGRTMAX (SIGRTMIN - 1)
      36  #endif
      37  
      38  #define NUMNAME(name) { SIG##name, #name }
      39  
      40  /* Signal names and numbers.  Put the preferred name first.  */
      41  static struct numname { int num; char const name[8]; } numname_table[] =
      42    {
      43      /* Signals required by POSIX 1003.1-2001 base, listed in
      44         traditional numeric order where possible.  */
      45  #ifdef SIGHUP
      46      NUMNAME (HUP),
      47  #endif
      48  #ifdef SIGINT
      49      NUMNAME (INT),
      50  #endif
      51  #ifdef SIGQUIT
      52      NUMNAME (QUIT),
      53  #endif
      54  #ifdef SIGILL
      55      NUMNAME (ILL),
      56  #endif
      57  #ifdef SIGTRAP
      58      NUMNAME (TRAP),
      59  #endif
      60  #ifdef SIGABRT
      61      NUMNAME (ABRT),
      62  #endif
      63  #ifdef SIGFPE
      64      NUMNAME (FPE),
      65  #endif
      66  #ifdef SIGKILL
      67      NUMNAME (KILL),
      68  #endif
      69  #ifdef SIGSEGV
      70      NUMNAME (SEGV),
      71  #endif
      72      /* On Haiku, SIGSEGV == SIGBUS, but we prefer SIGSEGV to match
      73         strsignal.c output, so SIGBUS must be listed second.  */
      74  #ifdef SIGBUS
      75      NUMNAME (BUS),
      76  #endif
      77  #ifdef SIGPIPE
      78      NUMNAME (PIPE),
      79  #endif
      80  #ifdef SIGALRM
      81      NUMNAME (ALRM),
      82  #endif
      83  #ifdef SIGTERM
      84      NUMNAME (TERM),
      85  #endif
      86  #ifdef SIGUSR1
      87      NUMNAME (USR1),
      88  #endif
      89  #ifdef SIGUSR2
      90      NUMNAME (USR2),
      91  #endif
      92  #ifdef SIGCHLD
      93      NUMNAME (CHLD),
      94  #endif
      95  #ifdef SIGURG
      96      NUMNAME (URG),
      97  #endif
      98  #ifdef SIGSTOP
      99      NUMNAME (STOP),
     100  #endif
     101  #ifdef SIGTSTP
     102      NUMNAME (TSTP),
     103  #endif
     104  #ifdef SIGCONT
     105      NUMNAME (CONT),
     106  #endif
     107  #ifdef SIGTTIN
     108      NUMNAME (TTIN),
     109  #endif
     110  #ifdef SIGTTOU
     111      NUMNAME (TTOU),
     112  #endif
     113  
     114      /* Signals required by POSIX 1003.1-2001 with the XSI extension.  */
     115  #ifdef SIGSYS
     116      NUMNAME (SYS),
     117  #endif
     118  #ifdef SIGPOLL
     119      NUMNAME (POLL),
     120  #endif
     121  #ifdef SIGVTALRM
     122      NUMNAME (VTALRM),
     123  #endif
     124  #ifdef SIGPROF
     125      NUMNAME (PROF),
     126  #endif
     127  #ifdef SIGXCPU
     128      NUMNAME (XCPU),
     129  #endif
     130  #ifdef SIGXFSZ
     131      NUMNAME (XFSZ),
     132  #endif
     133  
     134      /* Unix Version 7.  */
     135  #ifdef SIGIOT
     136      NUMNAME (IOT),      /* Older name for ABRT.  */
     137  #endif
     138  #ifdef SIGEMT
     139      NUMNAME (EMT),
     140  #endif
     141  
     142      /* USG Unix.  */
     143  #ifdef SIGPHONE
     144      NUMNAME (PHONE),
     145  #endif
     146  #ifdef SIGWIND
     147      NUMNAME (WIND),
     148  #endif
     149  
     150      /* Unix System V.  */
     151  #ifdef SIGCLD
     152      NUMNAME (CLD),
     153  #endif
     154  #ifdef SIGPWR
     155      NUMNAME (PWR),
     156  #endif
     157  
     158      /* GNU/Linux 2.2 and Solaris 8.  */
     159  #ifdef SIGCANCEL
     160      NUMNAME (CANCEL),
     161  #endif
     162  #ifdef SIGLWP
     163      NUMNAME (LWP),
     164  #endif
     165  #ifdef SIGWAITING
     166      NUMNAME (WAITING),
     167  #endif
     168  #ifdef SIGFREEZE
     169      NUMNAME (FREEZE),
     170  #endif
     171  #ifdef SIGTHAW
     172      NUMNAME (THAW),
     173  #endif
     174  #ifdef SIGLOST
     175      NUMNAME (LOST),
     176  #endif
     177  #ifdef SIGWINCH
     178      NUMNAME (WINCH),
     179  #endif
     180  
     181      /* GNU/Linux 2.2.  */
     182  #ifdef SIGINFO
     183      NUMNAME (INFO),
     184  #endif
     185  #ifdef SIGIO
     186      NUMNAME (IO),
     187  #endif
     188  #ifdef SIGSTKFLT
     189      NUMNAME (STKFLT),
     190  #endif
     191  
     192      /* AIX 7.  */
     193  #ifdef SIGCPUFAIL
     194      NUMNAME (CPUFAIL),
     195  #endif
     196  
     197      /* AIX 5L.  */
     198  #ifdef SIGDANGER
     199      NUMNAME (DANGER),
     200  #endif
     201  #ifdef SIGGRANT
     202      NUMNAME (GRANT),
     203  #endif
     204  #ifdef SIGMIGRATE
     205      NUMNAME (MIGRATE),
     206  #endif
     207  #ifdef SIGMSG
     208      NUMNAME (MSG),
     209  #endif
     210  #ifdef SIGPRE
     211      NUMNAME (PRE),
     212  #endif
     213  #ifdef SIGRETRACT
     214      NUMNAME (RETRACT),
     215  #endif
     216  #ifdef SIGSAK
     217      NUMNAME (SAK),
     218  #endif
     219  #ifdef SIGSOUND
     220      NUMNAME (SOUND),
     221  #endif
     222  
     223      /* Older AIX versions.  */
     224  #ifdef SIGALRM1
     225      NUMNAME (ALRM1),    /* unknown; taken from Bash 2.05 */
     226  #endif
     227  #ifdef SIGKAP
     228      NUMNAME (KAP),      /* Older name for SIGGRANT.  */
     229  #endif
     230  #ifdef SIGVIRT
     231      NUMNAME (VIRT),     /* unknown; taken from Bash 2.05 */
     232  #endif
     233  #ifdef SIGWINDOW
     234      NUMNAME (WINDOW),   /* Older name for SIGWINCH.  */
     235  #endif
     236  
     237      /* OpenBSD.  */
     238  #ifdef SIGTHR
     239      NUMNAME (THR),
     240  #endif
     241  
     242      /* BeOS, Haiku */
     243  #ifdef SIGKILLTHR
     244      NUMNAME (KILLTHR),
     245  #endif
     246  
     247      /* Older HP-UX versions.  */
     248  #ifdef SIGDIL
     249      NUMNAME (DIL),
     250  #endif
     251  
     252      /* native Windows */
     253  #ifdef SIGBREAK
     254      NUMNAME (BREAK),
     255  #endif
     256  
     257      /* Korn shell and Bash, of uncertain vintage.  */
     258      { 0, "EXIT" }
     259    };
     260  
     261  #define NUMNAME_ENTRIES (sizeof numname_table / sizeof numname_table[0])
     262  
     263  /* ISDIGIT differs from isdigit, as follows:
     264     - Its arg may be any int or unsigned int; it need not be an unsigned char
     265       or EOF.
     266     - It's typically faster.
     267     POSIX says that only '0' through '9' are digits.  Prefer ISDIGIT to
     268     isdigit unless it's important to use the locale's definition
     269     of "digit" even when the host does not conform to POSIX.  */
     270  #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
     271  
     272  /* Convert the signal name SIGNAME to a signal number.  Return the
     273     signal number if successful, -1 otherwise.  */
     274  
     275  static int
     276  str2signum (char const *signame)
     277  {
     278    if (ISDIGIT (*signame))
     279      {
     280        char *endp;
     281        long int n = strtol (signame, &endp, 10);
     282        if (! *endp && n <= SIGNUM_BOUND)
     283          return n;
     284      }
     285    else
     286      {
     287        unsigned int i;
     288        for (i = 0; i < NUMNAME_ENTRIES; i++)
     289          if (strcmp (numname_table[i].name, signame) == 0)
     290            return numname_table[i].num;
     291  
     292        {
     293          char *endp;
     294          int rtmin = SIGRTMIN;
     295          int rtmax = SIGRTMAX;
     296  
     297          if (0 < rtmin && strncmp (signame, "RTMIN", 5) == 0)
     298            {
     299              long int n = strtol (signame + 5, &endp, 10);
     300              if (! *endp && 0 <= n && n <= rtmax - rtmin)
     301                return rtmin + n;
     302            }
     303          else if (0 < rtmax && strncmp (signame, "RTMAX", 5) == 0)
     304            {
     305              long int n = strtol (signame + 5, &endp, 10);
     306              if (! *endp && rtmin - rtmax <= n && n <= 0)
     307                return rtmax + n;
     308            }
     309        }
     310      }
     311  
     312    return -1;
     313  }
     314  
     315  /* Convert the signal name SIGNAME to the signal number *SIGNUM.
     316     Return 0 if successful, -1 otherwise.  */
     317  
     318  int
     319  str2sig (char const *signame, int *signum)
     320  {
     321    *signum = str2signum (signame);
     322    return *signum < 0 ? -1 : 0;
     323  }
     324  
     325  /* Convert SIGNUM to a signal name in SIGNAME.  SIGNAME must point to
     326     a buffer of at least SIG2STR_MAX bytes.  Return 0 if successful, -1
     327     otherwise.  */
     328  
     329  int
     330  sig2str (int signum, char *signame)
     331  {
     332    unsigned int i;
     333    for (i = 0; i < NUMNAME_ENTRIES; i++)
     334      if (numname_table[i].num == signum)
     335        {
     336          strcpy (signame, numname_table[i].name);
     337          return 0;
     338        }
     339  
     340    {
     341      int rtmin = SIGRTMIN;
     342      int rtmax = SIGRTMAX;
     343      int base, delta;
     344  
     345      if (! (rtmin <= signum && signum <= rtmax))
     346        return -1;
     347  
     348      if (signum <= rtmin + (rtmax - rtmin) / 2)
     349        {
     350          strcpy (signame, "RTMIN");
     351          base = rtmin;
     352        }
     353      else
     354        {
     355          strcpy (signame, "RTMAX");
     356          base = rtmax;
     357        }
     358  
     359      delta = signum - base;
     360      if (delta != 0)
     361        sprintf (signame + 5, "%+d", delta);
     362      return 0;
     363    }
     364  }