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