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