diff options
author | Jim Meyering <jim@meyering.net> | 2002-04-28 21:17:45 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2002-04-28 21:17:45 +0000 |
commit | b41ca51fc6bff00f11ab42a5d518fe2ebb558f45 (patch) | |
tree | 6103b63a22667d9ea4082bb2d7485a5eae9278e2 /lib | |
parent | 8e6c9373c16bd2f68b08fea01e2f2c8a45e867f9 (diff) | |
download | coreutils-b41ca51fc6bff00f11ab42a5d518fe2ebb558f45.tar.xz |
New file: from Paul Eggert.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sig2str.c | 353 | ||||
-rw-r--r-- | lib/sig2str.h | 49 |
2 files changed, 402 insertions, 0 deletions
diff --git a/lib/sig2str.c b/lib/sig2str.c new file mode 100644 index 000000000..1edc9f119 --- /dev/null +++ b/lib/sig2str.c @@ -0,0 +1,353 @@ +/* sig2str.c -- convert between signal names and numbers + + Copyright (C) 2002 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 2, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <limits.h> +#include <signal.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#if HAVE_SYS_WAIT_H +# include <sys/wait.h> +#endif +#ifndef WTERMSIG +# define WTERMSIG(s) ((s) & 0x7F) +#endif + +#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. */ +#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 SIGBUS + NUMNAME (BUS), +#endif +#ifdef SIGSEGV + NUMNAME (SEGV), +#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. + - It's guaranteed to evaluate its argument exactly once. + - It's typically faster. + POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to + ISDIGIT_LOCALE 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) (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 + { + 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) +{ + 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; + + if (! (rtmin <= signum && signum <= rtmax)) + return -1; + + if (signum <= rtmin + (rtmax - rtmin) / 2) + { + int delta = signum - rtmin; + sprintf (signame, delta ? "RTMIN+%d" : "RTMIN", delta); + } + else + { + int delta = rtmax - signum; + sprintf (signame, delta ? "RTMAX-%d" : "RTMAX", delta); + } + + return 0; + } +} diff --git a/lib/sig2str.h b/lib/sig2str.h new file mode 100644 index 000000000..3a46a8ce8 --- /dev/null +++ b/lib/sig2str.h @@ -0,0 +1,49 @@ +/* sig2str.h -- convert between signal names and numbers + + Copyright (C) 2002 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 2, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert. */ + +/* Include <signal.h> before including this file. */ + +/* Don't override system declarations of SIG2STR_MAX, sig2str, str2sig. */ +#ifndef SIG2STR_MAX + +/* Upper bound on the string length of an integer converted to string. + 302 / 1000 is ceil (log10 (2.0)). Subtract 1 for the sign bit; + add 1 for integer division truncation; add 1 more for a minus sign. */ +# define INT_STRLEN_BOUND(t) ((sizeof (t) * CHAR_BIT - 1) * 302 / 1000 + 2) + +/* Size of a buffer needed to hold a signal name like "HUP". */ +# define SIG2STR_MAX (sizeof "SIGRTMAX" + INT_STRLEN_BOUND (int) - 1) + +int sig2str (int, char *); +int str2sig (char const *, int *); + +#endif + +/* An upper bound on signal numbers allowed by the system. */ + +#if defined _sys_nsig +# define SIGNUM_BOUND (_sys_nsig - 1) +#elif defined NSIG +# define SIGNUM_BOUND (NSIG - 1) +#elif defined WTERMSIG +# define SIGNUM_BOUND WTERMSIG (~ 0) +#else +# define SIGNUM_BOUND 127 +#endif |