8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libc / port / gen / waitpid.c
blob8f67f2dd40a646297cbd8a00d4ab57cff3bcb7ef
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
33 * All of the wait*() functions are cancellation points.
35 #pragma weak _waitpid = waitpid
36 #pragma weak _wait = wait
38 #include "lint.h"
39 #include <unistd.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <wait.h>
43 #include <sys/types.h>
44 #include <sys/siginfo.h>
45 #include <sys/times.h>
46 #include <sys/resource.h>
49 * Convert the siginfo_t code and status fields to an old style wait status.
51 static int
52 wstat(int code, int status)
54 int stat = (status & 0377);
56 switch (code) {
57 case CLD_EXITED:
58 stat <<= 8;
59 break;
60 case CLD_DUMPED:
61 stat |= WCOREFLG;
62 break;
63 case CLD_KILLED:
64 break;
65 case CLD_TRAPPED:
66 case CLD_STOPPED:
67 stat <<= 8;
68 stat |= WSTOPFLG;
69 break;
70 case CLD_CONTINUED:
71 stat = WCONTFLG;
72 break;
74 return (stat);
77 pid_t
78 waitpid(pid_t pid, int *stat_loc, int options)
80 idtype_t idtype;
81 id_t id;
82 siginfo_t info;
83 int error;
85 if (pid > 0) {
86 idtype = P_PID;
87 id = pid;
88 } else if (pid < -1) {
89 idtype = P_PGID;
90 id = -pid;
91 } else if (pid == -1) {
92 idtype = P_ALL;
93 id = 0;
94 } else {
95 idtype = P_PGID;
96 id = getpgid(0);
99 options |= (WEXITED|WTRAPPED);
101 if ((error = waitid(idtype, id, &info, options)) < 0)
102 return (error);
104 if (stat_loc)
105 *stat_loc = wstat(info.si_code, info.si_status);
107 return (info.si_pid);
110 pid_t
111 wait(int *stat_loc)
113 return (waitpid(-1, stat_loc, 0));
116 pid_t
117 wait4(pid_t pid, int *stat_loc, int options, struct rusage *rp)
119 struct tms before_tms;
120 struct tms after_tms;
121 siginfo_t info;
122 int error;
123 int noptions;
124 idtype_t idtype;
126 if (rp)
127 (void) memset(rp, 0, sizeof (struct rusage));
128 (void) memset(&info, 0, sizeof (siginfo_t));
130 if (times(&before_tms) == (clock_t)-1)
131 return (-1); /* errno is set by times() */
134 * SunOS's wait4() previously supported only WNOHANG &
135 * WUNTRACED. XPG4v2 mandates that wait3() (which calls
136 * wait4()) also support WCONTINUED.
138 if (options & ~(WNOHANG|WUNTRACED|WCONTINUED)) {
139 errno = EINVAL;
140 return (-1);
142 noptions = options | WEXITED | WTRAPPED;
145 * Emulate undocumented 4.x semantics for 1186845
147 if (pid < 0) {
148 pid = -pid;
149 idtype = P_PGID;
150 } else if (pid == 0) {
151 idtype = P_ALL;
152 } else {
153 idtype = P_PID;
156 error = waitid(idtype, pid, &info, noptions);
157 if (error == 0) {
158 clock_t diffu; /* difference in usertime (ticks) */
159 clock_t diffs; /* difference in systemtime (ticks) */
160 clock_t hz;
162 if ((options & WNOHANG) && info.si_pid == 0)
163 return (0); /* no child found */
165 if (rp) {
166 if (times(&after_tms) == (clock_t)-1)
167 return (-1); /* errno set by times() */
169 * The system/user time is an approximation only !!!
171 diffu = after_tms.tms_cutime - before_tms.tms_cutime;
172 diffs = after_tms.tms_cstime - before_tms.tms_cstime;
173 hz = CLK_TCK;
174 rp->ru_utime.tv_sec = diffu / hz;
175 rp->ru_utime.tv_usec = (diffu % hz) * (1000000 / hz);
176 rp->ru_stime.tv_sec = diffs / hz;
177 rp->ru_stime.tv_usec = (diffs % hz) * (1000000 / hz);
179 if (stat_loc)
180 *stat_loc = wstat(info.si_code, info.si_status);
181 return (info.si_pid);
182 } else {
183 return (-1); /* error number is set by waitid() */
187 pid_t
188 wait3(int *stat_loc, int options, struct rusage *rp)
190 return (wait4(0, stat_loc, options, rp));