xref: /onnv-gate/usr/src/lib/libc/port/gen/waitpid.c (revision 6812:febeba71273d)
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