1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1995-1997, by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 /* Portions Copyright(c) 1988, Sun Microsystems Inc. */ 32 /* All Rights Reserved */ 33 34 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ 35 36 /*LINTLIBRARY*/ 37 38 /* 39 * Compatibility lib for SunOS's wait4(). 40 */ 41 42 #include <sys/types.h> 43 #include <sys/time.h> 44 #include <sys/times.h> 45 #include <sys/wait.h> 46 #include <sys/siginfo.h> 47 #include <sys/procset.h> 48 #include <sys/param.h> 49 #include <sys/resource.h> 50 #include <unistd.h> 51 #include <string.h> 52 #include <errno.h> 53 54 /* 55 * Since sysV does not support rusage as in BSD, an approximate approach 56 * is: 57 * ... 58 * call times 59 * call waitid 60 * if ( a child is found ) 61 * call times again 62 * rusage ~= diff in the 2 times call 63 * ... 64 */ 65 66 /* 67 * forward declaration 68 */ 69 static int wstat(int, int); 70 71 pid_t 72 wait4(pid_t pid, int *status, int options, struct rusage *rp) 73 { 74 struct tms before_tms; 75 struct tms after_tms; 76 siginfo_t info; 77 int error; 78 int noptions; 79 idtype_t idtype; 80 81 if ((long)status == -1L || (long)rp == -1L) { 82 errno = EFAULT; 83 return (-1); 84 } 85 86 if (rp) 87 (void) memset(rp, 0, sizeof (struct rusage)); 88 (void) memset(&info, 0, sizeof (siginfo_t)); 89 if (times(&before_tms) < 0) 90 return (-1); /* errno is set by times() */ 91 92 /* 93 * SunOS's wait4() only supports WNOHANG & WUNTRACED 94 */ 95 if (options & ~(WNOHANG|WUNTRACED)) 96 return (EINVAL); /* used to be done by the kernel */ 97 noptions = options | WEXITED | WTRAPPED; 98 99 /* 100 * Emulate undocumented 4.x semantics for 1186845 101 */ 102 if (pid < 0) { 103 pid = -pid; 104 idtype = P_PGID; 105 } else if (pid == 0) 106 idtype = P_ALL; 107 else 108 idtype = P_PID; 109 110 error = waitid(idtype, pid, &info, noptions); 111 if (error == 0) { 112 clock_t diffu; /* difference in usertime (ticks) */ 113 clock_t diffs; /* difference in systemtime (ticks) */ 114 115 if ((options & WNOHANG) && (info.si_pid == 0)) 116 return (0); /* no child found */ 117 118 if (rp) { 119 if (times(&after_tms) < 0) 120 return (-1); /* errno set by times() */ 121 /* 122 * The system/user time is an approximation only !!! 123 */ 124 diffu = after_tms.tms_cutime - before_tms.tms_cutime; 125 diffs = after_tms.tms_cstime - before_tms.tms_cstime; 126 rp->ru_utime.tv_sec = diffu / HZ; 127 rp->ru_utime.tv_usec = (diffu % HZ) * (1000000 / HZ); 128 rp->ru_stime.tv_sec = diffs/ HZ; 129 rp->ru_stime.tv_usec = (diffs % HZ) * (1000000 / HZ); 130 } 131 if (status) 132 *status = wstat(info.si_code, info.si_status); 133 return (info.si_pid); 134 } else { 135 return (-1); /* error number is set by waitid() */ 136 } 137 } 138 139 /* 140 * Convert the status code to old style wait status 141 */ 142 static int 143 wstat(int code, int status) 144 { 145 int stat = (status & 0377); 146 147 switch (code) { 148 case CLD_EXITED: 149 stat <<= 8; 150 break; 151 case CLD_DUMPED: 152 stat |= WCOREFLG; 153 break; 154 case CLD_KILLED: 155 break; 156 case CLD_TRAPPED: 157 case CLD_STOPPED: 158 stat <<= 8; 159 stat |= WSTOPFLG; 160 break; 161 case CLD_CONTINUED: 162 stat = WCONTFLG; 163 break; 164 } 165 return (stat); 166 } 167