/contrib/cvs/lib/sighandle.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 418 lines · 294 code · 41 blank · 83 comment · 53 complexity · a6b4b3a6ce3e8322d75c0b9bc9772a5a MD5 · raw file

  1. /* sighandle.c -- Library routines for manipulating chains of signal handlers
  2. Copyright (C) 1992 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 2, or (at your option)
  6. 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. /* Written by Paul Sander, HaL Computer Systems, Inc. <paul@hal.com>
  12. Brian Berliner <berliner@Sun.COM> added POSIX support */
  13. /*************************************************************************
  14. *
  15. * signal.c -- This file contains code that manipulates chains of signal
  16. * handlers.
  17. *
  18. * Facilities are provided to register a signal handler for
  19. * any specific signal. When a signal is received, all of the
  20. * registered signal handlers are invoked in the reverse order
  21. * in which they are registered. Note that the signal handlers
  22. * must not themselves make calls to the signal handling
  23. * facilities.
  24. *
  25. *************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #endif
  29. #include "system.h"
  30. #include <sys/types.h>
  31. #include <stdio.h>
  32. #include <signal.h>
  33. /* Add prototype support. */
  34. #ifndef PROTO
  35. #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
  36. #define PROTO(ARGS) ARGS
  37. #else
  38. #define PROTO(ARGS) ()
  39. #endif
  40. #endif
  41. #ifdef STDC_HEADERS
  42. #include <stdlib.h>
  43. #else
  44. #if __STDC__
  45. char *calloc(unsigned nelem, unsigned size);
  46. char *malloc(unsigned size);
  47. #else
  48. char *calloc();
  49. char *malloc();
  50. #endif /* __STDC__ */
  51. #endif /* STDC_HEADERS */
  52. /* Define the highest signal number (usually) */
  53. #ifndef SIGMAX
  54. #define SIGMAX 64
  55. #endif
  56. /* Define linked list of signal handlers structure */
  57. struct SIG_hlist {
  58. RETSIGTYPE (*handler)();
  59. struct SIG_hlist *next;
  60. };
  61. /*
  62. * Define array of lists of signal handlers. Note that this depends on
  63. * the implementation to initialize each element to a null pointer.
  64. */
  65. static struct SIG_hlist **SIG_handlers;
  66. /* Define array of default signal vectors */
  67. #ifdef POSIX_SIGNALS
  68. static struct sigaction *SIG_defaults;
  69. #else
  70. #ifdef BSD_SIGNALS
  71. static struct sigvec *SIG_defaults;
  72. #else
  73. static RETSIGTYPE (**SIG_defaults) PROTO ((int));
  74. #endif
  75. #endif
  76. /* Critical section housekeeping */
  77. static int SIG_crSectNest = 0; /* Nesting level */
  78. #ifdef POSIX_SIGNALS
  79. static sigset_t SIG_crSectMask; /* Signal mask */
  80. #else
  81. static int SIG_crSectMask; /* Signal mask */
  82. #endif
  83. /*
  84. * Initialize the signal handler arrays
  85. */
  86. static int SIG_init()
  87. {
  88. int i;
  89. #ifdef POSIX_SIGNALS
  90. sigset_t sigset_test;
  91. #endif
  92. if (SIG_defaults && SIG_handlers) /* already allocated */
  93. return (0);
  94. #ifdef POSIX_SIGNALS
  95. (void) sigfillset(&sigset_test);
  96. for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++)
  97. ;
  98. if (i < SIGMAX)
  99. i = SIGMAX;
  100. i++;
  101. if (!SIG_defaults)
  102. SIG_defaults = (struct sigaction *)
  103. calloc(i, sizeof(struct sigaction));
  104. (void) sigemptyset(&SIG_crSectMask);
  105. #else
  106. i = SIGMAX+1;
  107. #ifdef BSD_SIGNALS
  108. if (!SIG_defaults)
  109. SIG_defaults = (struct sigvec *)
  110. calloc(i, sizeof(struct sigvec));
  111. #else
  112. if (!SIG_defaults)
  113. SIG_defaults = (RETSIGTYPE (**) PROTO ((int)) )
  114. calloc(i, sizeof(RETSIGTYPE (**) PROTO ((int)) ));
  115. #endif
  116. SIG_crSectMask = 0;
  117. #endif
  118. if (!SIG_handlers)
  119. SIG_handlers = (struct SIG_hlist **)
  120. calloc(i, sizeof(struct SIG_hlist *));
  121. return (!SIG_defaults || !SIG_handlers);
  122. }
  123. /*
  124. * The following invokes each signal handler in the reverse order in which
  125. * they were registered.
  126. */
  127. static RETSIGTYPE SIG_handle PROTO ((int));
  128. static RETSIGTYPE SIG_handle(sig)
  129. int sig;
  130. {
  131. struct SIG_hlist *this;
  132. /* Dispatch signal handlers */
  133. this = SIG_handlers[sig];
  134. while (this != (struct SIG_hlist *) NULL)
  135. {
  136. (*this->handler)(sig);
  137. this = this->next;
  138. }
  139. return;
  140. }
  141. /*
  142. * The following registers a signal handler. If the handler is already
  143. * registered, it is not registered twice, nor is the order in which signal
  144. * handlers are invoked changed. If this is the first signal handler
  145. * registered for a given signal, the old sigvec structure is saved for
  146. * restoration later.
  147. */
  148. int SIG_register(sig,fn)
  149. int sig;
  150. RETSIGTYPE (*fn)();
  151. {
  152. int val;
  153. struct SIG_hlist *this;
  154. #ifdef POSIX_SIGNALS
  155. struct sigaction act;
  156. sigset_t sigset_mask, sigset_omask;
  157. #else
  158. #ifdef BSD_SIGNALS
  159. struct sigvec vec;
  160. int mask;
  161. #endif
  162. #endif
  163. /* Initialize */
  164. if (SIG_init() != 0)
  165. return (-1);
  166. val = 0;
  167. /* Block this signal while we look at handler chain */
  168. #ifdef POSIX_SIGNALS
  169. (void) sigemptyset(&sigset_mask);
  170. (void) sigaddset(&sigset_mask, sig);
  171. (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
  172. #else
  173. #ifdef BSD_SIGNALS
  174. mask = sigblock(sigmask(sig));
  175. #endif
  176. #endif
  177. /* See if this handler was already registered */
  178. this = SIG_handlers[sig];
  179. while (this != (struct SIG_hlist *) NULL)
  180. {
  181. if (this->handler == fn) break;
  182. this = this->next;
  183. }
  184. /* Register the new handler only if it is not already registered. */
  185. if (this == (struct SIG_hlist *) NULL)
  186. {
  187. /*
  188. * If this is the first handler registered for this signal,
  189. * set up the signal handler dispatcher
  190. */
  191. if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
  192. {
  193. #ifdef POSIX_SIGNALS
  194. act.sa_handler = SIG_handle;
  195. (void) sigemptyset(&act.sa_mask);
  196. act.sa_flags = 0;
  197. val = sigaction(sig, &act, &SIG_defaults[sig]);
  198. #else
  199. #ifdef BSD_SIGNALS
  200. memset (&vec, 0, sizeof (vec));
  201. vec.sv_handler = SIG_handle;
  202. val = sigvec(sig, &vec, &SIG_defaults[sig]);
  203. #else
  204. if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR)
  205. val = -1;
  206. #endif
  207. #endif
  208. }
  209. /* If not, register it */
  210. if ((val == 0) && (this == (struct SIG_hlist *) NULL))
  211. {
  212. this = (struct SIG_hlist *)
  213. malloc(sizeof(struct SIG_hlist));
  214. if (this == NULL)
  215. {
  216. val = -1;
  217. }
  218. else
  219. {
  220. this->handler = fn;
  221. this->next = SIG_handlers[sig];
  222. SIG_handlers[sig] = this;
  223. }
  224. }
  225. }
  226. /* Unblock the signal */
  227. #ifdef POSIX_SIGNALS
  228. (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
  229. #else
  230. #ifdef BSD_SIGNALS
  231. (void) sigsetmask(mask);
  232. #endif
  233. #endif
  234. return val;
  235. }
  236. /*
  237. * The following deregisters a signal handler. If the last signal handler for
  238. * a given signal is deregistered, the default sigvec information is restored.
  239. */
  240. int SIG_deregister(sig,fn)
  241. int sig;
  242. RETSIGTYPE (*fn)();
  243. {
  244. int val;
  245. struct SIG_hlist *this;
  246. struct SIG_hlist *last;
  247. #ifdef POSIX_SIGNALS
  248. sigset_t sigset_mask, sigset_omask;
  249. #else
  250. #ifdef BSD_SIGNALS
  251. int mask;
  252. #endif
  253. #endif
  254. /* Initialize */
  255. if (SIG_init() != 0)
  256. return (-1);
  257. val = 0;
  258. last = (struct SIG_hlist *) NULL;
  259. /* Block this signal while we look at handler chain */
  260. #ifdef POSIX_SIGNALS
  261. (void) sigemptyset(&sigset_mask);
  262. (void) sigaddset(&sigset_mask, sig);
  263. (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
  264. #else
  265. #ifdef BSD_SIGNALS
  266. mask = sigblock(sigmask(sig));
  267. #endif
  268. #endif
  269. /* Search for the signal handler */
  270. this = SIG_handlers[sig];
  271. while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn))
  272. {
  273. last = this;
  274. this = this->next;
  275. }
  276. /* If it was registered, remove it */
  277. if (this != (struct SIG_hlist *) NULL)
  278. {
  279. if (last == (struct SIG_hlist *) NULL)
  280. {
  281. SIG_handlers[sig] = this->next;
  282. }
  283. else
  284. {
  285. last->next = this->next;
  286. }
  287. free((char *) this);
  288. }
  289. /* Restore default behavior if there are no registered handlers */
  290. if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
  291. {
  292. #ifdef POSIX_SIGNALS
  293. val = sigaction(sig, &SIG_defaults[sig],
  294. (struct sigaction *) NULL);
  295. #else
  296. #ifdef BSD_SIGNALS
  297. val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
  298. #else
  299. if (signal(sig, SIG_defaults[sig]) == SIG_ERR)
  300. val = -1;
  301. #endif
  302. #endif
  303. }
  304. /* Unblock the signal */
  305. #ifdef POSIX_SIGNALS
  306. (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
  307. #else
  308. #ifdef BSD_SIGNALS
  309. (void) sigsetmask(mask);
  310. #endif
  311. #endif
  312. return val;
  313. }
  314. /*
  315. * The following begins a critical section.
  316. */
  317. void SIG_beginCrSect()
  318. {
  319. if (SIG_init() == 0)
  320. {
  321. if (SIG_crSectNest == 0)
  322. {
  323. #ifdef POSIX_SIGNALS
  324. sigset_t sigset_mask;
  325. (void) sigfillset(&sigset_mask);
  326. (void) sigprocmask(SIG_SETMASK,
  327. &sigset_mask, &SIG_crSectMask);
  328. #else
  329. #ifdef BSD_SIGNALS
  330. SIG_crSectMask = sigblock(~0);
  331. #else
  332. /* TBD */
  333. #endif
  334. #endif
  335. }
  336. SIG_crSectNest++;
  337. }
  338. }
  339. /*
  340. * Return nonzero if currently in a critical section.
  341. * Otherwise return zero.
  342. */
  343. int SIG_inCrSect()
  344. {
  345. return SIG_crSectNest > 0;
  346. }
  347. /*
  348. * The following ends a critical section.
  349. */
  350. void SIG_endCrSect()
  351. {
  352. if (SIG_init() == 0)
  353. {
  354. SIG_crSectNest--;
  355. if (SIG_crSectNest == 0)
  356. {
  357. #ifdef POSIX_SIGNALS
  358. (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL);
  359. #else
  360. #ifdef BSD_SIGNALS
  361. (void) sigsetmask(SIG_crSectMask);
  362. #else
  363. /* TBD */
  364. #endif
  365. #endif
  366. }
  367. }
  368. }