17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5a574db85Sraf * Common Development and Distribution License (the "License"). 6a574db85Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21a574db85Sraf 227c478bd9Sstevel@tonic-gate /* 23a574db85Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 30*7257d1b4Sraf #pragma ident "%Z%%M% %I% %E% SMI" 317c478bd9Sstevel@tonic-gate 32*7257d1b4Sraf /* 33*7257d1b4Sraf * All of the wait*() functions are cancellation points. 34*7257d1b4Sraf */ 35*7257d1b4Sraf #pragma weak _waitpid = waitpid 36*7257d1b4Sraf #pragma weak _wait = wait 37*7257d1b4Sraf 38*7257d1b4Sraf #include "lint.h" 397c478bd9Sstevel@tonic-gate #include <unistd.h> 40a574db85Sraf #include <string.h> 41a574db85Sraf #include <errno.h> 427c478bd9Sstevel@tonic-gate #include <wait.h> 43a574db85Sraf #include <sys/types.h> 44a574db85Sraf #include <sys/siginfo.h> 45a574db85Sraf #include <sys/times.h> 46a574db85Sraf #include <sys/resource.h> 47a574db85Sraf 48a574db85Sraf /* 49a574db85Sraf * Convert the siginfo_t code and status fields to an old style wait status. 50a574db85Sraf */ 51a574db85Sraf static int 52a574db85Sraf wstat(int code, int status) 53a574db85Sraf { 54a574db85Sraf int stat = (status & 0377); 55a574db85Sraf 56a574db85Sraf switch (code) { 57a574db85Sraf case CLD_EXITED: 58a574db85Sraf stat <<= 8; 59a574db85Sraf break; 60a574db85Sraf case CLD_DUMPED: 61a574db85Sraf stat |= WCOREFLG; 62a574db85Sraf break; 63a574db85Sraf case CLD_KILLED: 64a574db85Sraf break; 65a574db85Sraf case CLD_TRAPPED: 66a574db85Sraf case CLD_STOPPED: 67a574db85Sraf stat <<= 8; 68a574db85Sraf stat |= WSTOPFLG; 69a574db85Sraf break; 70a574db85Sraf case CLD_CONTINUED: 71a574db85Sraf stat = WCONTFLG; 72a574db85Sraf break; 73a574db85Sraf } 74a574db85Sraf return (stat); 75a574db85Sraf } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate pid_t 78a574db85Sraf waitpid(pid_t pid, int *stat_loc, int options) 797c478bd9Sstevel@tonic-gate { 807c478bd9Sstevel@tonic-gate idtype_t idtype; 817c478bd9Sstevel@tonic-gate id_t id; 827c478bd9Sstevel@tonic-gate siginfo_t info; 837c478bd9Sstevel@tonic-gate int error; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate if (pid > 0) { 867c478bd9Sstevel@tonic-gate idtype = P_PID; 877c478bd9Sstevel@tonic-gate id = pid; 887c478bd9Sstevel@tonic-gate } else if (pid < -1) { 897c478bd9Sstevel@tonic-gate idtype = P_PGID; 907c478bd9Sstevel@tonic-gate id = -pid; 917c478bd9Sstevel@tonic-gate } else if (pid == -1) { 927c478bd9Sstevel@tonic-gate idtype = P_ALL; 937c478bd9Sstevel@tonic-gate id = 0; 947c478bd9Sstevel@tonic-gate } else { 957c478bd9Sstevel@tonic-gate idtype = P_PGID; 967c478bd9Sstevel@tonic-gate id = getpgid(0); 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate options |= (WEXITED|WTRAPPED); 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate if ((error = waitid(idtype, id, &info, options)) < 0) 1027c478bd9Sstevel@tonic-gate return (error); 1037c478bd9Sstevel@tonic-gate 104a574db85Sraf if (stat_loc) 105a574db85Sraf *stat_loc = wstat(info.si_code, info.si_status); 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate return (info.si_pid); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate pid_t 111a574db85Sraf wait(int *stat_loc) 1127c478bd9Sstevel@tonic-gate { 1137c478bd9Sstevel@tonic-gate return (waitpid(-1, stat_loc, 0)); 1147c478bd9Sstevel@tonic-gate } 115a574db85Sraf 116a574db85Sraf pid_t 117a574db85Sraf wait4(pid_t pid, int *stat_loc, int options, struct rusage *rp) 118a574db85Sraf { 119a574db85Sraf struct tms before_tms; 120a574db85Sraf struct tms after_tms; 121a574db85Sraf siginfo_t info; 122a574db85Sraf int error; 123a574db85Sraf int noptions; 124a574db85Sraf idtype_t idtype; 125a574db85Sraf 126a574db85Sraf if (rp) 127a574db85Sraf (void) memset(rp, 0, sizeof (struct rusage)); 128a574db85Sraf (void) memset(&info, 0, sizeof (siginfo_t)); 129a574db85Sraf 130a574db85Sraf if (times(&before_tms) == (clock_t)-1) 131a574db85Sraf return (-1); /* errno is set by times() */ 132a574db85Sraf 133a574db85Sraf /* 134a574db85Sraf * SunOS's wait4() previously supported only WNOHANG & 135a574db85Sraf * WUNTRACED. XPG4v2 mandates that wait3() (which calls 136a574db85Sraf * wait4()) also support WCONTINUED. 137a574db85Sraf */ 138a574db85Sraf if (options & ~(WNOHANG|WUNTRACED|WCONTINUED)) { 139a574db85Sraf errno = EINVAL; 140a574db85Sraf return (-1); 141a574db85Sraf } 142a574db85Sraf noptions = options | WEXITED | WTRAPPED; 143a574db85Sraf 144a574db85Sraf /* 145a574db85Sraf * Emulate undocumented 4.x semantics for 1186845 146a574db85Sraf */ 147a574db85Sraf if (pid < 0) { 148a574db85Sraf pid = -pid; 149a574db85Sraf idtype = P_PGID; 150a574db85Sraf } else if (pid == 0) { 151a574db85Sraf idtype = P_ALL; 152a574db85Sraf } else { 153a574db85Sraf idtype = P_PID; 154a574db85Sraf } 155a574db85Sraf 156a574db85Sraf error = waitid(idtype, pid, &info, noptions); 157a574db85Sraf if (error == 0) { 158a574db85Sraf clock_t diffu; /* difference in usertime (ticks) */ 159a574db85Sraf clock_t diffs; /* difference in systemtime (ticks) */ 160a574db85Sraf clock_t hz; 161a574db85Sraf 162a574db85Sraf if ((options & WNOHANG) && info.si_pid == 0) 163a574db85Sraf return (0); /* no child found */ 164a574db85Sraf 165a574db85Sraf if (rp) { 166a574db85Sraf if (times(&after_tms) == (clock_t)-1) 167a574db85Sraf return (-1); /* errno set by times() */ 168a574db85Sraf /* 169a574db85Sraf * The system/user time is an approximation only !!! 170a574db85Sraf */ 171a574db85Sraf diffu = after_tms.tms_cutime - before_tms.tms_cutime; 172a574db85Sraf diffs = after_tms.tms_cstime - before_tms.tms_cstime; 173a574db85Sraf hz = CLK_TCK; 174a574db85Sraf rp->ru_utime.tv_sec = diffu / hz; 175a574db85Sraf rp->ru_utime.tv_usec = (diffu % hz) * (1000000 / hz); 176a574db85Sraf rp->ru_stime.tv_sec = diffs / hz; 177a574db85Sraf rp->ru_stime.tv_usec = (diffs % hz) * (1000000 / hz); 178a574db85Sraf } 179a574db85Sraf if (stat_loc) 180a574db85Sraf *stat_loc = wstat(info.si_code, info.si_status); 181a574db85Sraf return (info.si_pid); 182a574db85Sraf } else { 183a574db85Sraf return (-1); /* error number is set by waitid() */ 184a574db85Sraf } 185a574db85Sraf } 186a574db85Sraf 187a574db85Sraf pid_t 188a574db85Sraf wait3(int *stat_loc, int options, struct rusage *rp) 189a574db85Sraf { 190a574db85Sraf return (wait4(0, stat_loc, options, rp)); 191a574db85Sraf } 192