Back to index

glibc  2.9
sigaction.c
Go to the documentation of this file.
00001 /* Copyright (C) 1997,1998,1999,2000,2002,2003,2004,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 <sgidefs.h>
00022 #include <signal.h>
00023 #include <string.h>
00024 
00025 #include <sysdep.h>
00026 #include <sys/syscall.h>
00027 
00028 #include <sgidefs.h>
00029 
00030 #include <kernel-features.h>
00031 
00032 /* The difference here is that the sigaction structure used in the
00033    kernel is not the same as we use in the libc.  Therefore we must
00034    translate it here.  */
00035 #include <kernel_sigaction.h>
00036 
00037 #if __ASSUME_REALTIME_SIGNALS == 0
00038 /* The variable is shared between all wrappers around signal handling
00039    functions which have RT equivalents.    This is the definition.  */
00040 int __libc_missing_rt_sigs;
00041 
00042 #endif
00043 
00044 #if _MIPS_SIM != _ABIO32
00045 
00046 # ifdef __NR_rt_sigreturn
00047 static void restore_rt (void) asm ("__restore_rt");
00048 # endif
00049 # ifdef __NR_sigreturn
00050 static void restore (void) asm ("__restore");
00051 # endif
00052 #endif
00053 
00054 /* If ACT is not NULL, change the action for SIG to *ACT.
00055    If OACT is not NULL, put the old action for SIG in *OACT.  */
00056 int
00057 __libc_sigaction (sig, act, oact)
00058      int sig;
00059      const struct sigaction *act;
00060      struct sigaction *oact;
00061 {
00062 #if __ASSUME_REALTIME_SIGNALS == 0
00063   struct old_kernel_sigaction k_sigact, k_osigact;
00064 #endif
00065   int result;
00066 
00067 #if defined __NR_rt_sigaction || __ASSUME_REALTIME_SIGNALS > 0
00068   /* First try the RT signals.     */
00069 # if __ASSUME_REALTIME_SIGNALS == 0
00070   if (!__libc_missing_rt_sigs)
00071 # endif
00072     {
00073       struct kernel_sigaction kact, koact;
00074       /* Save the current error value for later.  We need not do this
00075         if we are guaranteed to have realtime signals.   */
00076 # if __ASSUME_REALTIME_SIGNALS == 0
00077       int saved_errno = errno;
00078 # endif
00079 
00080       if (act)
00081        {
00082          kact.k_sa_handler = act->sa_handler;
00083          memcpy (&kact.sa_mask, &act->sa_mask, sizeof (kernel_sigset_t));
00084          kact.sa_flags = act->sa_flags;
00085 # ifdef HAVE_SA_RESTORER
00086 #  if _MIPS_SIM == _ABIO32
00087          kact.sa_restorer = act->sa_restorer;
00088 #  else
00089          kact.sa_restorer = &restore_rt;
00090 #  endif
00091 # endif
00092        }
00093 
00094       /* XXX The size argument hopefully will have to be changed to the
00095         real size of the user-level sigset_t.    */
00096       result = INLINE_SYSCALL (rt_sigaction, 4, sig,
00097                             act ? __ptrvalue (&kact) : NULL,
00098                             oact ? __ptrvalue (&koact) : NULL,
00099                             sizeof (kernel_sigset_t));
00100 
00101 # if __ASSUME_REALTIME_SIGNALS == 0
00102       if (result >= 0 || errno != ENOSYS)
00103 # endif
00104        {
00105          if (oact && result >= 0)
00106            {
00107              oact->sa_handler = koact.k_sa_handler;
00108              memcpy (&oact->sa_mask, &koact.sa_mask,
00109                             sizeof (kernel_sigset_t));
00110              oact->sa_flags = koact.sa_flags;
00111 # ifdef HAVE_SA_RESTORER
00112              oact->sa_restorer = koact.sa_restorer;
00113 # endif
00114            }
00115          return result;
00116        }
00117 
00118 # if __ASSUME_REALTIME_SIGNALS == 0
00119       __set_errno (saved_errno);
00120       __libc_missing_rt_sigs = 1;
00121 # endif
00122     }
00123 #endif
00124 
00125 #if __ASSUME_REALTIME_SIGNALS == 0
00126   if (act)
00127     {
00128       k_sigact.k_sa_handler = act->sa_handler;
00129       k_sigact.sa_mask = act->sa_mask.__val[0];
00130       k_sigact.sa_flags = act->sa_flags;
00131 # ifdef HAVE_SA_RESTORER
00132       k_sigact.sa_restorer = act->sa_restorer;
00133 # endif
00134     }
00135   result = INLINE_SYSCALL (sigaction, 3, sig,
00136                         act ? __ptrvalue (&k_sigact) : NULL,
00137                         oact ? __ptrvalue (&k_osigact) : NULL);
00138   if (oact && result >= 0)
00139     {
00140       oact->sa_handler = k_osigact.k_sa_handler;
00141       oact->sa_mask.__val[0] = k_osigact.sa_mask;
00142       oact->sa_flags = k_osigact.sa_flags;
00143 # ifdef HAVE_SA_RESTORER
00144 #  if _MIPS_SIM == _ABIO32
00145       oact->sa_restorer = k_osigact.sa_restorer;
00146 #  else
00147       oact->sa_restorer = &restore;
00148 #  endif
00149 # endif
00150     }
00151   return result;
00152 #endif
00153 }
00154 libc_hidden_def (__libc_sigaction)
00155 
00156 #ifdef WRAPPER_INCLUDE
00157 # include WRAPPER_INCLUDE
00158 #endif
00159 
00160 #ifndef LIBC_SIGACTION
00161 weak_alias (__libc_sigaction, __sigaction)
00162 libc_hidden_weak (__sigaction)
00163 weak_alias (__libc_sigaction, sigaction)
00164 #endif
00165 
00166 /* NOTE: Please think twice before making any changes to the bits of
00167    code below.  GDB needs some intimate knowledge about it to
00168    recognize them as signal trampolines, and make backtraces through
00169    signal handlers work right.  Important are both the names
00170    (__restore_rt) and the exact instruction sequence.
00171    If you ever feel the need to make any changes, please notify the
00172    appropriate GDB maintainer.  */
00173 
00174 #define RESTORE(name, syscall) RESTORE2 (name, syscall)
00175 #define RESTORE2(name, syscall) \
00176 asm                                       \
00177   (                                       \
00178    ".align 4\n"                                  \
00179    "__" #name ":\n"                       \
00180    "   li $2, " #syscall "\n"                    \
00181    "   syscall\n"                         \
00182    );
00183 
00184 /* The return code for realtime-signals.  */
00185 #if _MIPS_SIM != _ABIO32
00186 # ifdef __NR_rt_sigreturn
00187 RESTORE (restore_rt, __NR_rt_sigreturn)
00188 # endif
00189 # ifdef __NR_sigreturn
00190 RESTORE (restore, __NR_sigreturn)
00191 # endif
00192 #endif