home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / cvs-1.8.7-src.tgz / tar.out / fsf / cvs / lib / sighandle.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  9KB  |  415 lines

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