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