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