9a362262174c8838f52f7bf9d7023f0aeec445ce
[musl] / src / signal / sigaction.c
1 #include <stdlib.h>
2 #include <signal.h>
3 #include <errno.h>
4 #include "syscall.h"
5 #include "pthread_impl.h"
6
7 static void restorer()
8 {
9         syscall0(__NR_rt_sigreturn);
10 }
11
12 int __libc_sigaction(int sig, const struct sigaction *sa, struct sigaction *old)
13 {
14         struct {
15                 void *handler;
16                 unsigned long flags;
17                 void (*restorer)(void);
18                 sigset_t mask;
19         } ksa, kold;
20         long pksa=0, pkold=0;
21         if (sa) {
22                 ksa.handler = sa->sa_handler;
23                 ksa.flags = sa->sa_flags | SA_RESTORER;
24                 ksa.restorer = restorer;
25                 ksa.mask = sa->sa_mask;
26                 pksa = (long)&ksa;
27         }
28         if (old) pkold = (long)&kold;
29         if (syscall4(__NR_rt_sigaction, sig, pksa, pkold, 8))
30                 return -1;
31         if (old) {
32                 old->sa_handler = kold.handler;
33                 old->sa_flags = kold.flags;
34                 old->sa_mask = kold.mask;
35         }
36         return 0;
37 }
38
39 int __sigaction(int sig, const struct sigaction *sa, struct sigaction *old)
40 {
41         if (sig == SIGCANCEL || sig == SIGSYSCALL) {
42                 errno = EINVAL;
43                 return -1;
44         }
45         return __libc_sigaction(sig, sa, old);
46 }
47
48 weak_alias(__sigaction, sigaction);