1 /*
2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
8
9 /*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley Software License Agreement
12 * specifies the terms and conditions for redistribution.
13 */
14
15 /*
16 * Compatibility lib for BSD's wait3(). It is not
17 * binary compatible, since BSD's WNOHANG and WUNTRACED
18 * carry different #define values.
19 */
20 #include <errno.h>
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/times.h>
24 #include <wait.h>
25 #include <sys/siginfo.h>
26 #include <sys/procset.h>
27 #include <sys/param.h>
28 #include <sys/resource.h>
29
30 /*
31 * Since sysV does not support rusage as in BSD, an approximate approach
32 * is:
33 * ...
34 * call times
35 * call waitid
36 * if ( a child is found )
37 * call times again
38 * rusage ~= diff in the 2 times call
39 * ...
40 *
41 */
42
43 /*
44 * XXX: There is now a wait3 function in libc which should be used instead
45 * of this local version of wait3. With the addition of a wait3 prototype
46 * in <sys/wait.h> as per the X/Open XPG4v2 specification, compilation of
47 * the csh utility will result in warnings, hence the renaming of the local
48 * version. Using the libc wait3 rather than the local version results in
49 * a failure with csh, however, this version should eventually be dropped
50 * in favor of the libc wait3 with appropriate updates made to sh.proc.c
51 * to account for the difference in implementation of the local versus
52 * the libc versions. This should probably be done as part of an overall
53 * effort to rid csh of local versions of functions now in libc.
54 */
55
56 static int wstat(int code, int status);
57
58 pid_t
csh_wait3(int * status,int options,struct rusage * rp)59 csh_wait3(int *status, int options, struct rusage *rp)
60 {
61 struct tms before_tms;
62 struct tms after_tms;
63 siginfo_t info;
64 int error;
65
66 if (rp)
67 memset((void *)rp, 0, sizeof (struct rusage));
68 memset((void *)&info, 0, sizeof (siginfo_t));
69 if (times(&before_tms) == -1)
70 return (-1); /* errno is set by times() */
71
72 /*
73 * BSD's wait3() only supports WNOHANG & WUNTRACED
74 */
75 options |= (WNOHANG|WUNTRACED|WEXITED|WSTOPPED|WTRAPPED|WCONTINUED);
76 error = waitid(P_ALL, 0, &info, options);
77 if (error == 0) {
78 clock_t diffu; /* difference in usertime (ticks) */
79 clock_t diffs; /* difference in systemtime (ticks) */
80
81 if ((options & WNOHANG) && (info.si_pid == 0))
82 return (0); /* no child found */
83
84 if (rp) {
85 if (times(&after_tms) == -1)
86 return (-1); /* errno set by times() */
87 /*
88 * The system/user time is an approximation only !!!
89 */
90 diffu = after_tms.tms_cutime - before_tms.tms_cutime;
91 diffs = after_tms.tms_cstime - before_tms.tms_cstime;
92 rp->ru_utime.tv_sec = diffu/HZ;
93 rp->ru_utime.tv_usec = ((diffu % HZ) * 1000000) / HZ;
94 rp->ru_stime.tv_sec = diffs/HZ;
95 rp->ru_stime.tv_usec = ((diffs % HZ) * 1000000) / HZ;
96 }
97 *status = wstat(info.si_code, info.si_status);
98 return (info.si_pid);
99
100 } else {
101 return (-1); /* error number is set by waitid() */
102 }
103 }
104
105 /*
106 * Convert the status code to old style wait status
107 */
108 static int
wstat(int code,int status)109 wstat(int code, int status)
110 {
111 int stat = (status & 0377);
112
113 switch (code) {
114 case CLD_EXITED:
115 stat <<= 8;
116 break;
117 case CLD_DUMPED:
118 stat |= WCOREFLG;
119 break;
120 case CLD_KILLED:
121 break;
122 case CLD_TRAPPED:
123 case CLD_STOPPED:
124 stat <<= 8;
125 stat |= WSTOPFLG;
126 break;
127 case CLD_CONTINUED:
128 stat = WCONTFLG;
129 break;
130 }
131 return (stat);
132 }
133
134 pid_t
csh_wait_noreap(void)135 csh_wait_noreap(void)
136 {
137 siginfo_t info;
138
139 if (waitid(P_ALL, 0, &info,
140 WEXITED | WTRAPPED | WSTOPPED | WCONTINUED | WNOWAIT) != 0)
141 return (-1);
142 return (info.si_pid);
143 }
144