Back to index

glibc  2.9
sigset.c
Go to the documentation of this file.
00001 /* Copyright (C) 1998, 2000, 2005, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <errno.h>
00020 #define __need_NULL
00021 #include <stddef.h>
00022 #include <signal.h>
00023 #include <string.h>  /* For the real memset prototype.  */
00024 
00025 
00026 /* Set the disposition for SIG.  */
00027 __sighandler_t
00028 sigset (sig, disp)
00029      int sig;
00030      __sighandler_t disp;
00031 {
00032   struct sigaction act;
00033   struct sigaction oact;
00034   sigset_t set;
00035   sigset_t oset;
00036 
00037 #ifdef SIG_HOLD
00038   /* Handle SIG_HOLD first.  */
00039   if (disp == SIG_HOLD)
00040     {
00041       /* Create an empty signal set.  */
00042       if (__sigemptyset (&set) < 0)
00043        return SIG_ERR;
00044 
00045       /* Add the specified signal.  */
00046       if (__sigaddset (&set, sig) < 0)
00047        return SIG_ERR;
00048 
00049       /* Add the signal set to the current signal mask.  */
00050       if (__sigprocmask (SIG_BLOCK, &set, &oset) < 0)
00051        return SIG_ERR;
00052 
00053       /* If the signal was already blocked signal this to the caller.  */
00054       if (__sigismember (&oset, sig))
00055        return SIG_HOLD;
00056 
00057       /* We need to determine whether a specific handler is installed.  */
00058       if (__sigaction (sig, NULL, &oact) < 0)
00059        return SIG_ERR;
00060 
00061       return oact.sa_handler;
00062     }
00063 #endif /* SIG_HOLD */
00064 
00065   /* Check signal extents to protect __sigismember.  */
00066   if (disp == SIG_ERR || sig < 1 || sig >= NSIG)
00067     {
00068       __set_errno (EINVAL);
00069       return SIG_ERR;
00070     }
00071 
00072   act.sa_handler = disp;
00073   if (__sigemptyset (&act.sa_mask) < 0)
00074     return SIG_ERR;
00075   act.sa_flags = 0;
00076   if (__sigaction (sig, &act, &oact) < 0)
00077     return SIG_ERR;
00078 
00079   /* Create an empty signal set.  */
00080   if (__sigemptyset (&set) < 0)
00081     return SIG_ERR;
00082 
00083   /* Add the specified signal.  */
00084   if (__sigaddset (&set, sig) < 0)
00085     return SIG_ERR;
00086 
00087   /* Remove the signal set from the current signal mask.  */
00088   if (__sigprocmask (SIG_UNBLOCK, &set, &oset) < 0)
00089     return SIG_ERR;
00090 
00091   /* If the signal was already blocked return SIG_HOLD.  */
00092   return __sigismember (&oset, sig) ? SIG_HOLD : oact.sa_handler;
00093 }