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 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 /* 33 * All of the wait*() functions are cancellation points. 34 */ 35 #pragma weak _waitpid = waitpid 36 #pragma weak _wait = wait 37 38 #include "lint.h" 39 #include <unistd.h> 40 #include <string.h> 41 #include <errno.h> 42 #include <wait.h> 43 #include <sys/types.h> 44 #include <sys/siginfo.h> 45 #include <sys/times.h> 46 #include <sys/resource.h> 47 48 /* 49 * Convert the siginfo_t code and status fields to an old style wait status. 50 */ 51 static int 52 wstat(int code, int status) 53 { 54 int stat = (status & 0377); 55 56 switch (code) { 57 case CLD_EXITED: 58 stat <<= 8; 59 break; 60 case CLD_DUMPED: 61 stat |= WCOREFLG; 62 break; 63 case CLD_KILLED: 64 break; 65 case CLD_TRAPPED: 66 case CLD_STOPPED: 67 stat <<= 8; 68 stat |= WSTOPFLG; 69 break; 70 case CLD_CONTINUED: 71 stat = WCONTFLG; 72 break; 73 } 74 return (stat); 75 } 76 77 pid_t 78 waitpid(pid_t pid, int *stat_loc, int options) 79 { 80 idtype_t idtype; 81 id_t id; 82 siginfo_t info; 83 int error; 84 85 if (pid > 0) { 86 idtype = P_PID; 87 id = pid; 88 } else if (pid < -1) { 89 idtype = P_PGID; 90 id = -pid; 91 } else if (pid == -1) { 92 idtype = P_ALL; 93 id = 0; 94 } else { 95 idtype = P_PGID; 96 id = getpgid(0); 97 } 98 99 options |= (WEXITED|WTRAPPED); 100 101 if ((error = waitid(idtype, id, &info, options)) < 0) 102 return (error); 103 104 if (stat_loc) 105 *stat_loc = wstat(info.si_code, info.si_status); 106 107 return (info.si_pid); 108 } 109 110 pid_t 111 wait(int *stat_loc) 112 { 113 return (waitpid(-1, stat_loc, 0)); 114 } 115 116 pid_t 117 wait4(pid_t pid, int *stat_loc, int options, struct rusage *rp) 118 { 119 struct tms before_tms; 120 struct tms after_tms; 121 siginfo_t info; 122 int error; 123 int noptions; 124 idtype_t idtype; 125 126 if (rp) 127 (void) memset(rp, 0, sizeof (struct rusage)); 128 (void) memset(&info, 0, sizeof (siginfo_t)); 129 130 if (times(&before_tms) == (clock_t)-1) 131 return (-1); /* errno is set by times() */ 132 133 /* 134 * SunOS's wait4() previously supported only WNOHANG & 135 * WUNTRACED. XPG4v2 mandates that wait3() (which calls 136 * wait4()) also support WCONTINUED. 137 */ 138 if (options & ~(WNOHANG|WUNTRACED|WCONTINUED)) { 139 errno = EINVAL; 140 return (-1); 141 } 142 noptions = options | WEXITED | WTRAPPED; 143 144 /* 145 * Emulate undocumented 4.x semantics for 1186845 146 */ 147 if (pid < 0) { 148 pid = -pid; 149 idtype = P_PGID; 150 } else if (pid == 0) { 151 idtype = P_ALL; 152 } else { 153 idtype = P_PID; 154 } 155 156 error = waitid(idtype, pid, &info, noptions); 157 if (error == 0) { 158 clock_t diffu; /* difference in usertime (ticks) */ 159 clock_t diffs; /* difference in systemtime (ticks) */ 160 clock_t hz; 161 162 if ((options & WNOHANG) && info.si_pid == 0) 163 return (0); /* no child found */ 164 165 if (rp) { 166 if (times(&after_tms) == (clock_t)-1) 167 return (-1); /* errno set by times() */ 168 /* 169 * The system/user time is an approximation only !!! 170 */ 171 diffu = after_tms.tms_cutime - before_tms.tms_cutime; 172 diffs = after_tms.tms_cstime - before_tms.tms_cstime; 173 hz = CLK_TCK; 174 rp->ru_utime.tv_sec = diffu / hz; 175 rp->ru_utime.tv_usec = (diffu % hz) * (1000000 / hz); 176 rp->ru_stime.tv_sec = diffs / hz; 177 rp->ru_stime.tv_usec = (diffs % hz) * (1000000 / hz); 178 } 179 if (stat_loc) 180 *stat_loc = wstat(info.si_code, info.si_status); 181 return (info.si_pid); 182 } else { 183 return (-1); /* error number is set by waitid() */ 184 } 185 } 186 187 pid_t 188 wait3(int *stat_loc, int options, struct rusage *rp) 189 { 190 return (wait4(0, stat_loc, options, rp)); 191 } 192