350 lines
7.0 KiB
C
350 lines
7.0 KiB
C
|
/* sig2str.c -- convert between signal names and numbers
|
||
|
|
||
|
Copyright (C) 2002, 2004, 2006, 2009-2020 Free Software Foundation, Inc.
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program 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 General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||
|
|
||
|
/* Written by Paul Eggert. */
|
||
|
|
||
|
#include <config.h>
|
||
|
|
||
|
#include <limits.h>
|
||
|
#include <signal.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "sig2str.h"
|
||
|
|
||
|
#ifndef SIGRTMIN
|
||
|
# define SIGRTMIN 0
|
||
|
# undef SIGRTMAX
|
||
|
#endif
|
||
|
#ifndef SIGRTMAX
|
||
|
# define SIGRTMAX (SIGRTMIN - 1)
|
||
|
#endif
|
||
|
|
||
|
#define NUMNAME(name) { SIG##name, #name }
|
||
|
|
||
|
/* Signal names and numbers. Put the preferred name first. */
|
||
|
static struct numname { int num; char const name[8]; } numname_table[] =
|
||
|
{
|
||
|
/* Signals required by POSIX 1003.1-2001 base, listed in
|
||
|
traditional numeric order where possible. */
|
||
|
#ifdef SIGHUP
|
||
|
NUMNAME (HUP),
|
||
|
#endif
|
||
|
#ifdef SIGINT
|
||
|
NUMNAME (INT),
|
||
|
#endif
|
||
|
#ifdef SIGQUIT
|
||
|
NUMNAME (QUIT),
|
||
|
#endif
|
||
|
#ifdef SIGILL
|
||
|
NUMNAME (ILL),
|
||
|
#endif
|
||
|
#ifdef SIGTRAP
|
||
|
NUMNAME (TRAP),
|
||
|
#endif
|
||
|
#ifdef SIGABRT
|
||
|
NUMNAME (ABRT),
|
||
|
#endif
|
||
|
#ifdef SIGFPE
|
||
|
NUMNAME (FPE),
|
||
|
#endif
|
||
|
#ifdef SIGKILL
|
||
|
NUMNAME (KILL),
|
||
|
#endif
|
||
|
#ifdef SIGSEGV
|
||
|
NUMNAME (SEGV),
|
||
|
#endif
|
||
|
/* On Haiku, SIGSEGV == SIGBUS, but we prefer SIGSEGV to match
|
||
|
strsignal.c output, so SIGBUS must be listed second. */
|
||
|
#ifdef SIGBUS
|
||
|
NUMNAME (BUS),
|
||
|
#endif
|
||
|
#ifdef SIGPIPE
|
||
|
NUMNAME (PIPE),
|
||
|
#endif
|
||
|
#ifdef SIGALRM
|
||
|
NUMNAME (ALRM),
|
||
|
#endif
|
||
|
#ifdef SIGTERM
|
||
|
NUMNAME (TERM),
|
||
|
#endif
|
||
|
#ifdef SIGUSR1
|
||
|
NUMNAME (USR1),
|
||
|
#endif
|
||
|
#ifdef SIGUSR2
|
||
|
NUMNAME (USR2),
|
||
|
#endif
|
||
|
#ifdef SIGCHLD
|
||
|
NUMNAME (CHLD),
|
||
|
#endif
|
||
|
#ifdef SIGURG
|
||
|
NUMNAME (URG),
|
||
|
#endif
|
||
|
#ifdef SIGSTOP
|
||
|
NUMNAME (STOP),
|
||
|
#endif
|
||
|
#ifdef SIGTSTP
|
||
|
NUMNAME (TSTP),
|
||
|
#endif
|
||
|
#ifdef SIGCONT
|
||
|
NUMNAME (CONT),
|
||
|
#endif
|
||
|
#ifdef SIGTTIN
|
||
|
NUMNAME (TTIN),
|
||
|
#endif
|
||
|
#ifdef SIGTTOU
|
||
|
NUMNAME (TTOU),
|
||
|
#endif
|
||
|
|
||
|
/* Signals required by POSIX 1003.1-2001 with the XSI extension. */
|
||
|
#ifdef SIGSYS
|
||
|
NUMNAME (SYS),
|
||
|
#endif
|
||
|
#ifdef SIGPOLL
|
||
|
NUMNAME (POLL),
|
||
|
#endif
|
||
|
#ifdef SIGVTALRM
|
||
|
NUMNAME (VTALRM),
|
||
|
#endif
|
||
|
#ifdef SIGPROF
|
||
|
NUMNAME (PROF),
|
||
|
#endif
|
||
|
#ifdef SIGXCPU
|
||
|
NUMNAME (XCPU),
|
||
|
#endif
|
||
|
#ifdef SIGXFSZ
|
||
|
NUMNAME (XFSZ),
|
||
|
#endif
|
||
|
|
||
|
/* Unix Version 7. */
|
||
|
#ifdef SIGIOT
|
||
|
NUMNAME (IOT), /* Older name for ABRT. */
|
||
|
#endif
|
||
|
#ifdef SIGEMT
|
||
|
NUMNAME (EMT),
|
||
|
#endif
|
||
|
|
||
|
/* USG Unix. */
|
||
|
#ifdef SIGPHONE
|
||
|
NUMNAME (PHONE),
|
||
|
#endif
|
||
|
#ifdef SIGWIND
|
||
|
NUMNAME (WIND),
|
||
|
#endif
|
||
|
|
||
|
/* Unix System V. */
|
||
|
#ifdef SIGCLD
|
||
|
NUMNAME (CLD),
|
||
|
#endif
|
||
|
#ifdef SIGPWR
|
||
|
NUMNAME (PWR),
|
||
|
#endif
|
||
|
|
||
|
/* GNU/Linux 2.2 and Solaris 8. */
|
||
|
#ifdef SIGCANCEL
|
||
|
NUMNAME (CANCEL),
|
||
|
#endif
|
||
|
#ifdef SIGLWP
|
||
|
NUMNAME (LWP),
|
||
|
#endif
|
||
|
#ifdef SIGWAITING
|
||
|
NUMNAME (WAITING),
|
||
|
#endif
|
||
|
#ifdef SIGFREEZE
|
||
|
NUMNAME (FREEZE),
|
||
|
#endif
|
||
|
#ifdef SIGTHAW
|
||
|
NUMNAME (THAW),
|
||
|
#endif
|
||
|
#ifdef SIGLOST
|
||
|
NUMNAME (LOST),
|
||
|
#endif
|
||
|
#ifdef SIGWINCH
|
||
|
NUMNAME (WINCH),
|
||
|
#endif
|
||
|
|
||
|
/* GNU/Linux 2.2. */
|
||
|
#ifdef SIGINFO
|
||
|
NUMNAME (INFO),
|
||
|
#endif
|
||
|
#ifdef SIGIO
|
||
|
NUMNAME (IO),
|
||
|
#endif
|
||
|
#ifdef SIGSTKFLT
|
||
|
NUMNAME (STKFLT),
|
||
|
#endif
|
||
|
|
||
|
/* AIX 5L. */
|
||
|
#ifdef SIGDANGER
|
||
|
NUMNAME (DANGER),
|
||
|
#endif
|
||
|
#ifdef SIGGRANT
|
||
|
NUMNAME (GRANT),
|
||
|
#endif
|
||
|
#ifdef SIGMIGRATE
|
||
|
NUMNAME (MIGRATE),
|
||
|
#endif
|
||
|
#ifdef SIGMSG
|
||
|
NUMNAME (MSG),
|
||
|
#endif
|
||
|
#ifdef SIGPRE
|
||
|
NUMNAME (PRE),
|
||
|
#endif
|
||
|
#ifdef SIGRETRACT
|
||
|
NUMNAME (RETRACT),
|
||
|
#endif
|
||
|
#ifdef SIGSAK
|
||
|
NUMNAME (SAK),
|
||
|
#endif
|
||
|
#ifdef SIGSOUND
|
||
|
NUMNAME (SOUND),
|
||
|
#endif
|
||
|
|
||
|
/* Older AIX versions. */
|
||
|
#ifdef SIGALRM1
|
||
|
NUMNAME (ALRM1), /* unknown; taken from Bash 2.05 */
|
||
|
#endif
|
||
|
#ifdef SIGKAP
|
||
|
NUMNAME (KAP), /* Older name for SIGGRANT. */
|
||
|
#endif
|
||
|
#ifdef SIGVIRT
|
||
|
NUMNAME (VIRT), /* unknown; taken from Bash 2.05 */
|
||
|
#endif
|
||
|
#ifdef SIGWINDOW
|
||
|
NUMNAME (WINDOW), /* Older name for SIGWINCH. */
|
||
|
#endif
|
||
|
|
||
|
/* BeOS */
|
||
|
#ifdef SIGKILLTHR
|
||
|
NUMNAME (KILLTHR),
|
||
|
#endif
|
||
|
|
||
|
/* Older HP-UX versions. */
|
||
|
#ifdef SIGDIL
|
||
|
NUMNAME (DIL),
|
||
|
#endif
|
||
|
|
||
|
/* Korn shell and Bash, of uncertain vintage. */
|
||
|
{ 0, "EXIT" }
|
||
|
};
|
||
|
|
||
|
#define NUMNAME_ENTRIES (sizeof numname_table / sizeof numname_table[0])
|
||
|
|
||
|
/* ISDIGIT differs from isdigit, as follows:
|
||
|
- Its arg may be any int or unsigned int; it need not be an unsigned char
|
||
|
or EOF.
|
||
|
- It's typically faster.
|
||
|
POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
|
||
|
isdigit unless it's important to use the locale's definition
|
||
|
of "digit" even when the host does not conform to POSIX. */
|
||
|
#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
|
||
|
|
||
|
/* Convert the signal name SIGNAME to a signal number. Return the
|
||
|
signal number if successful, -1 otherwise. */
|
||
|
|
||
|
static int
|
||
|
str2signum (char const *signame)
|
||
|
{
|
||
|
if (ISDIGIT (*signame))
|
||
|
{
|
||
|
char *endp;
|
||
|
long int n = strtol (signame, &endp, 10);
|
||
|
if (! *endp && n <= SIGNUM_BOUND)
|
||
|
return n;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < NUMNAME_ENTRIES; i++)
|
||
|
if (strcmp (numname_table[i].name, signame) == 0)
|
||
|
return numname_table[i].num;
|
||
|
|
||
|
{
|
||
|
char *endp;
|
||
|
int rtmin = SIGRTMIN;
|
||
|
int rtmax = SIGRTMAX;
|
||
|
|
||
|
if (0 < rtmin && strncmp (signame, "RTMIN", 5) == 0)
|
||
|
{
|
||
|
long int n = strtol (signame + 5, &endp, 10);
|
||
|
if (! *endp && 0 <= n && n <= rtmax - rtmin)
|
||
|
return rtmin + n;
|
||
|
}
|
||
|
else if (0 < rtmax && strncmp (signame, "RTMAX", 5) == 0)
|
||
|
{
|
||
|
long int n = strtol (signame + 5, &endp, 10);
|
||
|
if (! *endp && rtmin - rtmax <= n && n <= 0)
|
||
|
return rtmax + n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* Convert the signal name SIGNAME to the signal number *SIGNUM.
|
||
|
Return 0 if successful, -1 otherwise. */
|
||
|
|
||
|
int
|
||
|
str2sig (char const *signame, int *signum)
|
||
|
{
|
||
|
*signum = str2signum (signame);
|
||
|
return *signum < 0 ? -1 : 0;
|
||
|
}
|
||
|
|
||
|
/* Convert SIGNUM to a signal name in SIGNAME. SIGNAME must point to
|
||
|
a buffer of at least SIG2STR_MAX bytes. Return 0 if successful, -1
|
||
|
otherwise. */
|
||
|
|
||
|
int
|
||
|
sig2str (int signum, char *signame)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < NUMNAME_ENTRIES; i++)
|
||
|
if (numname_table[i].num == signum)
|
||
|
{
|
||
|
strcpy (signame, numname_table[i].name);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
int rtmin = SIGRTMIN;
|
||
|
int rtmax = SIGRTMAX;
|
||
|
int base, delta;
|
||
|
|
||
|
if (! (rtmin <= signum && signum <= rtmax))
|
||
|
return -1;
|
||
|
|
||
|
if (signum <= rtmin + (rtmax - rtmin) / 2)
|
||
|
{
|
||
|
strcpy (signame, "RTMIN");
|
||
|
base = rtmin;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
strcpy (signame, "RTMAX");
|
||
|
base = rtmax;
|
||
|
}
|
||
|
|
||
|
delta = signum - base;
|
||
|
if (delta != 0)
|
||
|
sprintf (signame + 5, "%+d", delta);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|