This source file includes following definitions.
- sys_sgetmask
- sys_ssetmask
- sys_sigpending
- sys_sigsuspend
- save_old
- get_new
- sys_signal
- sys_sigaction
- do_signal
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
14 #include <asm/segment.h>
15
16 extern int core_dump(long signr,struct pt_regs * regs);
17
18 int sys_sgetmask()
19 {
20 return current->blocked;
21 }
22
23 int sys_ssetmask(int newmask)
24 {
25 int old=current->blocked;
26
27 current->blocked = newmask & ~(1<<(SIGKILL-1)) & ~(1<<(SIGSTOP-1));
28 return old;
29 }
30
31 int sys_sigpending(sigset_t *set)
32 {
33
34 verify_area(set,4);
35 put_fs_long(current->blocked & current->signal, (unsigned long *)set);
36 return 0;
37 }
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 int sys_sigsuspend(int restart, unsigned long old_mask, unsigned long set)
53 {
54 extern int sys_pause(void);
55
56 if (restart) {
57
58 current->blocked = old_mask;
59 return -EINTR;
60 }
61
62 *(&restart) = 1;
63 *(&old_mask) = current->blocked;
64 current->blocked = set;
65 (void) sys_pause();
66 return -ERESTARTNOINTR;
67 }
68
69 static inline void save_old(char * from,char * to)
70 {
71 int i;
72
73 verify_area(to, sizeof(struct sigaction));
74 for (i=0 ; i< sizeof(struct sigaction) ; i++) {
75 put_fs_byte(*from,to);
76 from++;
77 to++;
78 }
79 }
80
81 static inline void get_new(char * from,char * to)
82 {
83 int i;
84
85 for (i=0 ; i< sizeof(struct sigaction) ; i++)
86 *(to++) = get_fs_byte(from++);
87 }
88
89 int sys_signal(int signum, long handler, long restorer)
90 {
91 struct sigaction tmp;
92
93 if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
94 return -EINVAL;
95 tmp.sa_handler = (void (*)(int)) handler;
96 tmp.sa_mask = 0;
97 tmp.sa_flags = SA_ONESHOT | SA_NOMASK | SA_INTERRUPT;
98 tmp.sa_restorer = (void (*)(void)) restorer;
99 handler = (long) current->sigaction[signum-1].sa_handler;
100 current->sigaction[signum-1] = tmp;
101 return handler;
102 }
103
104 int sys_sigaction(int signum, const struct sigaction * action,
105 struct sigaction * oldaction)
106 {
107 struct sigaction tmp;
108
109 if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
110 return -EINVAL;
111 tmp = current->sigaction[signum-1];
112 get_new((char *) action,
113 (char *) (signum-1+current->sigaction));
114 if (oldaction)
115 save_old((char *) &tmp,(char *) oldaction);
116 if (current->sigaction[signum-1].sa_flags & SA_NOMASK)
117 current->sigaction[signum-1].sa_mask = 0;
118 else
119 current->sigaction[signum-1].sa_mask |= (1<<(signum-1));
120 return 0;
121 }
122
123 extern int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
124
125
126
127
128
129
130 int do_signal(long signr,struct pt_regs * regs)
131 {
132 unsigned long sa_handler;
133 long old_eip = regs->eip;
134 struct sigaction * sa = current->sigaction + signr - 1;
135 int longs;
136 unsigned long * tmp_esp;
137
138 #ifdef notdef
139 printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n",
140 current->pid, signr, regs->eax, regs->orig_eax,
141 sa->sa_flags & SA_INTERRUPT);
142 #endif
143 sa_handler = (unsigned long) sa->sa_handler;
144 if ((regs->orig_eax != -1) &&
145 ((regs->eax == -ERESTARTSYS) || (regs->eax == -ERESTARTNOINTR))) {
146 if ((sa_handler > 1) && (regs->eax == -ERESTARTSYS) &&
147 (sa->sa_flags & SA_INTERRUPT))
148 regs->eax = -EINTR;
149 else {
150 regs->eax = regs->orig_eax;
151 regs->eip = old_eip -= 2;
152 }
153 }
154 if (sa_handler==1) {
155
156 if (signr == SIGCHLD)
157 while (sys_waitpid(-1,NULL,WNOHANG) > 0)
158 ;
159 return(1);
160 }
161 if (!sa_handler) {
162 if (current->pid == 1)
163 return 1;
164 switch (signr) {
165 case SIGCONT:
166 case SIGCHLD:
167 case SIGWINCH:
168 return(1);
169
170 case SIGSTOP:
171 case SIGTSTP:
172 case SIGTTIN:
173 case SIGTTOU:
174 current->state = TASK_STOPPED;
175 current->exit_code = signr;
176 if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
177 SA_NOCLDSTOP))
178 send_sig(SIGCHLD, current->p_pptr, 1);
179 return(1);
180
181 case SIGQUIT:
182 case SIGILL:
183 case SIGTRAP:
184 case SIGIOT:
185 case SIGFPE:
186 case SIGSEGV:
187 if (core_dump(signr,regs))
188 do_exit(signr|0x80);
189
190 default:
191 do_exit(signr);
192 }
193 }
194
195
196
197 if (sa->sa_flags & SA_ONESHOT)
198 sa->sa_handler = NULL;
199 regs->eip = sa_handler;
200 longs = (sa->sa_flags & SA_NOMASK)?(7*4):(8*4);
201 regs->esp -= longs;
202 tmp_esp = (unsigned long *) regs->esp;
203 verify_area(tmp_esp,longs);
204 put_fs_long((long) sa->sa_restorer,tmp_esp++);
205 put_fs_long(signr,tmp_esp++);
206 if (!(sa->sa_flags & SA_NOMASK))
207 put_fs_long(current->blocked,tmp_esp++);
208 put_fs_long(regs->eax,tmp_esp++);
209 put_fs_long(regs->ecx,tmp_esp++);
210 put_fs_long(regs->edx,tmp_esp++);
211 put_fs_long(regs->eflags,tmp_esp++);
212 put_fs_long(old_eip,tmp_esp++);
213 current->blocked |= sa->sa_mask;
214
215 __asm__("testb $0,%%fs:%0"::"m" (*(char *) sa_handler));
216 return(0);
217 }