* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)kern_exit.c 7.10 (Berkeley) %G%
* Exit system call: pass back caller's arg
uap
= (struct a
*)u
.u_ap
;
exit(W_EXITCODE(uap
->rval
, 0));
* Save u. area for parent to look at.
* Wake up parent and init processes,
* and dispose of children.
register struct proc
*p
, *q
, *nq
;
MALLOC(p
->p_ru
, struct rusage
*, sizeof(struct rusage
),
p
->p_flag
&= ~(STRC
|SULOCK
);
for (i
= 0; i
< NSIG
; i
++)
untimeout(realitexpire
, (caddr_t
)p
);
* Release virtual memory. If we resulted from
* a vfork(), instead give the resources back to
if ((p
->p_flag
& SVFORK
) == 0)
while ((p
->p_flag
& SVFDONE
) == 0)
sleep((caddr_t
)p
, PZERO
- 1);
for (i
= 0; i
<= u
.u_lastfile
; i
++) {
p
->p_session
->s_leader
= 0;
u
.u_rlimit
[RLIMIT_FSIZE
].rlim_cur
= RLIM_INFINITY
;
* Freeing the user structure and kernel stack
* for the current process: have to run a bit longer
* using the pages which are about to be freed...
* vrelu will block memory allocation by raising ipl.
if (*p
->p_prev
= p
->p_nxt
) /* off allproc queue */
p
->p_nxt
->p_prev
= p
->p_prev
;
if (p
->p_nxt
= zombproc
) /* onto zombproc */
p
->p_nxt
->p_prev
= &p
->p_nxt
;
pidhash
[i
] = p
->p_idhash
;
for (i
= pidhash
[i
]; i
!= 0; i
= proc
[i
].p_idhash
)
if (proc
[i
].p_idhash
== x
) {
proc
[i
].p_idhash
= p
->p_idhash
;
printf("Can't exec init (errno %d)\n", WEXITSTATUS(rv
));
ruadd(p
->p_ru
, &u
.u_cru
);
if (p
->p_cptr
) /* only need this if any child is S_ZOMB */
wakeup((caddr_t
)&proc
[1]);
for (q
= p
->p_cptr
; q
!= NULL
; q
= nq
) {
proc
[1].p_cptr
->p_ysptr
= q
;
q
->p_osptr
= proc
[1].p_cptr
;
* Traced processes are killed
* since their existence means someone is screwing up.
* Stopped processes are sent a hangup and a continue.
* This is designed to be ``safe'' for setuid
* processes since they must be willing to tolerate
} else if (q
->p_stat
== SSTOP
) {
* Protect this process from future
* tty signals, clear TSTP/TTIN/TTOU if pending.
psignal(p
->p_pptr
, SIGCHLD
);
wakeup((caddr_t
)p
->p_pptr
);
dkeyrelease(p
->p_dkey
), p
->p_dkey
= 0;
ckeyrelease(p
->p_ckey
), p
->p_ckey
= 0;
u
.u_pcb
.pcb_savacc
.faddr
= (float *)NULL
;
} *uap
= (struct a
*)u
.u_ap
;
if ((u
.u_ar0
[PS
] & PSL_ALLCC
) != PSL_ALLCC
) {
uap
->options
= u
.u_ar0
[R0
];
uap
->rusage
= (struct rusage
*)u
.u_ar0
[R1
];
} *uap
= (struct a
*)u
.u_ap
;
* Search for a terminated (zombie) child,
* finally lay it to rest, and collect its status.
* Look also for stopped (traced) children,
* and pass back status from them.
} *uap
= (struct a
*)u
.u_ap
;
register struct proc
*p
, *q
;
if (uap
->options
&~ (WUNTRACED
|WNOHANG
))
for (p
= q
->p_cptr
; p
; p
= p
->p_osptr
) {
if (uap
->pid
!= WAIT_ANY
&&
p
->p_pid
!= uap
->pid
&& p
->p_pgid
!= -uap
->pid
)
if (p
->p_stat
== SZOMB
) {
u
.u_r
.r_val2
= p
->p_xstat
;
status
= p
->p_xstat
; /* convert to int */
if (error
= copyout((caddr_t
)&status
,
(caddr_t
)uap
->status
, sizeof(status
)))
if (uap
->rusage
&& (error
= copyout((caddr_t
)p
->p_ru
,
(caddr_t
)uap
->rusage
, sizeof (struct rusage
))))
ruadd(&u
.u_cru
, p
->p_ru
);
if (*p
->p_prev
= p
->p_nxt
) /* off zombproc */
p
->p_nxt
->p_prev
= p
->p_prev
;
p
->p_nxt
= freeproc
; /* onto freeproc */
if ((q
= p
->p_pptr
)->p_cptr
== p
)
if (p
->p_stat
== SSTOP
&& (p
->p_flag
& SWTED
) == 0 &&
(p
->p_flag
& STRC
|| uap
->options
& WUNTRACED
)) {
u
.u_r
.r_val2
= W_STOPCODE(p
->p_cursig
);
status
= W_STOPCODE(p
->p_cursig
);
error
= copyout((caddr_t
)&status
,
(caddr_t
)uap
->status
, sizeof(status
));
if (uap
->options
& WNOHANG
) {
if (setjmp(&u
.u_qsave
)) {
if ((u
.u_sigintr
& sigmask(p
->p_cursig
)) != 0)
sleep((caddr_t
)u
.u_procp
, PWAIT
);