Commit | Line | Data |
---|---|---|
1d348849 | 1 | /* kern_sig.c 6.3 84/05/22 */ |
961945a8 SL |
2 | |
3 | #include "../machine/reg.h" | |
4 | #include "../machine/pte.h" | |
5 | #include "../machine/psl.h" | |
687880f9 BJ |
6 | |
7 | #include "../h/param.h" | |
8 | #include "../h/systm.h" | |
9 | #include "../h/dir.h" | |
10 | #include "../h/user.h" | |
687880f9 BJ |
11 | #include "../h/inode.h" |
12 | #include "../h/proc.h" | |
687880f9 BJ |
13 | #include "../h/timeb.h" |
14 | #include "../h/times.h" | |
15 | #include "../h/conf.h" | |
16 | #include "../h/buf.h" | |
17 | #include "../h/mount.h" | |
18 | #include "../h/text.h" | |
19 | #include "../h/seg.h" | |
687880f9 | 20 | #include "../h/vm.h" |
687880f9 | 21 | #include "../h/acct.h" |
7b0cb7cb | 22 | #include "../h/uio.h" |
68954b3a | 23 | #include "../h/kernel.h" |
4f083fd7 | 24 | #include "../h/nami.h" |
687880f9 | 25 | |
457aa395 SL |
26 | #define mask(s) (1 << ((s)-1)) |
27 | #define cantmask (mask(SIGKILL)|mask(SIGCONT)|mask(SIGSTOP)) | |
28 | ||
4147b3f6 BJ |
29 | sigvec() |
30 | { | |
457aa395 | 31 | register struct a { |
dd012d1e | 32 | int signo; |
457aa395 SL |
33 | struct sigvec *nsv; |
34 | struct sigvec *osv; | |
dd012d1e | 35 | } *uap = (struct a *)u.u_ap; |
457aa395 SL |
36 | struct sigvec vec; |
37 | register struct sigvec *sv; | |
dd012d1e SL |
38 | register int sig; |
39 | ||
40 | sig = uap->signo; | |
457aa395 | 41 | if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) { |
dd012d1e SL |
42 | u.u_error = EINVAL; |
43 | return; | |
44 | } | |
457aa395 SL |
45 | sv = &vec; |
46 | if (uap->osv) { | |
47 | sv->sv_handler = u.u_signal[sig]; | |
48 | sv->sv_mask = u.u_sigmask[sig]; | |
49 | sv->sv_onstack = (u.u_sigonstack & mask(sig)) != 0; | |
50 | u.u_error = | |
51 | copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); | |
52 | if (u.u_error) | |
53 | return; | |
54 | } | |
55 | if (uap->nsv) { | |
56 | u.u_error = | |
57 | copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); | |
58 | if (u.u_error) | |
59 | return; | |
60 | if (sig == SIGCONT && sv->sv_handler == SIG_IGN) { | |
61 | u.u_error = EINVAL; | |
62 | return; | |
63 | } | |
64 | setsigvec(sig, sv); | |
65 | } | |
dd012d1e | 66 | } |
4147b3f6 | 67 | |
457aa395 SL |
68 | setsigvec(sig, sv) |
69 | int sig; | |
70 | register struct sigvec *sv; | |
dd012d1e SL |
71 | { |
72 | register struct proc *p; | |
457aa395 | 73 | register int bit; |
dd012d1e | 74 | |
457aa395 | 75 | bit = mask(sig); |
dd012d1e SL |
76 | p = u.u_procp; |
77 | /* | |
78 | * Change setting atomically. | |
79 | */ | |
80 | (void) spl6(); | |
457aa395 SL |
81 | u.u_signal[sig] = sv->sv_handler; |
82 | u.u_sigmask[sig] = sv->sv_mask &~ cantmask; | |
83 | if (sv->sv_onstack) | |
84 | u.u_sigonstack |= bit; | |
85 | else | |
86 | u.u_sigonstack &= ~bit; | |
87 | if (sv->sv_handler == SIG_IGN) { | |
88 | p->p_sig &= ~bit; /* never to be seen again */ | |
89 | p->p_sigignore |= bit; | |
90 | p->p_sigcatch &= ~bit; | |
dd012d1e | 91 | } else { |
457aa395 SL |
92 | p->p_sigignore &= ~bit; |
93 | if (sv->sv_handler == SIG_DFL) | |
94 | p->p_sigcatch &= ~bit; | |
dd012d1e | 95 | else |
457aa395 | 96 | p->p_sigcatch |= bit; |
dd012d1e SL |
97 | } |
98 | (void) spl0(); | |
4147b3f6 BJ |
99 | } |
100 | ||
101 | sigblock() | |
102 | { | |
dd012d1e | 103 | struct a { |
457aa395 | 104 | int sigmask; |
dd012d1e | 105 | } *uap = (struct a *)u.u_ap; |
457aa395 | 106 | register struct proc *p = u.u_procp; |
4147b3f6 | 107 | |
dd012d1e SL |
108 | (void) spl6(); |
109 | u.u_r.r_val1 = p->p_sigmask; | |
457aa395 | 110 | p->p_sigmask |= uap->sigmask &~ cantmask; |
dd012d1e | 111 | (void) spl0(); |
4147b3f6 BJ |
112 | } |
113 | ||
114 | sigsetmask() | |
687880f9 | 115 | { |
dd012d1e | 116 | struct a { |
457aa395 | 117 | int sigmask; |
dd012d1e SL |
118 | } *uap = (struct a *)u.u_ap; |
119 | register struct proc *p = u.u_procp; | |
687880f9 | 120 | |
dd012d1e SL |
121 | (void) spl6(); |
122 | u.u_r.r_val1 = p->p_sigmask; | |
457aa395 | 123 | p->p_sigmask = uap->sigmask &~ cantmask; |
dd012d1e | 124 | (void) spl0(); |
687880f9 BJ |
125 | } |
126 | ||
4147b3f6 BJ |
127 | sigpause() |
128 | { | |
dd012d1e | 129 | struct a { |
457aa395 | 130 | int sigmask; |
dd012d1e SL |
131 | } *uap = (struct a *)u.u_ap; |
132 | register struct proc *p = u.u_procp; | |
4147b3f6 | 133 | |
dd012d1e SL |
134 | /* |
135 | * When returning from sigpause, we want | |
136 | * the old mask to be restored after the | |
137 | * signal handler has finished. Thus, we | |
138 | * save it here and mark the proc structure | |
139 | * to indicate this (should be in u.). | |
140 | */ | |
141 | u.u_oldmask = p->p_sigmask; | |
142 | p->p_flag |= SOMASK; | |
457aa395 | 143 | p->p_sigmask = uap->sigmask &~ cantmask; |
dd012d1e SL |
144 | for (;;) |
145 | sleep((caddr_t)&u, PSLEP); | |
146 | /*NOTREACHED*/ | |
4147b3f6 | 147 | } |
457aa395 SL |
148 | #undef cantmask |
149 | #undef mask | |
4147b3f6 BJ |
150 | |
151 | sigstack() | |
152 | { | |
457aa395 | 153 | register struct a { |
457aa395 SL |
154 | struct sigstack *nss; |
155 | struct sigstack *oss; | |
dd012d1e | 156 | } *uap = (struct a *)u.u_ap; |
457aa395 | 157 | struct sigstack ss; |
4147b3f6 | 158 | |
457aa395 SL |
159 | if (uap->oss) { |
160 | u.u_error = copyout((caddr_t)&u.u_sigstack, (caddr_t)uap->oss, | |
161 | sizeof (struct sigstack)); | |
162 | if (u.u_error) | |
163 | return; | |
164 | } | |
165 | if (uap->nss) { | |
166 | u.u_error = | |
167 | copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)); | |
168 | if (u.u_error == 0) | |
169 | u.u_sigstack = ss; | |
170 | } | |
4147b3f6 BJ |
171 | } |
172 | ||
75a02b8d SL |
173 | /* KILL SHOULD BE UPDATED */ |
174 | ||
1e3738da BJ |
175 | kill() |
176 | { | |
dd012d1e SL |
177 | register struct a { |
178 | int pid; | |
179 | int signo; | |
180 | } *uap = (struct a *)u.u_ap; | |
1e3738da | 181 | |
75a02b8d SL |
182 | u.u_error = kill1(uap->signo < 0, |
183 | uap->signo < 0 ? -uap->signo : uap->signo, uap->pid); | |
1e3738da BJ |
184 | } |
185 | ||
186 | killpg() | |
187 | { | |
3b4f6e10 SL |
188 | register struct a { |
189 | int pgrp; | |
190 | int signo; | |
191 | } *uap = (struct a *)u.u_ap; | |
1e3738da | 192 | |
88a7a62a | 193 | u.u_error = kill1(1, uap->signo, uap->pgrp); |
1e3738da BJ |
194 | } |
195 | ||
dd012d1e SL |
196 | /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ |
197 | ||
88a7a62a | 198 | kill1(ispgrp, signo, who) |
3b4f6e10 SL |
199 | int ispgrp, signo, who; |
200 | { | |
201 | register struct proc *p; | |
202 | int f, priv = 0; | |
203 | ||
dc7d58ca | 204 | if (signo < 0 || signo > NSIG) |
3b4f6e10 SL |
205 | return (EINVAL); |
206 | if (who > 0 && !ispgrp) { | |
207 | p = pfind(who); | |
ac199305 | 208 | if (p == 0) |
3b4f6e10 | 209 | return (ESRCH); |
ac199305 KM |
210 | if (u.u_uid && u.u_uid != p->p_uid) |
211 | return (EPERM); | |
dc7d58ca SL |
212 | if (signo) |
213 | psignal(p, signo); | |
3b4f6e10 | 214 | return (0); |
687880f9 | 215 | } |
3b4f6e10 SL |
216 | if (who == -1 && u.u_uid == 0) |
217 | priv++, who = 0, ispgrp = 1; /* like sending to pgrp */ | |
218 | else if (who == 0) { | |
687880f9 BJ |
219 | /* |
220 | * Zero process id means send to my process group. | |
221 | */ | |
3b4f6e10 SL |
222 | ispgrp = 1; |
223 | who = u.u_procp->p_pgrp; | |
224 | if (who == 0) | |
225 | return (EINVAL); | |
687880f9 | 226 | } |
1d348849 | 227 | for (f = 0, p = allproc; p != NULL; p = p->p_nxt) { |
3b4f6e10 SL |
228 | if (!ispgrp) { |
229 | if (p->p_pid != who) | |
687880f9 | 230 | continue; |
3b4f6e10 SL |
231 | } else if (p->p_pgrp != who && priv == 0 || p->p_ppid == 0 || |
232 | (p->p_flag&SSYS) || (priv && p == u.u_procp)) | |
687880f9 BJ |
233 | continue; |
234 | if (u.u_uid != 0 && u.u_uid != p->p_uid && | |
3b4f6e10 | 235 | (signo != SIGCONT || !inferior(p))) |
687880f9 BJ |
236 | continue; |
237 | f++; | |
dc7d58ca SL |
238 | if (signo) |
239 | psignal(p, signo); | |
687880f9 | 240 | } |
88a7a62a | 241 | return (f == 0 ? ESRCH : 0); |
4147b3f6 | 242 | } |
687880f9 BJ |
243 | |
244 | /* | |
245 | * Send the specified signal to | |
246 | * all processes with 'pgrp' as | |
247 | * process group. | |
687880f9 BJ |
248 | */ |
249 | gsignal(pgrp, sig) | |
250 | register int pgrp; | |
251 | { | |
252 | register struct proc *p; | |
253 | ||
254 | if (pgrp == 0) | |
255 | return; | |
1d348849 | 256 | for (p = allproc; p != NULL; p = p->p_nxt) |
687880f9 BJ |
257 | if (p->p_pgrp == pgrp) |
258 | psignal(p, sig); | |
259 | } | |
260 | ||
261 | /* | |
262 | * Send the specified signal to | |
263 | * the specified process. | |
264 | */ | |
265 | psignal(p, sig) | |
266 | register struct proc *p; | |
267 | register int sig; | |
268 | { | |
269 | register int s; | |
270 | register int (*action)(); | |
dd012d1e | 271 | int sigmask; |
687880f9 BJ |
272 | |
273 | if ((unsigned)sig >= NSIG) | |
274 | return; | |
dd012d1e | 275 | sigmask = 1 << (sig-1); |
687880f9 BJ |
276 | |
277 | /* | |
278 | * If proc is traced, always give parent a chance. | |
687880f9 BJ |
279 | */ |
280 | if (p->p_flag & STRC) | |
281 | action = SIG_DFL; | |
282 | else { | |
687880f9 | 283 | /* |
dd012d1e SL |
284 | * If the signal is being ignored, |
285 | * then we forget about it immediately. | |
687880f9 | 286 | */ |
dd012d1e | 287 | if (p->p_sigignore & sigmask) |
687880f9 | 288 | return; |
dd012d1e SL |
289 | if (p->p_sigmask & sigmask) |
290 | action = SIG_HOLD; | |
291 | else if (p->p_sigcatch & sigmask) | |
292 | action = SIG_CATCH; | |
293 | else | |
294 | action = SIG_DFL; | |
687880f9 BJ |
295 | } |
296 | #define mask(sig) (1<<(sig-1)) | |
297 | #define stops (mask(SIGSTOP)|mask(SIGTSTP)|mask(SIGTTIN)|mask(SIGTTOU)) | |
298 | if (sig) { | |
299 | p->p_sig |= sigmask; | |
300 | switch (sig) { | |
301 | ||
302 | case SIGTERM: | |
dd012d1e | 303 | if ((p->p_flag&STRC) || action != SIG_DFL) |
687880f9 BJ |
304 | break; |
305 | /* fall into ... */ | |
306 | ||
307 | case SIGKILL: | |
308 | if (p->p_nice > NZERO) | |
309 | p->p_nice = NZERO; | |
310 | break; | |
311 | ||
312 | case SIGCONT: | |
313 | p->p_sig &= ~stops; | |
314 | break; | |
315 | ||
316 | case SIGSTOP: | |
317 | case SIGTSTP: | |
318 | case SIGTTIN: | |
319 | case SIGTTOU: | |
320 | p->p_sig &= ~mask(SIGCONT); | |
321 | break; | |
322 | } | |
323 | } | |
324 | #undef mask | |
325 | #undef stops | |
326 | /* | |
327 | * Defer further processing for signals which are held. | |
328 | */ | |
329 | if (action == SIG_HOLD) | |
330 | return; | |
331 | s = spl6(); | |
332 | switch (p->p_stat) { | |
333 | ||
334 | case SSLEEP: | |
335 | /* | |
336 | * If process is sleeping at negative priority | |
337 | * we can't interrupt the sleep... the signal will | |
338 | * be noticed when the process returns through | |
339 | * trap() or syscall(). | |
340 | */ | |
341 | if (p->p_pri <= PZERO) | |
342 | goto out; | |
343 | /* | |
344 | * Process is sleeping and traced... make it runnable | |
345 | * so it can discover the signal in issig() and stop | |
346 | * for the parent. | |
347 | */ | |
348 | if (p->p_flag&STRC) | |
349 | goto run; | |
350 | switch (sig) { | |
351 | ||
352 | case SIGSTOP: | |
353 | case SIGTSTP: | |
354 | case SIGTTIN: | |
355 | case SIGTTOU: | |
356 | /* | |
357 | * These are the signals which by default | |
358 | * stop a process. | |
359 | */ | |
360 | if (action != SIG_DFL) | |
361 | goto run; | |
362 | /* | |
363 | * Don't clog system with children of init | |
364 | * stopped from the keyboard. | |
365 | */ | |
366 | if (sig != SIGSTOP && p->p_pptr == &proc[1]) { | |
367 | psignal(p, SIGKILL); | |
368 | p->p_sig &= ~sigmask; | |
369 | splx(s); | |
370 | return; | |
371 | } | |
372 | /* | |
373 | * If a child in vfork(), stopping could | |
374 | * cause deadlock. | |
375 | */ | |
376 | if (p->p_flag&SVFORK) | |
377 | goto out; | |
378 | p->p_sig &= ~sigmask; | |
379 | p->p_cursig = sig; | |
380 | stop(p); | |
381 | goto out; | |
382 | ||
383 | case SIGIO: | |
384 | case SIGURG: | |
385 | case SIGCHLD: | |
386 | /* | |
387 | * These signals are special in that they | |
388 | * don't get propogated... if the process | |
389 | * isn't interested, forget it. | |
390 | */ | |
391 | if (action != SIG_DFL) | |
392 | goto run; | |
393 | p->p_sig &= ~sigmask; /* take it away */ | |
394 | goto out; | |
395 | ||
396 | default: | |
397 | /* | |
398 | * All other signals cause the process to run | |
399 | */ | |
400 | goto run; | |
401 | } | |
402 | /*NOTREACHED*/ | |
403 | ||
404 | case SSTOP: | |
405 | /* | |
406 | * If traced process is already stopped, | |
407 | * then no further action is necessary. | |
408 | */ | |
409 | if (p->p_flag&STRC) | |
410 | goto out; | |
411 | switch (sig) { | |
412 | ||
413 | case SIGKILL: | |
414 | /* | |
415 | * Kill signal always sets processes running. | |
416 | */ | |
417 | goto run; | |
418 | ||
419 | case SIGCONT: | |
420 | /* | |
421 | * If the process catches SIGCONT, let it handle | |
422 | * the signal itself. If it isn't waiting on | |
423 | * an event, then it goes back to run state. | |
424 | * Otherwise, process goes back to sleep state. | |
425 | */ | |
426 | if (action != SIG_DFL || p->p_wchan == 0) | |
427 | goto run; | |
428 | p->p_stat = SSLEEP; | |
429 | goto out; | |
430 | ||
431 | case SIGSTOP: | |
432 | case SIGTSTP: | |
433 | case SIGTTIN: | |
434 | case SIGTTOU: | |
435 | /* | |
436 | * Already stopped, don't need to stop again. | |
437 | * (If we did the shell could get confused.) | |
438 | */ | |
439 | p->p_sig &= ~sigmask; /* take it away */ | |
440 | goto out; | |
441 | ||
442 | default: | |
443 | /* | |
444 | * If process is sleeping interruptibly, then | |
445 | * unstick it so that when it is continued | |
446 | * it can look at the signal. | |
447 | * But don't setrun the process as its not to | |
448 | * be unstopped by the signal alone. | |
449 | */ | |
450 | if (p->p_wchan && p->p_pri > PZERO) | |
451 | unsleep(p); | |
452 | goto out; | |
453 | } | |
454 | /*NOTREACHED*/ | |
455 | ||
456 | default: | |
457 | /* | |
458 | * SRUN, SIDL, SZOMB do nothing with the signal, | |
459 | * other than kicking ourselves if we are running. | |
460 | * It will either never be noticed, or noticed very soon. | |
461 | */ | |
462 | if (p == u.u_procp && !noproc) | |
206ecc72 | 463 | #include "../vax/mtpr.h" |
687880f9 BJ |
464 | aston(); |
465 | goto out; | |
466 | } | |
467 | /*NOTREACHED*/ | |
468 | run: | |
469 | /* | |
470 | * Raise priority to at least PUSER. | |
471 | */ | |
472 | if (p->p_pri > PUSER) | |
473 | if ((p != u.u_procp || noproc) && p->p_stat == SRUN && | |
474 | (p->p_flag & SLOAD)) { | |
475 | remrq(p); | |
476 | p->p_pri = PUSER; | |
477 | setrq(p); | |
478 | } else | |
479 | p->p_pri = PUSER; | |
480 | setrun(p); | |
481 | out: | |
482 | splx(s); | |
483 | } | |
484 | ||
485 | /* | |
486 | * Returns true if the current | |
487 | * process has a signal to process. | |
488 | * The signal to process is put in p_cursig. | |
489 | * This is asked at least once each time a process enters the | |
490 | * system (though this can usually be done without actually | |
491 | * calling issig by checking the pending signal masks.) | |
492 | * A signal does not do anything | |
493 | * directly to a process; it sets | |
494 | * a flag that asks the process to | |
495 | * do something to itself. | |
496 | */ | |
497 | issig() | |
498 | { | |
499 | register struct proc *p; | |
500 | register int sig; | |
dd012d1e | 501 | int sigbits, sigmask; |
687880f9 BJ |
502 | |
503 | p = u.u_procp; | |
504 | for (;;) { | |
f99e4a3a | 505 | sigbits = p->p_sig &~ p->p_sigmask; |
687880f9 | 506 | if ((p->p_flag&STRC) == 0) |
f99e4a3a | 507 | sigbits &= ~p->p_sigignore; |
687880f9 BJ |
508 | if (p->p_flag&SVFORK) |
509 | #define bit(a) (1<<(a-1)) | |
510 | sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); | |
511 | if (sigbits == 0) | |
512 | break; | |
dd012d1e SL |
513 | sig = ffs(sigbits); |
514 | sigmask = 1 << (sig-1); | |
687880f9 BJ |
515 | p->p_sig &= ~sigmask; /* take the signal! */ |
516 | p->p_cursig = sig; | |
dd012d1e | 517 | if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) { |
687880f9 BJ |
518 | /* |
519 | * If traced, always stop, and stay | |
520 | * stopped until released by the parent. | |
521 | */ | |
522 | do { | |
523 | stop(p); | |
524 | swtch(); | |
525 | } while (!procxmt() && p->p_flag&STRC); | |
526 | ||
527 | /* | |
f99e4a3a SL |
528 | * If the traced bit got turned off, |
529 | * then put the signal taken above back into p_sig | |
530 | * and go back up to the top to rescan signals. | |
531 | * This ensures that p_sig* and u_signal are consistent. | |
687880f9 | 532 | */ |
f99e4a3a | 533 | if ((p->p_flag&STRC) == 0) { |
687880f9 BJ |
534 | p->p_sig |= sigmask; |
535 | continue; | |
536 | } | |
537 | ||
538 | /* | |
539 | * If parent wants us to take the signal, | |
540 | * then it will leave it in p->p_cursig; | |
541 | * otherwise we just look for signals again. | |
542 | */ | |
543 | sig = p->p_cursig; | |
544 | if (sig == 0) | |
545 | continue; | |
f99e4a3a SL |
546 | |
547 | /* | |
548 | * If signal is being masked put it back | |
549 | * into p_sig and look for other signals. | |
550 | */ | |
551 | sigmask = 1 << (sig-1); | |
552 | if (p->p_sigmask & sigmask) { | |
553 | p->p_sig |= sigmask; | |
554 | continue; | |
555 | } | |
687880f9 BJ |
556 | } |
557 | switch (u.u_signal[sig]) { | |
558 | ||
559 | case SIG_DFL: | |
560 | /* | |
561 | * Don't take default actions on system processes. | |
562 | */ | |
563 | if (p->p_ppid == 0) | |
564 | break; | |
565 | switch (sig) { | |
566 | ||
567 | case SIGTSTP: | |
568 | case SIGTTIN: | |
569 | case SIGTTOU: | |
570 | /* | |
571 | * Children of init aren't allowed to stop | |
572 | * on signals from the keyboard. | |
573 | */ | |
574 | if (p->p_pptr == &proc[1]) { | |
575 | psignal(p, SIGKILL); | |
576 | continue; | |
577 | } | |
578 | /* fall into ... */ | |
579 | ||
580 | case SIGSTOP: | |
581 | if (p->p_flag&STRC) | |
582 | continue; | |
583 | stop(p); | |
584 | swtch(); | |
585 | continue; | |
586 | ||
587 | case SIGCONT: | |
588 | case SIGCHLD: | |
dd012d1e | 589 | case SIGURG: |
457aa395 | 590 | case SIGIO: |
687880f9 BJ |
591 | /* |
592 | * These signals are normally not | |
593 | * sent if the action is the default. | |
594 | */ | |
595 | continue; /* == ignore */ | |
596 | ||
597 | default: | |
598 | goto send; | |
599 | } | |
600 | /*NOTREACHED*/ | |
601 | ||
602 | case SIG_HOLD: | |
603 | case SIG_IGN: | |
604 | /* | |
605 | * Masking above should prevent us | |
606 | * ever trying to take action on a held | |
607 | * or ignored signal, unless process is traced. | |
608 | */ | |
609 | if ((p->p_flag&STRC) == 0) | |
610 | printf("issig\n"); | |
611 | continue; | |
612 | ||
613 | default: | |
614 | /* | |
615 | * This signal has an action, let | |
616 | * psig process it. | |
617 | */ | |
618 | goto send; | |
619 | } | |
620 | /*NOTREACHED*/ | |
621 | } | |
622 | /* | |
623 | * Didn't find a signal to send. | |
624 | */ | |
625 | p->p_cursig = 0; | |
626 | return (0); | |
627 | ||
628 | send: | |
629 | /* | |
630 | * Let psig process the signal. | |
631 | */ | |
632 | return (sig); | |
633 | } | |
634 | ||
687880f9 BJ |
635 | /* |
636 | * Put the argument process into the stopped | |
637 | * state and notify the parent via wakeup and/or signal. | |
638 | */ | |
639 | stop(p) | |
640 | register struct proc *p; | |
641 | { | |
642 | ||
643 | p->p_stat = SSTOP; | |
644 | p->p_flag &= ~SWTED; | |
645 | wakeup((caddr_t)p->p_pptr); | |
646 | /* | |
647 | * Avoid sending signal to parent if process is traced | |
648 | */ | |
649 | if (p->p_flag&STRC) | |
650 | return; | |
651 | psignal(p->p_pptr, SIGCHLD); | |
652 | } | |
653 | ||
654 | /* | |
655 | * Perform the action specified by | |
656 | * the current signal. | |
657 | * The usual sequence is: | |
658 | * if (issig()) | |
659 | * psig(); | |
660 | * The signal bit has already been cleared by issig, | |
661 | * and the current signal number stored in p->p_cursig. | |
662 | */ | |
663 | psig() | |
664 | { | |
dd012d1e SL |
665 | register struct proc *p = u.u_procp; |
666 | register int sig = p->p_cursig; | |
667 | int sigmask = 1 << (sig - 1), returnmask; | |
687880f9 BJ |
668 | register int (*action)(); |
669 | ||
dd012d1e | 670 | if (sig == 0) |
687880f9 | 671 | panic("psig"); |
dd012d1e | 672 | action = u.u_signal[sig]; |
687880f9 | 673 | if (action != SIG_DFL) { |
dd012d1e | 674 | if (action == SIG_IGN || (p->p_sigmask & sigmask)) |
687880f9 BJ |
675 | panic("psig action"); |
676 | u.u_error = 0; | |
687880f9 | 677 | /* |
dd012d1e SL |
678 | * Set the new mask value and also defer further |
679 | * occurences of this signal (unless we're simulating | |
680 | * the old signal facilities). | |
681 | * | |
682 | * Special case: user has done a sigpause. Here the | |
683 | * current mask is not of interest, but rather the | |
684 | * mask from before the sigpause is what we want restored | |
685 | * after the signal processing is completed. | |
687880f9 | 686 | */ |
dd012d1e SL |
687 | (void) spl6(); |
688 | if (p->p_flag & SOUSIG) { | |
689 | if (sig != SIGILL && sig != SIGTRAP) { | |
690 | u.u_signal[sig] = SIG_DFL; | |
691 | p->p_sigcatch &= ~sigmask; | |
692 | } | |
693 | sigmask = 0; | |
687880f9 | 694 | } |
dd012d1e SL |
695 | if (p->p_flag & SOMASK) { |
696 | returnmask = u.u_oldmask; | |
697 | p->p_flag &= ~SOMASK; | |
698 | } else | |
699 | returnmask = p->p_sigmask; | |
457aa395 | 700 | p->p_sigmask |= u.u_sigmask[sig] | sigmask; |
dd012d1e | 701 | (void) spl0(); |
1e3738da | 702 | u.u_ru.ru_nsignals++; |
dd012d1e SL |
703 | sendsig(action, sig, returnmask); |
704 | p->p_cursig = 0; | |
687880f9 BJ |
705 | return; |
706 | } | |
707 | u.u_acflag |= AXSIG; | |
dd012d1e | 708 | switch (sig) { |
687880f9 BJ |
709 | |
710 | case SIGILL: | |
711 | case SIGIOT: | |
712 | case SIGBUS: | |
713 | case SIGQUIT: | |
714 | case SIGTRAP: | |
715 | case SIGEMT: | |
716 | case SIGFPE: | |
717 | case SIGSEGV: | |
718 | case SIGSYS: | |
dd012d1e | 719 | u.u_arg[0] = sig; |
687880f9 | 720 | if (core()) |
dd012d1e | 721 | sig += 0200; |
687880f9 | 722 | } |
dd012d1e | 723 | exit(sig); |
687880f9 BJ |
724 | } |
725 | ||
687880f9 BJ |
726 | /* |
727 | * Create a core image on the file "core" | |
728 | * If you are looking for protection glitches, | |
729 | * there are probably a wealth of them here | |
730 | * when this occurs to a suid command. | |
731 | * | |
732 | * It writes UPAGES block of the | |
733 | * user.h area followed by the entire | |
734 | * data+stack segments. | |
735 | */ | |
736 | core() | |
737 | { | |
738 | register struct inode *ip; | |
739 | extern schar(); | |
740 | ||
be6bd5b8 | 741 | if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) |
7b0cb7cb | 742 | return (0); |
1e3738da BJ |
743 | if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= |
744 | u.u_rlimit[RLIMIT_CORE].rlim_cur) | |
687880f9 BJ |
745 | return (0); |
746 | u.u_error = 0; | |
747 | u.u_dirp = "core"; | |
4f083fd7 | 748 | ip = namei(schar, CREATE, 1); |
687880f9 BJ |
749 | if (ip == NULL) { |
750 | if (u.u_error) | |
751 | return (0); | |
be6bd5b8 | 752 | ip = maknode(0644); |
687880f9 BJ |
753 | if (ip==NULL) |
754 | return (0); | |
755 | } | |
7b0cb7cb BJ |
756 | if (access(ip, IWRITE) || |
757 | (ip->i_mode&IFMT) != IFREG || | |
758 | ip->i_nlink != 1) { | |
687880f9 | 759 | u.u_error = EFAULT; |
7b0cb7cb BJ |
760 | goto out; |
761 | } | |
4f083fd7 | 762 | itrunc(ip, (u_long)0); |
7b0cb7cb | 763 | u.u_acflag |= ACORE; |
dd012d1e SL |
764 | u.u_error = rdwri(UIO_WRITE, ip, |
765 | (caddr_t)&u, | |
766 | ctob(UPAGES), | |
767 | 0, 1, (int *)0); | |
1edb1cf8 | 768 | if (u.u_error == 0) |
a1edc12b | 769 | u.u_error = rdwri(UIO_WRITE, ip, |
e0fc9a90 BJ |
770 | (caddr_t)ctob(dptov(u.u_procp, 0)), |
771 | ctob(u.u_dsize), | |
a1edc12b | 772 | ctob(UPAGES), 0, (int *)0); |
1edb1cf8 | 773 | if (u.u_error == 0) |
a1edc12b | 774 | u.u_error = rdwri(UIO_WRITE, ip, |
e0fc9a90 BJ |
775 | (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), |
776 | ctob(u.u_ssize), | |
a1edc12b | 777 | ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0); |
7b0cb7cb | 778 | out: |
687880f9 | 779 | iput(ip); |
7b0cb7cb | 780 | return (u.u_error == 0); |
687880f9 | 781 | } |