xref: /illumos-gate/usr/src/lib/libc/port/gen/waitpid.c (revision 7257d1b4)
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"
31*7257d1b4Sraf 
32a574db85Sraf /*
33*7257d1b4Sraf  * All of the wait*() functions are cancellation points.
34a574db85Sraf  */
35*7257d1b4Sraf #pragma weak _waitpid = waitpid
36*7257d1b4Sraf #pragma weak _wait = wait
377c478bd9Sstevel@tonic-gate 
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