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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* Copyright (c) 1988 AT&T */ 30 /* All Rights Reserved */ 31 32 /* 33 * All of these functions are cancellation points. 34 */ 35 #pragma weak waitpid = _waitpid 36 #pragma weak wait = _wait 37 #pragma weak wait4 = _wait4 38 #pragma weak wait3 = _wait3 39 40 #include "synonyms.h" 41 #include <unistd.h> 42 #include <string.h> 43 #include <errno.h> 44 #include <wait.h> 45 #include <sys/types.h> 46 #include <sys/siginfo.h> 47 #include <sys/times.h> 48 #include <sys/resource.h> 49 50 /* 51 * Convert the siginfo_t code and status fields to an old style wait status. 52 */ 53 static int 54 wstat(int code, int status) 55 { 56 int stat = (status & 0377); 57 58 switch (code) { 59 case CLD_EXITED: 60 stat <<= 8; 61 break; 62 case CLD_DUMPED: 63 stat |= WCOREFLG; 64 break; 65 case CLD_KILLED: 66 break; 67 case CLD_TRAPPED: 68 case CLD_STOPPED: 69 stat <<= 8; 70 stat |= WSTOPFLG; 71 break; 72 case CLD_CONTINUED: 73 stat = WCONTFLG; 74 break; 75 } 76 return (stat); 77 } 78 79 pid_t 80 waitpid(pid_t pid, int *stat_loc, int options) 81 { 82 idtype_t idtype; 83 id_t id; 84 siginfo_t info; 85 int error; 86 87 if (pid > 0) { 88 idtype = P_PID; 89 id = pid; 90 } else if (pid < -1) { 91 idtype = P_PGID; 92 id = -pid; 93 } else if (pid == -1) { 94 idtype = P_ALL; 95 id = 0; 96 } else { 97 idtype = P_PGID; 98 id = getpgid(0); 99 } 100 101 options |= (WEXITED|WTRAPPED); 102 103 if ((error = waitid(idtype, id, &info, options)) < 0) 104 return (error); 105 106 if (stat_loc) 107 *stat_loc = wstat(info.si_code, info.si_status); 108 109 return (info.si_pid); 110 } 111 112 pid_t 113 wait(int *stat_loc) 114 { 115 return (waitpid(-1, stat_loc, 0)); 116 } 117 118 pid_t 119 wait4(pid_t pid, int *stat_loc, int options, struct rusage *rp) 120 { 121 struct tms before_tms; 122 struct tms after_tms; 123 siginfo_t info; 124 int error; 125 int noptions; 126 idtype_t idtype; 127 128 if (rp) 129 (void) memset(rp, 0, sizeof (struct rusage)); 130 (void) memset(&info, 0, sizeof (siginfo_t)); 131 132 if (times(&before_tms) == (clock_t)-1) 133 return (-1); /* errno is set by times() */ 134 135 /* 136 * SunOS's wait4() previously supported only WNOHANG & 137 * WUNTRACED. XPG4v2 mandates that wait3() (which calls 138 * wait4()) also support WCONTINUED. 139 */ 140 if (options & ~(WNOHANG|WUNTRACED|WCONTINUED)) { 141 errno = EINVAL; 142 return (-1); 143 } 144 noptions = options | WEXITED | WTRAPPED; 145 146 /* 147 * Emulate undocumented 4.x semantics for 1186845 148 */ 149 if (pid < 0) { 150 pid = -pid; 151 idtype = P_PGID; 152 } else if (pid == 0) { 153 idtype = P_ALL; 154 } else { 155 idtype = P_PID; 156 } 157 158 error = waitid(idtype, pid, &info, noptions); 159 if (error == 0) { 160 clock_t diffu; /* difference in usertime (ticks) */ 161 clock_t diffs; /* difference in systemtime (ticks) */ 162 clock_t hz; 163 164 if ((options & WNOHANG) && info.si_pid == 0) 165 return (0); /* no child found */ 166 167 if (rp) { 168 if (times(&after_tms) == (clock_t)-1) 169 return (-1); /* errno set by times() */ 170 /* 171 * The system/user time is an approximation only !!! 172 */ 173 diffu = after_tms.tms_cutime - before_tms.tms_cutime; 174 diffs = after_tms.tms_cstime - before_tms.tms_cstime; 175 hz = CLK_TCK; 176 rp->ru_utime.tv_sec = diffu / hz; 177 rp->ru_utime.tv_usec = (diffu % hz) * (1000000 / hz); 178 rp->ru_stime.tv_sec = diffs / hz; 179 rp->ru_stime.tv_usec = (diffs % hz) * (1000000 / hz); 180 } 181 if (stat_loc) 182 *stat_loc = wstat(info.si_code, info.si_status); 183 return (info.si_pid); 184 } else { 185 return (-1); /* error number is set by waitid() */ 186 } 187 } 188 189 pid_t 190 wait3(int *stat_loc, int options, struct rusage *rp) 191 { 192 return (wait4(0, stat_loc, options, rp)); 193 } 194