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