1 /* $NetBSD: netbsd32_wait.c,v 1.1 2001/02/08 13:19:34 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/mount.h> 34 #include <sys/time.h> 35 #include <sys/wait.h> 36 #include <sys/ptrace.h> 37 #include <sys/resourcevar.h> 38 #include <sys/vnode.h> 39 #include <sys/pool.h> 40 #include <sys/proc.h> 41 42 #include <compat/netbsd32/netbsd32.h> 43 #include <compat/netbsd32/netbsd32_syscallargs.h> 44 #include <compat/netbsd32/netbsd32_conv.h> 45 46 int 47 netbsd32_wait4(q, v, retval) 48 struct proc *q; 49 void *v; 50 register_t *retval; 51 { 52 struct netbsd32_wait4_args /* { 53 syscallarg(int) pid; 54 syscallarg(netbsd32_intp) status; 55 syscallarg(int) options; 56 syscallarg(netbsd32_rusagep_t) rusage; 57 } */ *uap = v; 58 struct netbsd32_rusage ru32; 59 int nfound; 60 struct proc *p, *t; 61 int status, error; 62 63 if (SCARG(uap, pid) == 0) 64 SCARG(uap, pid) = -q->p_pgid; 65 if (SCARG(uap, options) &~ (WUNTRACED|WNOHANG)) 66 return (EINVAL); 67 68 loop: 69 nfound = 0; 70 for (p = q->p_children.lh_first; p != 0; p = p->p_sibling.le_next) { 71 if (SCARG(uap, pid) != WAIT_ANY && 72 p->p_pid != SCARG(uap, pid) && 73 p->p_pgid != -SCARG(uap, pid)) 74 continue; 75 nfound++; 76 if (p->p_stat == SZOMB) { 77 retval[0] = p->p_pid; 78 79 if (SCARG(uap, status)) { 80 status = p->p_xstat; /* convert to int */ 81 error = copyout((caddr_t)&status, 82 (caddr_t)(u_long)SCARG(uap, status), 83 sizeof(status)); 84 if (error) 85 return (error); 86 } 87 if (SCARG(uap, rusage)) { 88 netbsd32_from_rusage(p->p_ru, &ru32); 89 if ((error = copyout((caddr_t)&ru32, 90 (caddr_t)(u_long)SCARG(uap, rusage), 91 sizeof(struct netbsd32_rusage)))) 92 return (error); 93 } 94 /* 95 * If we got the child via ptrace(2) or procfs, and 96 * the parent is different (meaning the process was 97 * attached, rather than run as a child), then we need 98 * to give it back to the old parent, and send the 99 * parent a SIGCHLD. The rest of the cleanup will be 100 * done when the old parent waits on the child. 101 */ 102 if ((p->p_flag & P_TRACED) && 103 p->p_oppid != p->p_pptr->p_pid) { 104 t = pfind(p->p_oppid); 105 proc_reparent(p, t ? t : initproc); 106 p->p_oppid = 0; 107 p->p_flag &= ~(P_TRACED|P_WAITED|P_FSTRACE); 108 psignal(p->p_pptr, SIGCHLD); 109 wakeup((caddr_t)p->p_pptr); 110 return (0); 111 } 112 p->p_xstat = 0; 113 ruadd(&q->p_stats->p_cru, p->p_ru); 114 pool_put(&rusage_pool, p->p_ru); 115 116 /* 117 * Finally finished with old proc entry. 118 * Unlink it from its process group and free it. 119 */ 120 leavepgrp(p); 121 122 LIST_REMOVE(p, p_list); /* off zombproc */ 123 124 LIST_REMOVE(p, p_sibling); 125 126 /* 127 * Decrement the count of procs running with this uid. 128 */ 129 (void)chgproccnt(p->p_cred->p_ruid, -1); 130 131 /* 132 * Free up credentials. 133 */ 134 if (--p->p_cred->p_refcnt == 0) { 135 crfree(p->p_cred->pc_ucred); 136 pool_put(&pcred_pool, p->p_cred); 137 } 138 139 /* 140 * Release reference to text vnode 141 */ 142 if (p->p_textvp) 143 vrele(p->p_textvp); 144 145 pool_put(&proc_pool, p); 146 nprocs--; 147 return (0); 148 } 149 if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && 150 (p->p_flag & P_TRACED || SCARG(uap, options) & WUNTRACED)) { 151 p->p_flag |= P_WAITED; 152 retval[0] = p->p_pid; 153 154 if (SCARG(uap, status)) { 155 status = W_STOPCODE(p->p_xstat); 156 error = copyout((caddr_t)&status, 157 (caddr_t)(u_long)SCARG(uap, status), 158 sizeof(status)); 159 } else 160 error = 0; 161 return (error); 162 } 163 } 164 if (nfound == 0) 165 return (ECHILD); 166 if (SCARG(uap, options) & WNOHANG) { 167 retval[0] = 0; 168 return (0); 169 } 170 if ((error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) != 0) 171 return (error); 172 goto loop; 173 } 174 175 int 176 netbsd32_getrusage(p, v, retval) 177 struct proc *p; 178 void *v; 179 register_t *retval; 180 { 181 struct netbsd32_getrusage_args /* { 182 syscallarg(int) who; 183 syscallarg(netbsd32_rusagep_t) rusage; 184 } */ *uap = v; 185 struct rusage *rup; 186 struct netbsd32_rusage ru; 187 188 switch (SCARG(uap, who)) { 189 190 case RUSAGE_SELF: 191 rup = &p->p_stats->p_ru; 192 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); 193 break; 194 195 case RUSAGE_CHILDREN: 196 rup = &p->p_stats->p_cru; 197 break; 198 199 default: 200 return (EINVAL); 201 } 202 netbsd32_from_rusage(rup, &ru); 203 return (copyout(&ru, (caddr_t)(u_long)SCARG(uap, rusage), sizeof(ru))); 204 } 205