sig2str.c 7.0 KB

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