home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / glibc-1.06 / sysdeps / posix / __sigvec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-05  |  3.5 KB  |  141 lines

  1. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library 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 GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20. #include <signal.h>
  21. #include <errno.h>
  22. #include <stddef.h>
  23.  
  24.  
  25. /* We use a wrapper handler to support SV_RESETHAND.  */
  26.  
  27. static __sighandler_t wrapped_handlers[NSIG];
  28. static sigset_t wrapped_masks[NSIG];
  29.  
  30. static void
  31. DEFUN(wrapper_handler, (sig), int sig)
  32. {
  33.   int save;
  34.   struct sigaction act;
  35.  
  36.   act.sa_handler = SIG_DFL;
  37.   act.sa_mask = wrapped_masks[sig];
  38.   act.sa_flags = 0;
  39.   save = errno;
  40.   (void) __sigaction(sig, &act, (struct sigaction *) NULL);
  41.   errno = save;
  42.  
  43.   (*wrapped_handlers[sig])(sig);
  44. }
  45.  
  46. static
  47. #ifdef    __GNUC__
  48. inline
  49. #endif
  50. int
  51. DEFUN(convert_mask, (set, mask), sigset_t *set AND CONST int mask)
  52. {
  53.   register int sig;
  54.  
  55.   if (sizeof(*set) == sizeof(mask))
  56.     {
  57.       *(int *) set = mask;
  58.       return 0;
  59.     }
  60.  
  61.   if (__sigemptyset(set) < 0)
  62.     return -1;
  63.  
  64.   for (sig = 1; sig < NSIG; ++sig)
  65.     if (mask & sigmask(sig))
  66.       if (__sigaddset(set, sig) < 0)
  67.     return -1;
  68.  
  69.   return 0;
  70. }
  71.  
  72. /* If VEC is non-NULL, set the handler for SIG to the `sv_handler' member
  73.    of VEC.  The signals in `sv_mask' will be blocked while the handler runs.
  74.    If the SV_RESETHAND bit is set in `sv_flags', the handler for SIG will be
  75.    reset to SIG_DFL before `sv_handler' is entered.  If OVEC is non-NULL,
  76.    it is filled in with the old information for SIG.  */
  77. int
  78. DEFUN(__sigvec, (sig, vec, ovec),
  79.       int sig AND CONST struct sigvec *vec AND struct sigvec *ovec)
  80. {
  81.   struct sigaction old;
  82.  
  83.   if (vec == NULL || !(vec->sv_flags & SV_RESETHAND))
  84.     {
  85.       struct sigaction new, *n;
  86.  
  87.       if (vec == NULL)
  88.     n = NULL;
  89.       else
  90.     {
  91.       n = &new;
  92.       n->sa_handler = vec->sv_handler;
  93.       if (convert_mask(&n->sa_mask, vec->sv_mask) < 0)
  94.         return -1;
  95.       n->sa_flags = (((vec->sv_flags & SV_ONSTACK) ? SA_ONSTACK : 0) |
  96.              (!(vec->sv_flags & SV_INTERRUPT) ? SA_RESTART : 0));
  97.     }
  98.  
  99.       if (__sigaction(sig, n, &old) < 0)
  100.     return -1;
  101.     }
  102.   else
  103.     {
  104.       struct sigaction wrapper;
  105.  
  106.       wrapper.sa_handler = wrapper_handler;
  107.       wrapped_handlers[sig] = vec->sv_handler;
  108.       if (convert_mask(&wrapped_masks[sig], vec->sv_mask) < 0)
  109.     return -1;
  110.  
  111.       if (__sigaction(sig, &wrapper, &old) < 0)
  112.     return -1;
  113.     }
  114.  
  115.   if (ovec != NULL)
  116.     {
  117.       register int i;
  118.       int mask = 0;
  119.  
  120.       if (sizeof (int) == sizeof (sigset_t))
  121.     mask = old.sa_mask;
  122.       else
  123.     for (i = 1; i < NSIG; ++i)
  124.       if (__sigismember(&old.sa_mask, i))
  125.         mask |= sigmask(i);
  126.  
  127.       ovec->sv_mask = mask;
  128.       ovec->sv_flags = (((old.sa_flags & SA_ONSTACK) ? SV_ONSTACK : 0) |
  129.             (!(old.sa_flags & SA_RESTART) ? SV_INTERRUPT : 0));
  130.       if (old.sa_handler == wrapper_handler)
  131.     {
  132.       ovec->sv_flags |= SV_RESETHAND;
  133.       ovec->sv_handler = wrapped_handlers[sig];
  134.     }
  135.       else
  136.     ovec->sv_handler = old.sa_handler;
  137.     }
  138.  
  139.   return 0;
  140. }
  141.