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 /*LINTLIBRARY*/ 35 36 /* 37 * Compatibility lib for SunOS's wait4(). 38 */ 39 40 #include <sys/types.h> 41 #include <sys/time.h> 42 #include <sys/times.h> 43 #include <sys/wait.h> 44 #include <sys/siginfo.h> 45 #include <sys/procset.h> 46 #include <sys/param.h> 47 #include <sys/resource.h> 48 #include <unistd.h> 49 #include <string.h> 50 #include <errno.h> 51 52 /* 53 * Since sysV does not support rusage as in BSD, an approximate approach 54 * is: 55 * ... 56 * call times 57 * call waitid 58 * if ( a child is found ) 59 * call times again 60 * rusage ~= diff in the 2 times call 61 * ... 62 */ 63 64 /* 65 * forward declaration 66 */ 67 static int wstat(int, int); 68 69 pid_t 70 wait4(pid_t pid, int *status, int options, struct rusage *rp) 71 { 72 struct tms before_tms; 73 struct tms after_tms; 74 siginfo_t info; 75 int error; 76 int noptions; 77 idtype_t idtype; 78 79 if ((long)status == -1L || (long)rp == -1L) { 80 errno = EFAULT; 81 return (-1); 82 } 83 84 if (rp) 85 (void) memset(rp, 0, sizeof (struct rusage)); 86 (void) memset(&info, 0, sizeof (siginfo_t)); 87 if (times(&before_tms) < 0) 88 return (-1); /* errno is set by times() */ 89 90 /* 91 * SunOS's wait4() only supports WNOHANG & WUNTRACED 92 */ 93 if (options & ~(WNOHANG|WUNTRACED)) 94 return (EINVAL); /* used to be done by the kernel */ 95 noptions = options | WEXITED | WTRAPPED; 96 97 /* 98 * Emulate undocumented 4.x semantics for 1186845 99 */ 100 if (pid < 0) { 101 pid = -pid; 102 idtype = P_PGID; 103 } else if (pid == 0) 104 idtype = P_ALL; 105 else 106 idtype = P_PID; 107 108 error = waitid(idtype, pid, &info, noptions); 109 if (error == 0) { 110 clock_t diffu; /* difference in usertime (ticks) */ 111 clock_t diffs; /* difference in systemtime (ticks) */ 112 113 if ((options & WNOHANG) && (info.si_pid == 0)) 114 return (0); /* no child found */ 115 116 if (rp) { 117 if (times(&after_tms) < 0) 118 return (-1); /* errno set by times() */ 119 /* 120 * The system/user time is an approximation only !!! 121 */ 122 diffu = after_tms.tms_cutime - before_tms.tms_cutime; 123 diffs = after_tms.tms_cstime - before_tms.tms_cstime; 124 rp->ru_utime.tv_sec = diffu / HZ; 125 rp->ru_utime.tv_usec = (diffu % HZ) * (1000000 / HZ); 126 rp->ru_stime.tv_sec = diffs/ HZ; 127 rp->ru_stime.tv_usec = (diffs % HZ) * (1000000 / HZ); 128 } 129 if (status) 130 *status = wstat(info.si_code, info.si_status); 131 return (info.si_pid); 132 } else { 133 return (-1); /* error number is set by waitid() */ 134 } 135 } 136 137 /* 138 * Convert the status code to old style wait status 139 */ 140 static int 141 wstat(int code, int status) 142 { 143 int stat = (status & 0377); 144 145 switch (code) { 146 case CLD_EXITED: 147 stat <<= 8; 148 break; 149 case CLD_DUMPED: 150 stat |= WCOREFLG; 151 break; 152 case CLD_KILLED: 153 break; 154 case CLD_TRAPPED: 155 case CLD_STOPPED: 156 stat <<= 8; 157 stat |= WSTOPFLG; 158 break; 159 case CLD_CONTINUED: 160 stat = WCONTFLG; 161 break; 162 } 163 return (stat); 164 } 165