os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/compat/waitpid.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/compat/waitpid.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,174 @@
     1.4 +/* 
     1.5 + * waitpid.c --
     1.6 + *
     1.7 + *	This procedure emulates the POSIX waitpid kernel call on
     1.8 + *	BSD systems that don't have waitpid but do have wait3.
     1.9 + *	This code is based on a prototype version written by
    1.10 + *	Mark Diekhans and Karl Lehenbauer.
    1.11 + *
    1.12 + * Copyright (c) 1993 The Regents of the University of California.
    1.13 + * Copyright (c) 1994 Sun Microsystems, Inc.
    1.14 + *
    1.15 + * See the file "license.terms" for information on usage and redistribution
    1.16 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    1.17 + *
    1.18 + * RCS: @(#) $Id: waitpid.c,v 1.3 2000/01/11 22:08:50 hobbs Exp $
    1.19 + */
    1.20 +
    1.21 +#include "tclInt.h"
    1.22 +#include "tclPort.h"
    1.23 +
    1.24 +#ifndef pid_t
    1.25 +#define pid_t int
    1.26 +#endif
    1.27 +
    1.28 +/*
    1.29 + * A linked list of the following structures is used to keep track
    1.30 + * of processes for which we received notification from the kernel,
    1.31 + * but the application hasn't waited for them yet (this can happen
    1.32 + * because wait may not return the process we really want).  We
    1.33 + * save the information here until the application finally does
    1.34 + * wait for the process.
    1.35 + */
    1.36 +
    1.37 +typedef struct WaitInfo {
    1.38 +    pid_t pid;				/* Pid of process that exited. */
    1.39 +    WAIT_STATUS_TYPE status;		/* Status returned when child exited
    1.40 +					 * or suspended. */
    1.41 +    struct WaitInfo *nextPtr;		/* Next in list of exited processes. */
    1.42 +} WaitInfo;
    1.43 +
    1.44 +static WaitInfo *deadList = NULL;	/* First in list of all dead
    1.45 +					 * processes. */
    1.46 +
    1.47 +/*
    1.48 + *----------------------------------------------------------------------
    1.49 + *
    1.50 + * waitpid --
    1.51 + *
    1.52 + *	This procedure emulates the functionality of the POSIX
    1.53 + *	waitpid kernel call, using the BSD wait3 kernel call.
    1.54 + *	Note:  it doesn't emulate absolutely all of the waitpid
    1.55 + *	functionality, in that it doesn't support pid's of 0
    1.56 + *	or < -1.
    1.57 + *
    1.58 + * Results:
    1.59 + *	-1 is returned if there is an error in the wait kernel call.
    1.60 + *	Otherwise the pid of an exited or suspended process is
    1.61 + *	returned and *statusPtr is set to the status value of the
    1.62 + *	process.
    1.63 + *
    1.64 + * Side effects:
    1.65 + *	None.
    1.66 + *
    1.67 + *----------------------------------------------------------------------
    1.68 + */
    1.69 +
    1.70 +#ifdef waitpid
    1.71 +#   undef waitpid
    1.72 +#endif
    1.73 +
    1.74 +pid_t
    1.75 +waitpid(pid, statusPtr, options)
    1.76 +    pid_t pid;			/* The pid to wait on.  Must be -1 or
    1.77 +				 * greater than zero. */
    1.78 +    int *statusPtr;		/* Where to store wait status for the
    1.79 +				 * process. */
    1.80 +    int options;		/* OR'ed combination of WNOHANG and
    1.81 +				 * WUNTRACED. */
    1.82 +{
    1.83 +    register WaitInfo *waitPtr, *prevPtr;
    1.84 +    pid_t result;
    1.85 +    WAIT_STATUS_TYPE status;
    1.86 +
    1.87 +    if ((pid < -1) || (pid == 0)) {
    1.88 +	errno = EINVAL;
    1.89 +	return -1;
    1.90 +    }
    1.91 +
    1.92 +    /*
    1.93 +     * See if there's a suitable process that has already stopped or
    1.94 +     * exited. If so, remove it from the list of exited processes and
    1.95 +     * return its information.
    1.96 +     */
    1.97 +
    1.98 +    for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL;
    1.99 +	    prevPtr = waitPtr, waitPtr = waitPtr->nextPtr) {
   1.100 +	if ((pid != waitPtr->pid) && (pid != -1)) {
   1.101 +	    continue;
   1.102 +	}
   1.103 +	if (!(options & WUNTRACED) && (WIFSTOPPED(waitPtr->status))) {
   1.104 +	    continue;
   1.105 +	}
   1.106 +	result = waitPtr->pid;
   1.107 +	*statusPtr = *((int *) &waitPtr->status);
   1.108 +	if (prevPtr == NULL) {
   1.109 +	    deadList = waitPtr->nextPtr;
   1.110 +	} else {
   1.111 +	    prevPtr->nextPtr = waitPtr->nextPtr;
   1.112 +	}
   1.113 +	ckfree((char *) waitPtr);
   1.114 +	return result;
   1.115 +    }
   1.116 +
   1.117 +    /*
   1.118 +     * Wait for any process to stop or exit.  If it's an acceptable one
   1.119 +     * then return it to the caller;  otherwise store information about it
   1.120 +     * in the list of exited processes and try again.  On systems that
   1.121 +     * have only wait but not wait3, there are several situations we can't
   1.122 +     * handle, but we do the best we can (e.g. can still handle some
   1.123 +     * combinations of options by invoking wait instead of wait3).
   1.124 +     */
   1.125 +
   1.126 +    while (1) {
   1.127 +#if NO_WAIT3
   1.128 +	if (options & WNOHANG) {
   1.129 +	    return 0;
   1.130 +	}
   1.131 +	if (options != 0) {
   1.132 +	    errno = EINVAL;
   1.133 +	    return -1;
   1.134 +	}
   1.135 +	result = wait(&status);
   1.136 +#else
   1.137 +	result = wait3(&status, options, 0);
   1.138 +#endif
   1.139 +	if ((result == -1) && (errno == EINTR)) {
   1.140 +	    continue;
   1.141 +	}
   1.142 +	if (result <= 0) {
   1.143 +	    return result;
   1.144 +	}
   1.145 +
   1.146 +	if ((pid != result) && (pid != -1)) {
   1.147 +	    goto saveInfo;
   1.148 +	}
   1.149 +	if (!(options & WUNTRACED) && (WIFSTOPPED(status))) {
   1.150 +	    goto saveInfo;
   1.151 +	}
   1.152 +	*statusPtr = *((int *) &status);
   1.153 +	return result;
   1.154 +
   1.155 +	/*
   1.156 +	 * Can't return this info to caller.  Save it in the list of
   1.157 +	 * stopped or exited processes.  Tricky point: first check for
   1.158 +	 * an existing entry for the process and overwrite it if it
   1.159 +	 * exists (e.g. a previously stopped process might now be dead).
   1.160 +	 */
   1.161 +
   1.162 +	saveInfo:
   1.163 +	for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) {
   1.164 +	    if (waitPtr->pid == result) {
   1.165 +		waitPtr->status = status;
   1.166 +		goto waitAgain;
   1.167 +	    }
   1.168 +	}
   1.169 +	waitPtr = (WaitInfo *) ckalloc(sizeof(WaitInfo));
   1.170 +	waitPtr->pid = result;
   1.171 +	waitPtr->status = status;
   1.172 +	waitPtr->nextPtr = deadList;
   1.173 +	deadList = waitPtr;
   1.174 +
   1.175 +	waitAgain: continue;
   1.176 +    }
   1.177 +}