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