Back to index

glibc  2.9
sigvec.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991,92,1994-98,2002,2004 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 <signal.h>
00020 #include <errno.h>
00021 #include <stddef.h>
00022 
00023 /* Include macros to convert between `sigset_t' and old-style mask. */
00024 #include <sigset-cvt-mask.h>
00025 
00026 #ifndef SA_RESETHAND
00027 /* When sigaction lacks the extension bit for it,
00028    we use a wrapper handler to support SV_RESETHAND.  */
00029 struct sigvec_wrapper_data
00030 {
00031   __sighandler_t sw_handler;
00032   unsigned int sw_mask;
00033 };
00034 
00035 static void sigvec_wrapper_handler (int sig) __THROW;
00036 
00037 static struct sigvec_wrapper_data sigvec_wrapper_data[NSIG];
00038 #endif
00039 
00040 
00041 /* If VEC is non-NULL, set the handler for SIG to the `sv_handler' member
00042    of VEC.  The signals in `sv_mask' will be blocked while the handler runs.
00043    If the SV_RESETHAND bit is set in `sv_flags', the handler for SIG will be
00044    reset to SIG_DFL before `sv_handler' is entered.  If OVEC is non-NULL,
00045    it is filled in with the old information for SIG.  */
00046 int
00047 __sigvec (sig, vec, ovec)
00048      int sig;
00049      const struct sigvec *vec;
00050      struct sigvec *ovec;
00051 {
00052   struct sigaction old;
00053 
00054 #ifndef SA_RESETHAND
00055   if (vec == NULL || !(vec->sv_flags & SV_RESETHAND))
00056 #endif
00057     {
00058       struct sigaction new, *n;
00059 
00060       if (vec == NULL)
00061        n = NULL;
00062       else
00063        {
00064          __sighandler_t handler;
00065          unsigned int mask;
00066          unsigned int sv_flags;
00067          unsigned int sa_flags;
00068 
00069          handler = vec->sv_handler;
00070          mask = vec->sv_mask;
00071          sv_flags = vec->sv_flags;
00072          sa_flags = 0;
00073          if (sv_flags & SV_ONSTACK)
00074            {
00075 #ifdef SA_ONSTACK
00076              sa_flags |= SA_ONSTACK;
00077 #else
00078              __set_errno (ENOSYS);
00079              return -1;
00080 #endif
00081            }
00082 #ifdef SA_RESTART
00083          if (!(sv_flags & SV_INTERRUPT))
00084            sa_flags |= SA_RESTART;
00085 #endif
00086 #ifdef SA_RESETHAND
00087          if (sv_flags & SV_RESETHAND)
00088            sa_flags |= SA_RESETHAND;
00089 #endif
00090          n = &new;
00091          new.sa_handler = handler;
00092          if (sigset_set_old_mask (&new.sa_mask, mask) < 0)
00093            return -1;
00094          new.sa_flags = sa_flags;
00095        }
00096 
00097       if (__sigaction (sig, n, &old) < 0)
00098        return -1;
00099     }
00100 #ifndef SA_RESETHAND
00101   else
00102     {
00103       __sighandler_t handler;
00104       unsigned int mask;
00105       struct sigvec_wrapper_data *data;
00106       struct sigaction wrapper;
00107 
00108       handler = vec->sv_handler;
00109       mask = (unsigned int)vec->sv_mask;
00110       data = &sigvec_wrapper_data[sig];
00111       wrapper.sa_handler = sigvec_wrapper_handler;
00112       /* FIXME: should we set wrapper.sa_mask, wrapper.sa_flags??  */
00113       data->sw_handler = handler;
00114       data->sw_mask = mask;
00115 
00116       if (__sigaction (sig, &wrapper, &old) < 0)
00117        return -1;
00118     }
00119 #endif
00120 
00121   if (ovec != NULL)
00122     {
00123       __sighandler_t handler;
00124       unsigned int sv_flags;
00125       unsigned int sa_flags;
00126       unsigned int mask;
00127 
00128       handler = old.sa_handler;
00129       sv_flags = 0;
00130       sa_flags = old.sa_flags;
00131 #ifndef SA_RESETHAND
00132       if (handler == sigvec_wrapper_handler)
00133        {
00134          handler = sigvec_wrapper_data[sig].sw_handler;
00135          /* should we use data->sw_mask?? */
00136          sv_flags |= SV_RESETHAND;
00137        }
00138 #else
00139      if (sa_flags & SA_RESETHAND)
00140        sv_flags |= SV_RESETHAND;
00141 #endif
00142       mask = sigset_get_old_mask (&old.sa_mask);
00143 #ifdef SA_ONSTACK
00144      if (sa_flags & SA_ONSTACK)
00145        sv_flags |= SV_ONSTACK;
00146 #endif
00147 #ifdef SA_RESTART
00148      if (!(sa_flags & SA_RESTART))
00149 #endif
00150        sv_flags |= SV_INTERRUPT;
00151       ovec->sv_handler = handler;
00152       ovec->sv_mask = (int)mask;
00153       ovec->sv_flags = (int)sv_flags;
00154     }
00155 
00156   return 0;
00157 }
00158 
00159 weak_alias (__sigvec, sigvec)
00160 
00161 #ifndef SA_RESETHAND
00162 static void
00163 sigvec_wrapper_handler (sig)
00164      int sig;
00165 {
00166   struct sigvec_wrapper_data *data;
00167   struct sigaction act;
00168   int save;
00169   __sighandler_t handler;
00170 
00171   data = &sigvec_wrapper_data[sig];
00172   act.sa_handler = SIG_DFL;
00173   act.sa_flags = 0;
00174   sigset_set_old_mask (&act.sa_mask, data->sw_mask);
00175   handler = data->sw_handler;
00176   save = errno;
00177   (void) __sigaction (sig, &act, (struct sigaction *) NULL);
00178   __set_errno (save);
00179 
00180   (*handler) (sig);
00181 }
00182 #endif