17c478bd9Sstevel@tonic-gate /* 2*70a587ddSchin * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate /* 187c478bd9Sstevel@tonic-gate * Compatibility lib for BSD's wait3(). It is not 197c478bd9Sstevel@tonic-gate * binary compatible, since BSD's WNOHANG and WUNTRACED 207c478bd9Sstevel@tonic-gate * carry different #define values. 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate #include <errno.h> 237c478bd9Sstevel@tonic-gate #include <sys/types.h> 247c478bd9Sstevel@tonic-gate #include <sys/time.h> 257c478bd9Sstevel@tonic-gate #include <sys/times.h> 267c478bd9Sstevel@tonic-gate #include <wait.h> 277c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 287c478bd9Sstevel@tonic-gate #include <sys/procset.h> 297c478bd9Sstevel@tonic-gate #include <sys/param.h> 307c478bd9Sstevel@tonic-gate #include <sys/resource.h> 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate /* 337c478bd9Sstevel@tonic-gate * Since sysV does not support rusage as in BSD, an approximate approach 347c478bd9Sstevel@tonic-gate * is: 357c478bd9Sstevel@tonic-gate * ... 367c478bd9Sstevel@tonic-gate * call times 377c478bd9Sstevel@tonic-gate * call waitid 387c478bd9Sstevel@tonic-gate * if ( a child is found ) 397c478bd9Sstevel@tonic-gate * call times again 407c478bd9Sstevel@tonic-gate * rusage ~= diff in the 2 times call 417c478bd9Sstevel@tonic-gate * ... 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* 467c478bd9Sstevel@tonic-gate * XXX: There is now a wait3 function in libc which should be used instead 477c478bd9Sstevel@tonic-gate * of this local version of wait3. With the addition of a wait3 prototype 487c478bd9Sstevel@tonic-gate * in <sys/wait.h> as per the X/Open XPG4v2 specification, compilation of 497c478bd9Sstevel@tonic-gate * the csh utility will result in warnings, hence the renaming of the local 507c478bd9Sstevel@tonic-gate * version. Using the libc wait3 rather than the local version results in 517c478bd9Sstevel@tonic-gate * a failure with csh, however, this version should eventually be dropped 527c478bd9Sstevel@tonic-gate * in favor of the libc wait3 with appropriate updates made to sh.proc.c 537c478bd9Sstevel@tonic-gate * to account for the difference in implementation of the local versus 547c478bd9Sstevel@tonic-gate * the libc versions. This should probably be done as part of an overall 557c478bd9Sstevel@tonic-gate * effort to rid csh of local versions of functions now in libc. 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate 588e3c57a3Sraf static int wstat(int code, int status); 597c478bd9Sstevel@tonic-gate 608e3c57a3Sraf pid_t 618e3c57a3Sraf csh_wait3(int *status, int options, struct rusage *rp) 627c478bd9Sstevel@tonic-gate { 637c478bd9Sstevel@tonic-gate struct tms before_tms; 647c478bd9Sstevel@tonic-gate struct tms after_tms; 657c478bd9Sstevel@tonic-gate siginfo_t info; 667c478bd9Sstevel@tonic-gate int error; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate if (rp) 697c478bd9Sstevel@tonic-gate memset((void *)rp, 0, sizeof (struct rusage)); 707c478bd9Sstevel@tonic-gate memset((void *)&info, 0, sizeof (siginfo_t)); 717c478bd9Sstevel@tonic-gate if (times(&before_tms) == -1) 727c478bd9Sstevel@tonic-gate return (-1); /* errno is set by times() */ 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * BSD's wait3() only supports WNOHANG & WUNTRACED 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate options |= (WNOHANG|WUNTRACED|WEXITED|WSTOPPED|WTRAPPED|WCONTINUED); 787c478bd9Sstevel@tonic-gate error = waitid(P_ALL, 0, &info, options); 797c478bd9Sstevel@tonic-gate if (error == 0) { 807c478bd9Sstevel@tonic-gate clock_t diffu; /* difference in usertime (ticks) */ 817c478bd9Sstevel@tonic-gate clock_t diffs; /* difference in systemtime (ticks) */ 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate if ((options & WNOHANG) && (info.si_pid == 0)) 847c478bd9Sstevel@tonic-gate return (0); /* no child found */ 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate if (rp) { 877c478bd9Sstevel@tonic-gate if (times(&after_tms) == -1) 887c478bd9Sstevel@tonic-gate return (-1); /* errno set by times() */ 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * The system/user time is an approximation only !!! 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate diffu = after_tms.tms_cutime - before_tms.tms_cutime; 937c478bd9Sstevel@tonic-gate diffs = after_tms.tms_cstime - before_tms.tms_cstime; 947c478bd9Sstevel@tonic-gate rp->ru_utime.tv_sec = diffu/HZ; 95*70a587ddSchin rp->ru_utime.tv_usec = ((diffu % HZ) * 1000000) / HZ; 967c478bd9Sstevel@tonic-gate rp->ru_stime.tv_sec = diffs/HZ; 97*70a587ddSchin rp->ru_stime.tv_usec = ((diffs % HZ) * 1000000) / HZ; 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate *status = wstat(info.si_code, info.si_status); 1007c478bd9Sstevel@tonic-gate return (info.si_pid); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate } else { 1037c478bd9Sstevel@tonic-gate return (-1); /* error number is set by waitid() */ 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * Convert the status code to old style wait status 1097c478bd9Sstevel@tonic-gate */ 1108e3c57a3Sraf static int 1118e3c57a3Sraf wstat(int code, int status) 1127c478bd9Sstevel@tonic-gate { 1138e3c57a3Sraf int stat = (status & 0377); 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate switch (code) { 1167c478bd9Sstevel@tonic-gate case CLD_EXITED: 1177c478bd9Sstevel@tonic-gate stat <<= 8; 1187c478bd9Sstevel@tonic-gate break; 1197c478bd9Sstevel@tonic-gate case CLD_DUMPED: 1207c478bd9Sstevel@tonic-gate stat |= WCOREFLG; 1217c478bd9Sstevel@tonic-gate break; 1227c478bd9Sstevel@tonic-gate case CLD_KILLED: 1237c478bd9Sstevel@tonic-gate break; 1247c478bd9Sstevel@tonic-gate case CLD_TRAPPED: 1257c478bd9Sstevel@tonic-gate case CLD_STOPPED: 1267c478bd9Sstevel@tonic-gate stat <<= 8; 1277c478bd9Sstevel@tonic-gate stat |= WSTOPFLG; 1287c478bd9Sstevel@tonic-gate break; 1297c478bd9Sstevel@tonic-gate case CLD_CONTINUED: 1307c478bd9Sstevel@tonic-gate stat = WCONTFLG; 1317c478bd9Sstevel@tonic-gate break; 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate return (stat); 1347c478bd9Sstevel@tonic-gate } 1358e3c57a3Sraf 1368e3c57a3Sraf pid_t 1378e3c57a3Sraf csh_wait_noreap(void) 1388e3c57a3Sraf { 1398e3c57a3Sraf siginfo_t info; 1408e3c57a3Sraf 1418e3c57a3Sraf if (waitid(P_ALL, 0, &info, 1428e3c57a3Sraf WEXITED | WTRAPPED | WSTOPPED | WCONTINUED | WNOWAIT) != 0) 1438e3c57a3Sraf return (-1); 1448e3c57a3Sraf return (info.si_pid); 1458e3c57a3Sraf } 146