chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / ports / sysdeps / unix / sysv / sysv4 / sigaction.c
1 /* Copyright (C) 1994,1995,1996,1997,2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <errno.h>
20 #include <signal.h>
21 #include <stddef.h>
22
23 static __sighandler_t user_handlers[NSIG];
24
25 extern int __context_syscall (int, struct sigcontext *);
26 extern int __sigaction_syscall (int,
27                                 const struct sigaction *, struct sigaction *);
28
29 static void
30 trampoline (int sig, int code, struct sigcontext *context)
31 {
32   (*(void (*) (int, int, struct sigcontext *)) user_handlers[sig])
33     (sig, code, context);
34   __context_syscall (1, context);
35 }
36
37 /* If ACT is not NULL, change the action for SIG to *ACT.
38    If OACT is not NULL, put the old action for SIG in *OACT.  */
39 int
40 __sigaction (sig, act, oact)
41      int sig;
42      const struct sigaction *act;
43      struct sigaction *oact;
44 {
45   struct sigaction myact;
46   __sighandler_t ohandler;
47
48   if (sig <= 0 || sig >= NSIG)
49     {
50       __set_errno (EINVAL);
51       return -1;
52     }
53
54   ohandler = user_handlers[sig];
55
56   if (act != NULL)
57     {
58       user_handlers[sig] = act->sa_handler;
59       if (act->sa_handler != SIG_DFL && act->sa_handler != SIG_IGN)
60         {
61           myact = *act;
62           act = &myact;
63           act->sa_handler = (__sighandler_t) trampoline;
64         }
65     }
66
67   if (__sigaction_syscall (sig, act, oact) < 0)
68     {
69       /* The syscall got an error.  Restore the old handler and return -1.  */
70       user_handlers[sig] = ohandler;
71       return -1;
72     }
73
74   if (oact != NULL && oact->sa_handler == (__sighandler_t) trampoline)
75     oact->sa_handler = ohandler;
76
77   return 0;
78 }
79 libc_hidden_def (__sigaction)
80 weak_alias (__sigaction, sigaction)