view usr/src/cmd/csh/wait3.c @ 0:c9caec207d52 b86

Initial porting based on b86
author Koji Uno <koji.uno@sun.com>
date Tue, 02 Jun 2009 18:56:50 +0900
parents
children 1a15d5aaf794
line wrap: on
line source

/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/

/*
 * Copyright (c) 1980 Regents of the University of California.
 * All rights reserved. The Berkeley Software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#pragma ident	"@(#)wait3.c	1.8	06/06/12 SMI"

/*
 * Compatibility lib for BSD's wait3(). It is not
 * binary compatible, since BSD's WNOHANG and WUNTRACED
 * carry different #define values.
 */
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/times.h>
#include <wait.h>
#include <sys/siginfo.h>
#include <sys/procset.h>
#include <sys/param.h>
#include <sys/resource.h>

/*
 * Since sysV does not support rusage as in BSD, an approximate approach
 * is:
 *	...
 *	call times
 *	call waitid
 *	if ( a child is found )
 *		call times again
 *		rusage ~= diff in the 2 times call
 *	...
 *
 */

/*
 * XXX:  There is now a wait3 function in libc which should be used instead
 * of this local version of wait3.  With the addition of a wait3 prototype
 * in <sys/wait.h> as per the X/Open XPG4v2 specification, compilation of
 * the csh utility will result in warnings, hence the renaming of the local
 * version.  Using the libc wait3 rather than the local version results in
 * a failure with csh, however, this version should eventually be dropped
 * in favor of the libc wait3 with appropriate updates made to sh.proc.c
 * to account for the difference in implementation of the local versus
 * the libc versions.  This should probably be done as part of an overall
 * effort to rid csh of local versions of functions now in libc.
 */

static int wstat(int code, int status);

pid_t
csh_wait3(int *status, int options, struct rusage *rp)
{
	struct tms before_tms;
	struct tms after_tms;
	siginfo_t info;
	int error;

	if (rp)
		memset((void *)rp, 0, sizeof (struct rusage));
	memset((void *)&info, 0, sizeof (siginfo_t));
	if (times(&before_tms) == -1)
		return (-1);	/* errno is set by times() */

	/*
	 * BSD's wait3() only supports WNOHANG & WUNTRACED
	 */
	options |= (WNOHANG|WUNTRACED|WEXITED|WSTOPPED|WTRAPPED|WCONTINUED);
	error = waitid(P_ALL, 0, &info, options);
	if (error == 0) {
		clock_t	diffu;	/* difference in usertime (ticks) */
		clock_t	diffs;	/* difference in systemtime (ticks) */

		if ((options & WNOHANG) && (info.si_pid == 0))
			return (0);	/* no child found */

		if (rp) {
			if (times(&after_tms) == -1)
				return (-1);	/* errno set by times() */
			/*
			 * The system/user time is an approximation only !!!
			 */
			diffu = after_tms.tms_cutime - before_tms.tms_cutime;
			diffs = after_tms.tms_cstime - before_tms.tms_cstime;
			rp->ru_utime.tv_sec = diffu/HZ;
			rp->ru_utime.tv_usec = ((diffu % HZ) * 1000000) / HZ;
			rp->ru_stime.tv_sec = diffs/HZ;
			rp->ru_stime.tv_usec = ((diffs % HZ) * 1000000) / HZ;
		}
		*status = wstat(info.si_code, info.si_status);
		return (info.si_pid);

	} else {
		return (-1);	/* error number is set by waitid() */
	}
}

/*
 * Convert the status code to old style wait status
 */
static int
wstat(int code, int status)
{
	int stat = (status & 0377);

	switch (code) {
		case CLD_EXITED:
			stat <<= 8;
			break;
		case CLD_DUMPED:
			stat |= WCOREFLG;
			break;
		case CLD_KILLED:
			break;
		case CLD_TRAPPED:
		case CLD_STOPPED:
			stat <<= 8;
			stat |= WSTOPFLG;
			break;
		case CLD_CONTINUED:
			stat = WCONTFLG;
			break;
	}
	return (stat);
}

pid_t
csh_wait_noreap(void)
{
	siginfo_t info;

	if (waitid(P_ALL, 0, &info,
	    WEXITED | WTRAPPED | WSTOPPED | WCONTINUED | WNOWAIT) != 0)
		return (-1);
	return (info.si_pid);
}