os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/compat/waitpid.c
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 +}