xref: /titanic_52/usr/src/cmd/csh/wait3.c (revision 70a587dd392ff1dbaa2875c6c33921f08ea85273)
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