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
30a574db85Sraf /*
31*7257d1b4Sraf * All of the wait*() functions are cancellation points.
32a574db85Sraf */
33*7257d1b4Sraf #pragma weak _waitpid = waitpid
34*7257d1b4Sraf #pragma weak _wait = wait
357c478bd9Sstevel@tonic-gate
36*7257d1b4Sraf #include "lint.h"
377c478bd9Sstevel@tonic-gate #include <unistd.h>
38a574db85Sraf #include <string.h>
39a574db85Sraf #include <errno.h>
407c478bd9Sstevel@tonic-gate #include <wait.h>
41a574db85Sraf #include <sys/types.h>
42a574db85Sraf #include <sys/siginfo.h>
43a574db85Sraf #include <sys/times.h>
44a574db85Sraf #include <sys/resource.h>
45a574db85Sraf
46a574db85Sraf /*
47a574db85Sraf * Convert the siginfo_t code and status fields to an old style wait status.
48a574db85Sraf */
49a574db85Sraf static int
wstat(int code,int status)50a574db85Sraf wstat(int code, int status)
51a574db85Sraf {
52a574db85Sraf int stat = (status & 0377);
53a574db85Sraf
54a574db85Sraf switch (code) {
55a574db85Sraf case CLD_EXITED:
56a574db85Sraf stat <<= 8;
57a574db85Sraf break;
58a574db85Sraf case CLD_DUMPED:
59a574db85Sraf stat |= WCOREFLG;
60a574db85Sraf break;
61a574db85Sraf case CLD_KILLED:
62a574db85Sraf break;
63a574db85Sraf case CLD_TRAPPED:
64a574db85Sraf case CLD_STOPPED:
65a574db85Sraf stat <<= 8;
66a574db85Sraf stat |= WSTOPFLG;
67a574db85Sraf break;
68a574db85Sraf case CLD_CONTINUED:
69a574db85Sraf stat = WCONTFLG;
70a574db85Sraf break;
71a574db85Sraf }
72a574db85Sraf return (stat);
73a574db85Sraf }
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate pid_t
waitpid(pid_t pid,int * stat_loc,int options)76a574db85Sraf waitpid(pid_t pid, int *stat_loc, int options)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate idtype_t idtype;
797c478bd9Sstevel@tonic-gate id_t id;
807c478bd9Sstevel@tonic-gate siginfo_t info;
817c478bd9Sstevel@tonic-gate int error;
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate if (pid > 0) {
847c478bd9Sstevel@tonic-gate idtype = P_PID;
857c478bd9Sstevel@tonic-gate id = pid;
867c478bd9Sstevel@tonic-gate } else if (pid < -1) {
877c478bd9Sstevel@tonic-gate idtype = P_PGID;
887c478bd9Sstevel@tonic-gate id = -pid;
897c478bd9Sstevel@tonic-gate } else if (pid == -1) {
907c478bd9Sstevel@tonic-gate idtype = P_ALL;
917c478bd9Sstevel@tonic-gate id = 0;
927c478bd9Sstevel@tonic-gate } else {
937c478bd9Sstevel@tonic-gate idtype = P_PGID;
947c478bd9Sstevel@tonic-gate id = getpgid(0);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate options |= (WEXITED|WTRAPPED);
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate if ((error = waitid(idtype, id, &info, options)) < 0)
1007c478bd9Sstevel@tonic-gate return (error);
1017c478bd9Sstevel@tonic-gate
102a574db85Sraf if (stat_loc)
103a574db85Sraf *stat_loc = wstat(info.si_code, info.si_status);
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate return (info.si_pid);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate pid_t
wait(int * stat_loc)109a574db85Sraf wait(int *stat_loc)
1107c478bd9Sstevel@tonic-gate {
1117c478bd9Sstevel@tonic-gate return (waitpid(-1, stat_loc, 0));
1127c478bd9Sstevel@tonic-gate }
113a574db85Sraf
114a574db85Sraf pid_t
wait4(pid_t pid,int * stat_loc,int options,struct rusage * rp)115a574db85Sraf wait4(pid_t pid, int *stat_loc, int options, struct rusage *rp)
116a574db85Sraf {
117a574db85Sraf struct tms before_tms;
118a574db85Sraf struct tms after_tms;
119a574db85Sraf siginfo_t info;
120a574db85Sraf int error;
121a574db85Sraf int noptions;
122a574db85Sraf idtype_t idtype;
123a574db85Sraf
124a574db85Sraf if (rp)
125a574db85Sraf (void) memset(rp, 0, sizeof (struct rusage));
126a574db85Sraf (void) memset(&info, 0, sizeof (siginfo_t));
127a574db85Sraf
128a574db85Sraf if (times(&before_tms) == (clock_t)-1)
129a574db85Sraf return (-1); /* errno is set by times() */
130a574db85Sraf
131a574db85Sraf /*
132a574db85Sraf * SunOS's wait4() previously supported only WNOHANG &
133a574db85Sraf * WUNTRACED. XPG4v2 mandates that wait3() (which calls
134a574db85Sraf * wait4()) also support WCONTINUED.
135a574db85Sraf */
136a574db85Sraf if (options & ~(WNOHANG|WUNTRACED|WCONTINUED)) {
137a574db85Sraf errno = EINVAL;
138a574db85Sraf return (-1);
139a574db85Sraf }
140a574db85Sraf noptions = options | WEXITED | WTRAPPED;
141a574db85Sraf
142a574db85Sraf /*
143a574db85Sraf * Emulate undocumented 4.x semantics for 1186845
144a574db85Sraf */
145a574db85Sraf if (pid < 0) {
146a574db85Sraf pid = -pid;
147a574db85Sraf idtype = P_PGID;
148a574db85Sraf } else if (pid == 0) {
149a574db85Sraf idtype = P_ALL;
150a574db85Sraf } else {
151a574db85Sraf idtype = P_PID;
152a574db85Sraf }
153a574db85Sraf
154a574db85Sraf error = waitid(idtype, pid, &info, noptions);
155a574db85Sraf if (error == 0) {
156a574db85Sraf clock_t diffu; /* difference in usertime (ticks) */
157a574db85Sraf clock_t diffs; /* difference in systemtime (ticks) */
158a574db85Sraf clock_t hz;
159a574db85Sraf
160a574db85Sraf if ((options & WNOHANG) && info.si_pid == 0)
161a574db85Sraf return (0); /* no child found */
162a574db85Sraf
163a574db85Sraf if (rp) {
164a574db85Sraf if (times(&after_tms) == (clock_t)-1)
165a574db85Sraf return (-1); /* errno set by times() */
166a574db85Sraf /*
167a574db85Sraf * The system/user time is an approximation only !!!
168a574db85Sraf */
169a574db85Sraf diffu = after_tms.tms_cutime - before_tms.tms_cutime;
170a574db85Sraf diffs = after_tms.tms_cstime - before_tms.tms_cstime;
171a574db85Sraf hz = CLK_TCK;
172a574db85Sraf rp->ru_utime.tv_sec = diffu / hz;
173a574db85Sraf rp->ru_utime.tv_usec = (diffu % hz) * (1000000 / hz);
174a574db85Sraf rp->ru_stime.tv_sec = diffs / hz;
175a574db85Sraf rp->ru_stime.tv_usec = (diffs % hz) * (1000000 / hz);
176a574db85Sraf }
177a574db85Sraf if (stat_loc)
178a574db85Sraf *stat_loc = wstat(info.si_code, info.si_status);
179a574db85Sraf return (info.si_pid);
180a574db85Sraf } else {
181a574db85Sraf return (-1); /* error number is set by waitid() */
182a574db85Sraf }
183a574db85Sraf }
184a574db85Sraf
185a574db85Sraf pid_t
wait3(int * stat_loc,int options,struct rusage * rp)186a574db85Sraf wait3(int *stat_loc, int options, struct rusage *rp)
187a574db85Sraf {
188a574db85Sraf return (wait4(0, stat_loc, options, rp));
189a574db85Sraf }
190