summaryrefslogtreecommitdiffstats
path: root/private/crt32/exec/wait.c
blob: c6ba4cae43a3eb0aab831c7c0a11eb54fa9b981d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/***
*wait.c - OS/2 wait for child process to terminate
*
*	Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*	defines _wait() - wait for child process to terminate
*
*Revision History:
*	06-08-89  PHG	Module created, based on asm version
*	03-08-90  GJF	Made calling type _CALLTYPE2 (for now), added #include
*			<cruntime.h> and fixed the copyright. Also, cleaned up
*			the formatting a bit.
*	04-02-90  GJF	Now _CALLTYPE1.
*	07-24-90  SBM	Removed '32' from API names
*	09-27-90  GJF	New-style function declarators.
*	12-04-90  SRW	Changed to include <oscalls.h> instead of <doscalls.h>
*	12-06-90  SRW	Added _CRUISER_ and _WIN32 conditionals.
*	01-17-91  GJF	ANSI naming
*       02-18-91  SRW   Fixed code to close process handle. [_WIN32_]
*	04-26-91  SRW	Removed level 3 warnings [_WIN32_]
*	12-17-91  GJF	Fixed _cwait for Win32. However, _wait is still
*			broken [_WIN32_].
*	07-21-92  GJF	Removed _wait for Win32, not implemented and no good
*			way to implement.
*	12-14-92  GJF	For Win32, map ERROR_INVALID_HANDLE to ECHILD.
*
*******************************************************************************/

#include <cruntime.h>
#include <oscalls.h>
#include <process.h>
#include <errno.h>
#include <internal.h>
#include <stdlib.h>

/***
*int _cwait(stat_loc, process_id, action_code) - wait for specific child
*	process
*
*Purpose:
*	The function _cwait() suspends the calling-process until the specified
*	child-process terminates.  If the specifed child-process terminated
*	prior to the call to _cwait(), return is immediate.
*
*Entry:
*	int *stat_loc - pointer to where status is stored or NULL
*	process_id - specific process id to be interrogated (0 means any)
*	action_code - specific action to perform on process ID
*		    either _WAIT_CHILD or _WAIT_GRANDCHILD
*
*Exit:
*	process ID of terminated child or -1 on error
*
*	*stat_loc is updated to contain the following:
*	Normal termination: lo-byte = 0, hi-byte = child exit code
*	Abnormal termination: lo-byte = term status, hi-byte = 0
*
*Exceptions:
*
*******************************************************************************/

int _CRTAPI1 _cwait (
	int *stat_loc,
	int process_id,
	int action_code
	)
{
#ifdef	_CRUISER_
	ULONG retstatus;  	        /* return status from child */
	ULONG retval;	    	        /* return value from wait */
	char abnormend; 		/* child terminated abnormally */
	ULONG dosretval;		/* return value from OS/2 call */
	RESULTCODES retcodes;		/* return codes from child process */
	PID pid_finished;		/* process id of child that finished */

	/* call OS/2 wait for child routine */
	if (dosretval = DOSWAITCHILD(action_code, DCWW_WAIT, &retcodes,
	&pid_finished, process_id)) {
		/* error occured -- map error code and return */
		_dosmaperr(dosretval);
		return -1;
	}

	/* set status code values -- note that return value is
	   truncated to a byte for XENIX compatibility */

	if (retcodes.codeTerminate != 0) {
            abnormend = 1;
            retstatus = retcodes.codeTerminate & 0xFF;
        }
        else {
            abnormend = 0;
            retstatus = (retcodes.codeResult & 0xFF) << 8 +
			(retcodes.codeTerminate & 0xFF);
        }

	if (stat_loc != NULL)
            *stat_loc = retstatus;

	if (abnormend) {
		/* abnormal termination, set errno and return -1 */
		errno = EINTR;
		_doserrno = 0;	    /* no OS/2 error */
		return -1;
	}

	return retval;

#else	/* ndef _CRUISER_ */

#ifdef	_WIN32_

	int retval;
	int retstatus;
	unsigned long oserror;

	DBG_UNREFERENCED_PARAMETER(action_code);

	/* Explicitly check for process_id being -1 or -2. In Windows NT,
	 * -1 is a handle on the current process, -2 is a handle on the
	 * current thread, and it is perfectly legal to to wait (forever)
	 * on either */
	if ( (process_id == -1) || (process_id == -2) ) {
	    errno = ECHILD;
	    return -1;
	}

	/* wait for child process, then fetch its exit code */
	if ( (WaitForSingleObject((HANDLE)process_id, (DWORD)(-1L)) == 0) &&
	  GetExitCodeProcess((HANDLE)process_id, (LPDWORD)&retstatus) ) {
	    retval = process_id;
	}
	else {
	    /* one of the API calls failed. map the error and set up to
	       return failure. note the invalid handle error is mapped in-
	       line to ECHILD */
	    if ( (oserror = GetLastError()) == ERROR_INVALID_HANDLE ) {
		errno = ECHILD;
		_doserrno = oserror;
	    }
	    else
		_dosmaperr(GetLastError());

	    retval = -1;
	    retstatus = -1;
	}

        CloseHandle((HANDLE)process_id);

	if (stat_loc != NULL)
	    *stat_loc = retstatus;

	return retval;

#else	/* ndef _WIN32_ */

#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!

#endif	/* _WIN32_ */

#endif	/* _CRUISER_ */
}


#ifndef _WIN32_

/***
*int _wait(stat_loc) - wait for a child to terminate
*
*Purpose:
*	The function _wait() suspends the calling-process until one of the
*	immediate children terminates.	If a child-process terminated prior to
*	the call on the function _wait(), return is immediate.
*
*Entry:
*	int *stat_loc - pointer to where status is stored or NULL
*
*Exit:
*	returns process id or -1 on errors.
*
*	*stat_loc is updated to contain the following:
*	Normal termination: lo-byte = 0, hi-byte = child exit code
*	Abnormal termination: lo-byte = term status, hi-byte = 0
*
*Exceptions:
*
*******************************************************************************/

/* _wait calls _cwait to do all the real work */
int _CRTAPI1 _wait (
	int *stat_loc
	)
{
	return _cwait(stat_loc, 0, _WAIT_CHILD);
}


#endif