This source file includes following definitions.
- sys_sigprocmask
- sys_sgetmask
- sys_ssetmask
- sys_sigpending
- check_pending
- sys_signal
- sys_sigaction
1
2
3
4
5
6
7 #include <linux/sched.h>
8 #include <linux/kernel.h>
9 #include <linux/signal.h>
10 #include <linux/errno.h>
11 #include <linux/wait.h>
12 #include <linux/ptrace.h>
13 #include <linux/unistd.h>
14
15 #include <asm/segment.h>
16
17 #define _S(nr) (1<<((nr)-1))
18
19 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
20
21 asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
22 {
23 sigset_t new_set, old_set = current->blocked;
24 int error;
25
26 if (set) {
27 error = verify_area(VERIFY_READ, set, sizeof(sigset_t));
28 if (error)
29 return error;
30 new_set = get_fs_long((unsigned long *) set) & _BLOCKABLE;
31 switch (how) {
32 case SIG_BLOCK:
33 current->blocked |= new_set;
34 break;
35 case SIG_UNBLOCK:
36 current->blocked &= ~new_set;
37 break;
38 case SIG_SETMASK:
39 current->blocked = new_set;
40 break;
41 default:
42 return -EINVAL;
43 }
44 }
45 if (oset) {
46 error = verify_area(VERIFY_WRITE, oset, sizeof(sigset_t));
47 if (error)
48 return error;
49 put_fs_long(old_set, (unsigned long *) oset);
50 }
51 return 0;
52 }
53
54 asmlinkage int sys_sgetmask(void)
55 {
56 return current->blocked;
57 }
58
59 asmlinkage int sys_ssetmask(int newmask)
60 {
61 int old=current->blocked;
62
63 current->blocked = newmask & _BLOCKABLE;
64 return old;
65 }
66
67 asmlinkage int sys_sigpending(sigset_t *set)
68 {
69 int error;
70
71 error = verify_area(VERIFY_WRITE, set, 4);
72 if (!error)
73 put_fs_long(current->blocked & current->signal, (unsigned long *)set);
74 return error;
75 }
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 static void check_pending(int signum)
93 {
94 struct sigaction *p;
95
96 p = signum - 1 + current->sigaction;
97 if (p->sa_handler == SIG_IGN) {
98 if (signum == SIGCHLD)
99 return;
100 current->signal &= ~_S(signum);
101 return;
102 }
103 if (p->sa_handler == SIG_DFL) {
104 if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH)
105 return;
106 current->signal &= ~_S(signum);
107 return;
108 }
109 }
110
111 asmlinkage unsigned long sys_signal(int signum, void (*handler)(int))
112 {
113 int err;
114 struct sigaction tmp;
115
116 if (signum<1 || signum>32)
117 return -EINVAL;
118 if (signum==SIGKILL || signum==SIGSTOP)
119 return -EINVAL;
120 if (handler != SIG_DFL && handler != SIG_IGN) {
121 err = verify_area(VERIFY_READ, handler, 1);
122 if (err)
123 return err;
124 }
125 tmp.sa_handler = handler;
126 tmp.sa_mask = 0;
127 tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
128 tmp.sa_restorer = NULL;
129 handler = current->sigaction[signum-1].sa_handler;
130 current->sigaction[signum-1] = tmp;
131 check_pending(signum);
132 return (unsigned long) handler;
133 }
134
135 asmlinkage int sys_sigaction(int signum, const struct sigaction * action,
136 struct sigaction * oldaction)
137 {
138 struct sigaction new_sa, *p;
139
140 if (signum<1 || signum>32)
141 return -EINVAL;
142 if (signum==SIGKILL || signum==SIGSTOP)
143 return -EINVAL;
144 p = signum - 1 + current->sigaction;
145 if (action) {
146 int err = verify_area(VERIFY_READ, action, sizeof(*action));
147 if (err)
148 return err;
149 memcpy_fromfs(&new_sa, action, sizeof(struct sigaction));
150 if (new_sa.sa_flags & SA_NOMASK)
151 new_sa.sa_mask = 0;
152 else {
153 new_sa.sa_mask |= _S(signum);
154 new_sa.sa_mask &= _BLOCKABLE;
155 }
156 if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
157 err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
158 if (err)
159 return err;
160 }
161 }
162 if (oldaction) {
163 int err = verify_area(VERIFY_WRITE, oldaction, sizeof(*oldaction));
164 if (err)
165 return err;
166 memcpy_tofs(oldaction, p, sizeof(struct sigaction));
167 }
168 if (action) {
169 *p = new_sa;
170 check_pending(signum);
171 }
172 return 0;
173 }