1/* sig2str.c -- convert between signal names and numbers 2 3 Copyright (C) 2002, 2004, 2006, 2009-2010 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 <http://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. */ 41static 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. */ 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 SIGBUS 70 NUMNAME (BUS), 71#endif 72#ifdef SIGSEGV 73 NUMNAME (SEGV), 74#endif 75#ifdef SIGPIPE 76 NUMNAME (PIPE), 77#endif 78#ifdef SIGALRM 79 NUMNAME (ALRM), 80#endif 81#ifdef SIGTERM 82 NUMNAME (TERM), 83#endif 84#ifdef SIGUSR1 85 NUMNAME (USR1), 86#endif 87#ifdef SIGUSR2 88 NUMNAME (USR2), 89#endif 90#ifdef SIGCHLD 91 NUMNAME (CHLD), 92#endif 93#ifdef SIGURG 94 NUMNAME (URG), 95#endif 96#ifdef SIGSTOP 97 NUMNAME (STOP), 98#endif 99#ifdef SIGTSTP 100 NUMNAME (TSTP), 101#endif 102#ifdef SIGCONT 103 NUMNAME (CONT), 104#endif 105#ifdef SIGTTIN 106 NUMNAME (TTIN), 107#endif 108#ifdef SIGTTOU 109 NUMNAME (TTOU), 110#endif 111 112 /* Signals required by POSIX 1003.1-2001 with the XSI extension. */ 113#ifdef SIGSYS 114 NUMNAME (SYS), 115#endif 116#ifdef SIGPOLL 117 NUMNAME (POLL), 118#endif 119#ifdef SIGVTALRM 120 NUMNAME (VTALRM), 121#endif 122#ifdef SIGPROF 123 NUMNAME (PROF), 124#endif 125#ifdef SIGXCPU 126 NUMNAME (XCPU), 127#endif 128#ifdef SIGXFSZ 129 NUMNAME (XFSZ), 130#endif 131 132 /* Unix Version 7. */ 133#ifdef SIGIOT 134 NUMNAME (IOT), /* Older name for ABRT. */ 135#endif 136#ifdef SIGEMT 137 NUMNAME (EMT), 138#endif 139 140 /* USG Unix. */ 141#ifdef SIGPHONE 142 NUMNAME (PHONE), 143#endif 144#ifdef SIGWIND 145 NUMNAME (WIND), 146#endif 147 148 /* Unix System V. */ 149#ifdef SIGCLD 150 NUMNAME (CLD), 151#endif 152#ifdef SIGPWR 153 NUMNAME (PWR), 154#endif 155 156 /* GNU/Linux 2.2 and Solaris 8. */ 157#ifdef SIGCANCEL 158 NUMNAME (CANCEL), 159#endif 160#ifdef SIGLWP 161 NUMNAME (LWP), 162#endif 163#ifdef SIGWAITING 164 NUMNAME (WAITING), 165#endif 166#ifdef SIGFREEZE 167 NUMNAME (FREEZE), 168#endif 169#ifdef SIGTHAW 170 NUMNAME (THAW), 171#endif 172#ifdef SIGLOST 173 NUMNAME (LOST), 174#endif 175#ifdef SIGWINCH 176 NUMNAME (WINCH), 177#endif 178 179 /* GNU/Linux 2.2. */ 180#ifdef SIGINFO 181 NUMNAME (INFO), 182#endif 183#ifdef SIGIO 184 NUMNAME (IO), 185#endif 186#ifdef SIGSTKFLT 187 NUMNAME (STKFLT), 188#endif 189 190 /* AIX 5L. */ 191#ifdef SIGDANGER 192 NUMNAME (DANGER), 193#endif 194#ifdef SIGGRANT 195 NUMNAME (GRANT), 196#endif 197#ifdef SIGMIGRATE 198 NUMNAME (MIGRATE), 199#endif 200#ifdef SIGMSG 201 NUMNAME (MSG), 202#endif 203#ifdef SIGPRE 204 NUMNAME (PRE), 205#endif 206#ifdef SIGRETRACT 207 NUMNAME (RETRACT), 208#endif 209#ifdef SIGSAK 210 NUMNAME (SAK), 211#endif 212#ifdef SIGSOUND 213 NUMNAME (SOUND), 214#endif 215 216 /* Older AIX versions. */ 217#ifdef SIGALRM1 218 NUMNAME (ALRM1), /* unknown; taken from Bash 2.05 */ 219#endif 220#ifdef SIGKAP 221 NUMNAME (KAP), /* Older name for SIGGRANT. */ 222#endif 223#ifdef SIGVIRT 224 NUMNAME (VIRT), /* unknown; taken from Bash 2.05 */ 225#endif 226#ifdef SIGWINDOW 227 NUMNAME (WINDOW), /* Older name for SIGWINCH. */ 228#endif 229 230 /* BeOS */ 231#ifdef SIGKILLTHR 232 NUMNAME (KILLTHR), 233#endif 234 235 /* Older HP-UX versions. */ 236#ifdef SIGDIL 237 NUMNAME (DIL), 238#endif 239 240 /* Korn shell and Bash, of uncertain vintage. */ 241 { 0, "EXIT" } 242 }; 243 244#define NUMNAME_ENTRIES (sizeof numname_table / sizeof numname_table[0]) 245 246/* ISDIGIT differs from isdigit, as follows: 247 - Its arg may be any int or unsigned int; it need not be an unsigned char 248 or EOF. 249 - It's typically faster. 250 POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to 251 isdigit unless it's important to use the locale's definition 252 of `digit' even when the host does not conform to POSIX. */ 253#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) 254 255/* Convert the signal name SIGNAME to a signal number. Return the 256 signal number if successful, -1 otherwise. */ 257 258static int 259str2signum (char const *signame) 260{ 261 if (ISDIGIT (*signame)) 262 { 263 char *endp; 264 long int n = strtol (signame, &endp, 10); 265 if (! *endp && n <= SIGNUM_BOUND) 266 return n; 267 } 268 else 269 { 270 unsigned int i; 271 for (i = 0; i < NUMNAME_ENTRIES; i++) 272 if (strcmp (numname_table[i].name, signame) == 0) 273 return numname_table[i].num; 274 275 { 276 char *endp; 277 int rtmin = SIGRTMIN; 278 int rtmax = SIGRTMAX; 279 280 if (0 < rtmin && strncmp (signame, "RTMIN", 5) == 0) 281 { 282 long int n = strtol (signame + 5, &endp, 10); 283 if (! *endp && 0 <= n && n <= rtmax - rtmin) 284 return rtmin + n; 285 } 286 else if (0 < rtmax && strncmp (signame, "RTMAX", 5) == 0) 287 { 288 long int n = strtol (signame + 5, &endp, 10); 289 if (! *endp && rtmin - rtmax <= n && n <= 0) 290 return rtmax + n; 291 } 292 } 293 } 294 295 return -1; 296} 297 298/* Convert the signal name SIGNAME to the signal number *SIGNUM. 299 Return 0 if successful, -1 otherwise. */ 300 301int 302str2sig (char const *signame, int *signum) 303{ 304 *signum = str2signum (signame); 305 return *signum < 0 ? -1 : 0; 306} 307 308/* Convert SIGNUM to a signal name in SIGNAME. SIGNAME must point to 309 a buffer of at least SIG2STR_MAX bytes. Return 0 if successful, -1 310 otherwise. */ 311 312int 313sig2str (int signum, char *signame) 314{ 315 unsigned int i; 316 for (i = 0; i < NUMNAME_ENTRIES; i++) 317 if (numname_table[i].num == signum) 318 { 319 strcpy (signame, numname_table[i].name); 320 return 0; 321 } 322 323 { 324 int rtmin = SIGRTMIN; 325 int rtmax = SIGRTMAX; 326 327 if (! (rtmin <= signum && signum <= rtmax)) 328 return -1; 329 330 if (signum <= rtmin + (rtmax - rtmin) / 2) 331 { 332 int delta = signum - rtmin; 333 sprintf (signame, delta ? "RTMIN+%d" : "RTMIN", delta); 334 } 335 else 336 { 337 int delta = rtmax - signum; 338 sprintf (signame, delta ? "RTMAX-%d" : "RTMAX", delta); 339 } 340 341 return 0; 342 } 343} 344