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