Back to index

glibc  2.9
sigaction.c
Go to the documentation of this file.
00001 /* Copyright (C) 1997-2000,2002,2003,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 #include <signal.h>
00021 #include <string.h>
00022 
00023 #include <sysdep.h>
00024 #include <sys/syscall.h>
00025 
00026 #include <kernel-features.h>
00027 
00028 /* The difference here is that the sigaction structure used in the
00029    kernel is not the same as we use in the libc.  Therefore we must
00030    translate it here.  */
00031 #include <kernel_sigaction.h>
00032 
00033 #if __ASSUME_REALTIME_SIGNALS == 0
00034 /* The variable is shared between all wrappers around signal handling
00035    functions which have RT equivalents.  This is the definition.  */
00036 int __libc_missing_rt_sigs;
00037 #endif
00038 
00039 
00040 /* If ACT is not NULL, change the action for SIG to *ACT.
00041    If OACT is not NULL, put the old action for SIG in *OACT.  */
00042 int
00043 __libc_sigaction (sig, act, oact)
00044      int sig;
00045      const struct sigaction *act;
00046      struct sigaction *oact;
00047 {
00048 #if __ASSUME_REALTIME_SIGNALS == 0
00049   struct old_kernel_sigaction k_sigact, k_osigact;
00050 #endif
00051   int result;
00052 
00053 #if defined __NR_rt_sigaction || __ASSUME_REALTIME_SIGNALS > 0
00054   /* First try the RT signals.  */
00055 # if __ASSUME_REALTIME_SIGNALS == 0
00056   if (!__libc_missing_rt_sigs)
00057 # endif
00058     {
00059       struct kernel_sigaction kact, koact;
00060       /* Save the current error value for later.  We need not do this
00061         if we are guaranteed to have realtime signals.  */
00062 # if __ASSUME_REALTIME_SIGNALS == 0
00063       int saved_errno = errno;
00064 # endif
00065 
00066       if (act)
00067        {
00068          kact.k_sa_handler = act->sa_handler;
00069          memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
00070          kact.sa_flags = act->sa_flags;
00071 # ifdef HAVE_SA_RESTORER
00072          kact.sa_restorer = act->sa_restorer;
00073 # endif
00074        }
00075 
00076       /* XXX The size argument hopefully will have to be changed to the
00077         real size of the user-level sigset_t.  */
00078       result = INLINE_SYSCALL (rt_sigaction, 4, sig,
00079                             act ? __ptrvalue (&kact) : NULL,
00080                             oact ? __ptrvalue (&koact) : NULL, _NSIG / 8);
00081 
00082 # if __ASSUME_REALTIME_SIGNALS == 0
00083       if (result >= 0 || errno != ENOSYS)
00084 # endif
00085        {
00086          if (oact && result >= 0)
00087            {
00088              oact->sa_handler = koact.k_sa_handler;
00089              memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
00090              oact->sa_flags = koact.sa_flags;
00091 # ifdef HAVE_SA_RESTORER
00092              oact->sa_restorer = koact.sa_restorer;
00093 # endif
00094            }
00095          return result;
00096        }
00097 
00098 # if __ASSUME_REALTIME_SIGNALS == 0
00099       __set_errno (saved_errno);
00100       __libc_missing_rt_sigs = 1;
00101 # endif
00102     }
00103 #endif
00104 
00105 #if __ASSUME_REALTIME_SIGNALS == 0
00106   if (act)
00107     {
00108       k_sigact.k_sa_handler = act->sa_handler;
00109       k_sigact.sa_mask = act->sa_mask.__val[0];
00110       k_sigact.sa_flags = act->sa_flags;
00111 # ifdef HAVE_SA_RESTORER
00112       k_sigact.sa_restorer = act->sa_restorer;
00113 # endif
00114     }
00115   result = INLINE_SYSCALL (sigaction, 3, sig,
00116                         act ? __ptrvalue (&k_sigact) : NULL,
00117                         oact ? __ptrvalue (&k_osigact) : NULL);
00118   if (oact && result >= 0)
00119     {
00120       oact->sa_handler = k_osigact.k_sa_handler;
00121       oact->sa_mask.__val[0] = k_osigact.sa_mask;
00122       oact->sa_flags = k_osigact.sa_flags;
00123 # ifdef HAVE_SA_RESTORER
00124       oact->sa_restorer = k_osigact.sa_restorer;
00125 # endif
00126     }
00127   return result;
00128 #endif
00129 }
00130 libc_hidden_def (__libc_sigaction)
00131 
00132 #ifdef WRAPPER_INCLUDE
00133 # include WRAPPER_INCLUDE
00134 #endif
00135 
00136 #ifndef LIBC_SIGACTION
00137 weak_alias (__libc_sigaction, __sigaction)
00138 libc_hidden_weak (__sigaction)
00139 weak_alias (__libc_sigaction, sigaction)
00140 #endif