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
wstat(int code,int status)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
waitpid(pid_t pid,int * stat_loc,int options)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
wait(int * stat_loc)111a574db85Sraf wait(int *stat_loc)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate return (waitpid(-1, stat_loc, 0));
1147c478bd9Sstevel@tonic-gate }
115a574db85Sraf
116a574db85Sraf pid_t
wait4(pid_t pid,int * stat_loc,int options,struct rusage * rp)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
wait3(int * stat_loc,int options,struct rusage * rp)188a574db85Sraf wait3(int *stat_loc, int options, struct rusage *rp)
189a574db85Sraf {
190a574db85Sraf return (wait4(0, stat_loc, options, rp));
191a574db85Sraf }
192