Back to index

glibc  2.9
sigaction.c
Go to the documentation of this file.
00001 /* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2005, 2006
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <signal.h>
00022 #include <string.h>
00023 
00024 #include <sysdep.h>
00025 #include <sys/syscall.h>
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 /* The variable is shared between all wrappers around signal handling
00034    functions which have RT equivalents.  */
00035 int __libc_missing_rt_sigs;
00036 
00037 #define SA_RESTORER  0x04000000
00038 
00039 #ifdef __ARM_EABI__
00040 extern void __default_sa_restorer_v1(void);
00041 extern void __default_sa_restorer_v2(void);
00042 extern void __default_rt_sa_restorer_v1(void);
00043 extern void __default_rt_sa_restorer_v2(void);
00044 # ifdef __ASSUME_SIGFRAME_V2
00045 #  define __default_sa_restorer __default_sa_restorer_v2
00046 #  define __default_rt_sa_restorer __default_rt_sa_restorer_v2
00047 # else
00048 #  include <ldsodefs.h>
00049 #  define __default_sa_restorer (GLRO(dl_osversion) >= 0x020612       \
00050                              ? __default_sa_restorer_v2 \
00051                              : __default_sa_restorer_v1)
00052 #  define __default_rt_sa_restorer (GLRO(dl_osversion) >= 0x020612    \
00053                                 ? __default_rt_sa_restorer_v2  \
00054                                 : __default_rt_sa_restorer_v1)
00055 # endif
00056 #else
00057 extern void __default_sa_restorer(void);
00058 extern void __default_rt_sa_restorer(void);
00059 #endif
00060 
00061 /* When RT signals are in use we need to use a different return stub.  */
00062 #ifdef __NR_rt_sigreturn
00063 #define choose_restorer(flags)                                 \
00064   (flags & SA_SIGINFO) ? __default_rt_sa_restorer              \
00065   : __default_sa_restorer
00066 #else
00067 #define choose_restorer(flags)                                 \
00068   __default_sa_restorer
00069 #endif
00070 
00071 /* If ACT is not NULL, change the action for SIG to *ACT.
00072    If OACT is not NULL, put the old action for SIG in *OACT.  */
00073 int
00074 __libc_sigaction (sig, act, oact)
00075      int sig;
00076      const struct sigaction *act;
00077      struct sigaction *oact;
00078 {
00079 #ifndef __ASSUME_REALTIME_SIGNALS
00080   struct old_kernel_sigaction k_sigact, k_osigact;
00081 #endif
00082   int result;
00083 
00084 #ifdef __NR_rt_sigaction
00085   /* First try the RT signals.  */
00086 # ifndef __ASSUME_REALTIME_SIGNALS
00087   if (!__libc_missing_rt_sigs)
00088 # endif
00089     {
00090       struct kernel_sigaction kact, koact;
00091 # ifndef __ASSUME_REALTIME_SIGNALS
00092       int saved_errno = errno;
00093 # endif
00094 
00095       if (act)
00096        {
00097          kact.k_sa_handler = act->sa_handler;
00098          memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
00099          kact.sa_flags = act->sa_flags;
00100 # ifdef HAVE_SA_RESTORER
00101          if (kact.sa_flags & SA_RESTORER)
00102            kact.sa_restorer = act->sa_restorer;
00103          else
00104            {
00105              kact.sa_restorer = choose_restorer (kact.sa_flags);
00106              kact.sa_flags |= SA_RESTORER;
00107            }
00108 # endif
00109        }
00110 
00111       /* XXX The size argument hopefully will have to be changed to the
00112         real size of the user-level sigset_t.  */
00113       result = INLINE_SYSCALL (rt_sigaction, 4, sig,
00114                             act ? __ptrvalue (&kact) : NULL,
00115                             oact ? __ptrvalue (&koact) : NULL, _NSIG / 8);
00116 
00117 # ifndef __ASSUME_REALTIME_SIGNALS
00118       if (result >= 0 || errno != ENOSYS)
00119 # endif
00120        {
00121          if (oact && result >= 0)
00122            {
00123              oact->sa_handler = koact.k_sa_handler;
00124              memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
00125              oact->sa_flags = koact.sa_flags;
00126 # ifdef HAVE_SA_RESTORER
00127              oact->sa_restorer = koact.sa_restorer;
00128 # endif
00129            }
00130          return result;
00131        }
00132 
00133 # ifndef __ASSUME_REALTIME_SIGNALS
00134       __set_errno (saved_errno);
00135       __libc_missing_rt_sigs = 1;
00136 # endif
00137     }
00138 #endif
00139 
00140 #ifndef __ASSUME_REALTIME_SIGNALS
00141   if (act)
00142     {
00143       k_sigact.k_sa_handler = act->sa_handler;
00144       k_sigact.sa_mask = act->sa_mask.__val[0];
00145       k_sigact.sa_flags = act->sa_flags;
00146 # ifdef HAVE_SA_RESTORER
00147       if (k_sigact.sa_flags & SA_RESTORER)
00148        k_sigact.sa_restorer = act->sa_restorer;
00149       else
00150        {
00151          k_sigact.sa_restorer = choose_restorer (k_sigact.sa_flags);
00152          k_sigact.sa_flags |= SA_RESTORER;
00153        }
00154 # endif
00155     }
00156   result = INLINE_SYSCALL (sigaction, 3, sig,
00157                         act ? __ptrvalue (&k_sigact) : NULL,
00158                         oact ? __ptrvalue (&k_osigact) : NULL);
00159   if (oact && result >= 0)
00160     {
00161       oact->sa_handler = k_osigact.k_sa_handler;
00162       oact->sa_mask.__val[0] = k_osigact.sa_mask;
00163       oact->sa_flags = k_osigact.sa_flags;
00164 # ifdef HAVE_SA_RESTORER
00165       oact->sa_restorer = k_osigact.sa_restorer;
00166 # endif
00167     }
00168   return result;
00169 #endif
00170 }
00171 libc_hidden_def (__libc_sigaction)
00172 
00173 #ifdef WRAPPER_INCLUDE
00174 # include WRAPPER_INCLUDE
00175 #endif
00176 
00177 #ifndef LIBC_SIGACTION
00178 weak_alias (__libc_sigaction, __sigaction)
00179 libc_hidden_weak (__sigaction)
00180 weak_alias (__libc_sigaction, sigaction)
00181 #endif