/* wait.c (rsxnt) -- Copyright (c) 1996-1998 Rainer Schnitker */

#include "rsxnt.h"
#include <string.h>

#ifdef EMX_SYS_LIB /* dynamic link via ctordtor in ptrace() */
extern WAIT_DEBUG _func_rsxnt_wait_debuggee = NULL;
#endif

int __wait(int *status)
{
    EMXPROCESS *p = _rsxnt_get_process_ptr();
    int i, h, pid;
    DWORD rc;
    HANDLE handles[MAX_CHILD + 1], hfind;
    DWORD dwExit;

    if (p->debuggee.status)
#ifndef EMX_SYS_LIB
        return _rsxnt_wait_debuggee(status);
#else
        if (_func_rsxnt_wait_debuggee)
            return (*_func_rsxnt_wait_debuggee)(status);
#endif

    h = 0;
    for (i = 0; i < MAX_CHILD; i++) {
	if (p->childs[i].hProcess)
	    handles[h++] = p->childs[i].hProcess;
    }
    if (!h)
	return _rsxnt_errno(ECHILD);

    if (_rsxnt_win32_version == WIN32S) {
	DWORD dw;
	int ok = 0;
	rc = WAIT_FAILED;

	for (;;) {
	    int n = 0;

	    for (i = 0; i < h; i++) {
		if (GetExitCodeProcess(handles[i], &dw) != FALSE) {
		    if (dw != STILL_ACTIVE) {
			ok = 1;
			rc = WAIT_OBJECT_0 + i;
			break;
		    }
		} else
		    ++n;
	    }

	    if (n == h)
		return _rsxnt_errno(ECHILD);

	    if (ok == 0)
		Sleep(100);
	    else
		break;
	}
    }
    else {
	rc = WaitForMultipleObjects(h, handles, FALSE, INFINITE);
    }

    if (rc == WAIT_FAILED)
	return _rsxnt_errno(ECHILD);
    else
	rc -= WAIT_OBJECT_0;

    hfind = handles[rc];

    for (h = 0; h < MAX_CHILD; h++)
	if (p->childs[h].hProcess == hfind)
		break;

    GetExitCodeProcess(p->childs[h].hProcess, &dwExit);
    CloseHandle (p->childs[h].hProcess);
    *status = dwExit << 8;

    pid = p->childs[h].pid;
    memset (&(p->childs[h]), 0, sizeof(struct child));
    return pid;
}
