10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55891Sraf * Common Development and Distribution License (the "License").
65891Sraf * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
215891Sraf
220Sstevel@tonic-gate /*
235891Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */
280Sstevel@tonic-gate /* All Rights Reserved */
290Sstevel@tonic-gate
30*6812Sraf #pragma ident "%Z%%M% %I% %E% SMI"
31*6812Sraf
325891Sraf /*
33*6812Sraf * All of the wait*() functions are cancellation points.
345891Sraf */
35*6812Sraf #pragma weak _waitpid = waitpid
36*6812Sraf #pragma weak _wait = wait
370Sstevel@tonic-gate
38*6812Sraf #include "lint.h"
395891Sraf #include <unistd.h>
405891Sraf #include <string.h>
415891Sraf #include <errno.h>
425891Sraf #include <wait.h>
430Sstevel@tonic-gate #include <sys/types.h>
445891Sraf #include <sys/siginfo.h>
455891Sraf #include <sys/times.h>
465891Sraf #include <sys/resource.h>
475891Sraf
485891Sraf /*
495891Sraf * Convert the siginfo_t code and status fields to an old style wait status.
505891Sraf */
515891Sraf static int
wstat(int code,int status)525891Sraf wstat(int code, int status)
535891Sraf {
545891Sraf int stat = (status & 0377);
555891Sraf
565891Sraf switch (code) {
575891Sraf case CLD_EXITED:
585891Sraf stat <<= 8;
595891Sraf break;
605891Sraf case CLD_DUMPED:
615891Sraf stat |= WCOREFLG;
625891Sraf break;
635891Sraf case CLD_KILLED:
645891Sraf break;
655891Sraf case CLD_TRAPPED:
665891Sraf case CLD_STOPPED:
675891Sraf stat <<= 8;
685891Sraf stat |= WSTOPFLG;
695891Sraf break;
705891Sraf case CLD_CONTINUED:
715891Sraf stat = WCONTFLG;
725891Sraf break;
735891Sraf }
745891Sraf return (stat);
755891Sraf }
760Sstevel@tonic-gate
770Sstevel@tonic-gate pid_t
waitpid(pid_t pid,int * stat_loc,int options)785891Sraf waitpid(pid_t pid, int *stat_loc, int options)
790Sstevel@tonic-gate {
800Sstevel@tonic-gate idtype_t idtype;
810Sstevel@tonic-gate id_t id;
820Sstevel@tonic-gate siginfo_t info;
830Sstevel@tonic-gate int error;
840Sstevel@tonic-gate
850Sstevel@tonic-gate if (pid > 0) {
860Sstevel@tonic-gate idtype = P_PID;
870Sstevel@tonic-gate id = pid;
880Sstevel@tonic-gate } else if (pid < -1) {
890Sstevel@tonic-gate idtype = P_PGID;
900Sstevel@tonic-gate id = -pid;
910Sstevel@tonic-gate } else if (pid == -1) {
920Sstevel@tonic-gate idtype = P_ALL;
930Sstevel@tonic-gate id = 0;
940Sstevel@tonic-gate } else {
950Sstevel@tonic-gate idtype = P_PGID;
960Sstevel@tonic-gate id = getpgid(0);
970Sstevel@tonic-gate }
980Sstevel@tonic-gate
990Sstevel@tonic-gate options |= (WEXITED|WTRAPPED);
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate if ((error = waitid(idtype, id, &info, options)) < 0)
1020Sstevel@tonic-gate return (error);
1030Sstevel@tonic-gate
1045891Sraf if (stat_loc)
1055891Sraf *stat_loc = wstat(info.si_code, info.si_status);
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate return (info.si_pid);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate pid_t
wait(int * stat_loc)1115891Sraf wait(int *stat_loc)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate return (waitpid(-1, stat_loc, 0));
1140Sstevel@tonic-gate }
1155891Sraf
1165891Sraf pid_t
wait4(pid_t pid,int * stat_loc,int options,struct rusage * rp)1175891Sraf wait4(pid_t pid, int *stat_loc, int options, struct rusage *rp)
1185891Sraf {
1195891Sraf struct tms before_tms;
1205891Sraf struct tms after_tms;
1215891Sraf siginfo_t info;
1225891Sraf int error;
1235891Sraf int noptions;
1245891Sraf idtype_t idtype;
1255891Sraf
1265891Sraf if (rp)
1275891Sraf (void) memset(rp, 0, sizeof (struct rusage));
1285891Sraf (void) memset(&info, 0, sizeof (siginfo_t));
1295891Sraf
1305891Sraf if (times(&before_tms) == (clock_t)-1)
1315891Sraf return (-1); /* errno is set by times() */
1325891Sraf
1335891Sraf /*
1345891Sraf * SunOS's wait4() previously supported only WNOHANG &
1355891Sraf * WUNTRACED. XPG4v2 mandates that wait3() (which calls
1365891Sraf * wait4()) also support WCONTINUED.
1375891Sraf */
1385891Sraf if (options & ~(WNOHANG|WUNTRACED|WCONTINUED)) {
1395891Sraf errno = EINVAL;
1405891Sraf return (-1);
1415891Sraf }
1425891Sraf noptions = options | WEXITED | WTRAPPED;
1435891Sraf
1445891Sraf /*
1455891Sraf * Emulate undocumented 4.x semantics for 1186845
1465891Sraf */
1475891Sraf if (pid < 0) {
1485891Sraf pid = -pid;
1495891Sraf idtype = P_PGID;
1505891Sraf } else if (pid == 0) {
1515891Sraf idtype = P_ALL;
1525891Sraf } else {
1535891Sraf idtype = P_PID;
1545891Sraf }
1555891Sraf
1565891Sraf error = waitid(idtype, pid, &info, noptions);
1575891Sraf if (error == 0) {
1585891Sraf clock_t diffu; /* difference in usertime (ticks) */
1595891Sraf clock_t diffs; /* difference in systemtime (ticks) */
1605891Sraf clock_t hz;
1615891Sraf
1625891Sraf if ((options & WNOHANG) && info.si_pid == 0)
1635891Sraf return (0); /* no child found */
1645891Sraf
1655891Sraf if (rp) {
1665891Sraf if (times(&after_tms) == (clock_t)-1)
1675891Sraf return (-1); /* errno set by times() */
1685891Sraf /*
1695891Sraf * The system/user time is an approximation only !!!
1705891Sraf */
1715891Sraf diffu = after_tms.tms_cutime - before_tms.tms_cutime;
1725891Sraf diffs = after_tms.tms_cstime - before_tms.tms_cstime;
1735891Sraf hz = CLK_TCK;
1745891Sraf rp->ru_utime.tv_sec = diffu / hz;
1755891Sraf rp->ru_utime.tv_usec = (diffu % hz) * (1000000 / hz);
1765891Sraf rp->ru_stime.tv_sec = diffs / hz;
1775891Sraf rp->ru_stime.tv_usec = (diffs % hz) * (1000000 / hz);
1785891Sraf }
1795891Sraf if (stat_loc)
1805891Sraf *stat_loc = wstat(info.si_code, info.si_status);
1815891Sraf return (info.si_pid);
1825891Sraf } else {
1835891Sraf return (-1); /* error number is set by waitid() */
1845891Sraf }
1855891Sraf }
1865891Sraf
1875891Sraf pid_t
wait3(int * stat_loc,int options,struct rusage * rp)1885891Sraf wait3(int *stat_loc, int options, struct rusage *rp)
1895891Sraf {
1905891Sraf return (wait4(0, stat_loc, options, rp));
1915891Sraf }
192