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 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 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 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