xref: /aosp_15_r20/external/deqp/framework/delibs/deutil/deProcess.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Utility Library
3*35238bceSAndroid Build Coastguard Worker  * ----------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Process abstraction.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "deProcess.h"
25*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
26*35238bceSAndroid Build Coastguard Worker #include "deString.h"
27*35238bceSAndroid Build Coastguard Worker 
28*35238bceSAndroid Build Coastguard Worker #if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || \
29*35238bceSAndroid Build Coastguard Worker     (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX)
30*35238bceSAndroid Build Coastguard Worker 
31*35238bceSAndroid Build Coastguard Worker #include "deCommandLine.h"
32*35238bceSAndroid Build Coastguard Worker 
33*35238bceSAndroid Build Coastguard Worker #include <sys/types.h>
34*35238bceSAndroid Build Coastguard Worker #include <sys/wait.h>
35*35238bceSAndroid Build Coastguard Worker #include <unistd.h>
36*35238bceSAndroid Build Coastguard Worker #include <stdlib.h>
37*35238bceSAndroid Build Coastguard Worker #include <signal.h>
38*35238bceSAndroid Build Coastguard Worker #include <fcntl.h>
39*35238bceSAndroid Build Coastguard Worker #include <errno.h>
40*35238bceSAndroid Build Coastguard Worker 
41*35238bceSAndroid Build Coastguard Worker typedef enum ProcessState_e
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker     PROCESSSTATE_NOT_STARTED = 0,
44*35238bceSAndroid Build Coastguard Worker     PROCESSSTATE_RUNNING,
45*35238bceSAndroid Build Coastguard Worker     PROCESSSTATE_FINISHED,
46*35238bceSAndroid Build Coastguard Worker 
47*35238bceSAndroid Build Coastguard Worker     PROCESSSTATE_LAST
48*35238bceSAndroid Build Coastguard Worker } ProcessState;
49*35238bceSAndroid Build Coastguard Worker 
50*35238bceSAndroid Build Coastguard Worker struct deProcess_s
51*35238bceSAndroid Build Coastguard Worker {
52*35238bceSAndroid Build Coastguard Worker     ProcessState state;
53*35238bceSAndroid Build Coastguard Worker     int exitCode;
54*35238bceSAndroid Build Coastguard Worker     char *lastError;
55*35238bceSAndroid Build Coastguard Worker 
56*35238bceSAndroid Build Coastguard Worker     pid_t pid;
57*35238bceSAndroid Build Coastguard Worker     deFile *standardIn;
58*35238bceSAndroid Build Coastguard Worker     deFile *standardOut;
59*35238bceSAndroid Build Coastguard Worker     deFile *standardErr;
60*35238bceSAndroid Build Coastguard Worker };
61*35238bceSAndroid Build Coastguard Worker 
die(int statusPipe,const char * message)62*35238bceSAndroid Build Coastguard Worker static void die(int statusPipe, const char *message)
63*35238bceSAndroid Build Coastguard Worker {
64*35238bceSAndroid Build Coastguard Worker     size_t msgLen = strlen(message);
65*35238bceSAndroid Build Coastguard Worker     int res       = 0;
66*35238bceSAndroid Build Coastguard Worker 
67*35238bceSAndroid Build Coastguard Worker     printf("Process launch failed: %s\n", message);
68*35238bceSAndroid Build Coastguard Worker     res = (int)write(statusPipe, message, msgLen + 1);
69*35238bceSAndroid Build Coastguard Worker     DE_UNREF(res); /* No need to check result. */
70*35238bceSAndroid Build Coastguard Worker     exit(-1);
71*35238bceSAndroid Build Coastguard Worker }
72*35238bceSAndroid Build Coastguard Worker 
dieLastError(int statusPipe,const char * message)73*35238bceSAndroid Build Coastguard Worker static void dieLastError(int statusPipe, const char *message)
74*35238bceSAndroid Build Coastguard Worker {
75*35238bceSAndroid Build Coastguard Worker     char msgBuf[256];
76*35238bceSAndroid Build Coastguard Worker     int lastErr = errno;
77*35238bceSAndroid Build Coastguard Worker     deSprintf(msgBuf, sizeof(msgBuf), "%s, error %d: %s", message, lastErr, strerror(lastErr));
78*35238bceSAndroid Build Coastguard Worker     die(statusPipe, msgBuf);
79*35238bceSAndroid Build Coastguard Worker }
80*35238bceSAndroid Build Coastguard Worker 
beginsWithPath(const char * fileName,const char * pathPrefix)81*35238bceSAndroid Build Coastguard Worker DE_INLINE bool beginsWithPath(const char *fileName, const char *pathPrefix)
82*35238bceSAndroid Build Coastguard Worker {
83*35238bceSAndroid Build Coastguard Worker     size_t pathLen = strlen(pathPrefix);
84*35238bceSAndroid Build Coastguard Worker 
85*35238bceSAndroid Build Coastguard Worker     /* Strip trailing / */
86*35238bceSAndroid Build Coastguard Worker     while (pathLen > 0 && pathPrefix[pathLen - 1] == '/')
87*35238bceSAndroid Build Coastguard Worker         pathLen -= 1;
88*35238bceSAndroid Build Coastguard Worker 
89*35238bceSAndroid Build Coastguard Worker     return pathLen > 0 && deMemoryEqual(fileName, pathPrefix, pathLen) && fileName[pathLen] == '/';
90*35238bceSAndroid Build Coastguard Worker }
91*35238bceSAndroid Build Coastguard Worker 
stripLeadingPath(char * fileName,const char * pathPrefix)92*35238bceSAndroid Build Coastguard Worker static void stripLeadingPath(char *fileName, const char *pathPrefix)
93*35238bceSAndroid Build Coastguard Worker {
94*35238bceSAndroid Build Coastguard Worker     size_t pathLen     = strlen(pathPrefix);
95*35238bceSAndroid Build Coastguard Worker     size_t fileNameLen = strlen(fileName);
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(beginsWithPath(fileName, pathPrefix));
98*35238bceSAndroid Build Coastguard Worker 
99*35238bceSAndroid Build Coastguard Worker     /* Strip trailing / */
100*35238bceSAndroid Build Coastguard Worker     while (pathLen > 0 && pathPrefix[pathLen - 1] == '/')
101*35238bceSAndroid Build Coastguard Worker         pathLen -= 1;
102*35238bceSAndroid Build Coastguard Worker 
103*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(pathLen > 0);
104*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(fileName[pathLen] == '/');
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker     memmove(&fileName[0], &fileName[0] + pathLen + 1, fileNameLen - pathLen);
107*35238bceSAndroid Build Coastguard Worker }
108*35238bceSAndroid Build Coastguard Worker 
109*35238bceSAndroid Build Coastguard Worker /* Doesn't return on success. */
execProcess(const char * commandLine,const char * workingDirectory,int statusPipe)110*35238bceSAndroid Build Coastguard Worker static void execProcess(const char *commandLine, const char *workingDirectory, int statusPipe)
111*35238bceSAndroid Build Coastguard Worker {
112*35238bceSAndroid Build Coastguard Worker     deCommandLine *cmdLine = deCommandLine_parse(commandLine);
113*35238bceSAndroid Build Coastguard Worker     char **argList         = cmdLine ? (char **)deCalloc(sizeof(char *) * ((size_t)cmdLine->numArgs + 1)) : DE_NULL;
114*35238bceSAndroid Build Coastguard Worker 
115*35238bceSAndroid Build Coastguard Worker     if (!cmdLine || !argList)
116*35238bceSAndroid Build Coastguard Worker         die(statusPipe, "Command line parsing failed (out of memory)");
117*35238bceSAndroid Build Coastguard Worker 
118*35238bceSAndroid Build Coastguard Worker     if (workingDirectory && chdir(workingDirectory) != 0)
119*35238bceSAndroid Build Coastguard Worker         dieLastError(statusPipe, "chdir() failed");
120*35238bceSAndroid Build Coastguard Worker 
121*35238bceSAndroid Build Coastguard Worker     {
122*35238bceSAndroid Build Coastguard Worker         int argNdx;
123*35238bceSAndroid Build Coastguard Worker         for (argNdx = 0; argNdx < cmdLine->numArgs; argNdx++)
124*35238bceSAndroid Build Coastguard Worker             argList[argNdx] = cmdLine->args[argNdx];
125*35238bceSAndroid Build Coastguard Worker         argList[argNdx] = DE_NULL; /* Terminate with 0. */
126*35238bceSAndroid Build Coastguard Worker     }
127*35238bceSAndroid Build Coastguard Worker 
128*35238bceSAndroid Build Coastguard Worker     if (workingDirectory && beginsWithPath(argList[0], workingDirectory))
129*35238bceSAndroid Build Coastguard Worker         stripLeadingPath(argList[0], workingDirectory);
130*35238bceSAndroid Build Coastguard Worker 
131*35238bceSAndroid Build Coastguard Worker     execv(argList[0], argList);
132*35238bceSAndroid Build Coastguard Worker 
133*35238bceSAndroid Build Coastguard Worker     /* Failed. */
134*35238bceSAndroid Build Coastguard Worker     dieLastError(statusPipe, "execv() failed");
135*35238bceSAndroid Build Coastguard Worker }
136*35238bceSAndroid Build Coastguard Worker 
deProcess_create(void)137*35238bceSAndroid Build Coastguard Worker deProcess *deProcess_create(void)
138*35238bceSAndroid Build Coastguard Worker {
139*35238bceSAndroid Build Coastguard Worker     deProcess *process = (deProcess *)deCalloc(sizeof(deProcess));
140*35238bceSAndroid Build Coastguard Worker     if (!process)
141*35238bceSAndroid Build Coastguard Worker         return NULL;
142*35238bceSAndroid Build Coastguard Worker 
143*35238bceSAndroid Build Coastguard Worker     process->state = PROCESSSTATE_NOT_STARTED;
144*35238bceSAndroid Build Coastguard Worker 
145*35238bceSAndroid Build Coastguard Worker     return process;
146*35238bceSAndroid Build Coastguard Worker }
147*35238bceSAndroid Build Coastguard Worker 
deProcess_cleanupHandles(deProcess * process)148*35238bceSAndroid Build Coastguard Worker static void deProcess_cleanupHandles(deProcess *process)
149*35238bceSAndroid Build Coastguard Worker {
150*35238bceSAndroid Build Coastguard Worker     if (process->standardIn)
151*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardIn);
152*35238bceSAndroid Build Coastguard Worker 
153*35238bceSAndroid Build Coastguard Worker     if (process->standardOut)
154*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardOut);
155*35238bceSAndroid Build Coastguard Worker 
156*35238bceSAndroid Build Coastguard Worker     if (process->standardErr)
157*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardErr);
158*35238bceSAndroid Build Coastguard Worker 
159*35238bceSAndroid Build Coastguard Worker     process->pid         = 0;
160*35238bceSAndroid Build Coastguard Worker     process->standardIn  = DE_NULL;
161*35238bceSAndroid Build Coastguard Worker     process->standardOut = DE_NULL;
162*35238bceSAndroid Build Coastguard Worker     process->standardErr = DE_NULL;
163*35238bceSAndroid Build Coastguard Worker }
164*35238bceSAndroid Build Coastguard Worker 
deProcess_destroy(deProcess * process)165*35238bceSAndroid Build Coastguard Worker void deProcess_destroy(deProcess *process)
166*35238bceSAndroid Build Coastguard Worker {
167*35238bceSAndroid Build Coastguard Worker     /* Never leave child processes running. Otherwise we'll have zombies. */
168*35238bceSAndroid Build Coastguard Worker     if (deProcess_isRunning(process))
169*35238bceSAndroid Build Coastguard Worker     {
170*35238bceSAndroid Build Coastguard Worker         deProcess_kill(process);
171*35238bceSAndroid Build Coastguard Worker         deProcess_waitForFinish(process);
172*35238bceSAndroid Build Coastguard Worker     }
173*35238bceSAndroid Build Coastguard Worker 
174*35238bceSAndroid Build Coastguard Worker     deProcess_cleanupHandles(process);
175*35238bceSAndroid Build Coastguard Worker     deFree(process->lastError);
176*35238bceSAndroid Build Coastguard Worker     deFree(process);
177*35238bceSAndroid Build Coastguard Worker }
178*35238bceSAndroid Build Coastguard Worker 
deProcess_getLastError(const deProcess * process)179*35238bceSAndroid Build Coastguard Worker const char *deProcess_getLastError(const deProcess *process)
180*35238bceSAndroid Build Coastguard Worker {
181*35238bceSAndroid Build Coastguard Worker     return process->lastError ? process->lastError : "No error";
182*35238bceSAndroid Build Coastguard Worker }
183*35238bceSAndroid Build Coastguard Worker 
deProcess_getExitCode(const deProcess * process)184*35238bceSAndroid Build Coastguard Worker int deProcess_getExitCode(const deProcess *process)
185*35238bceSAndroid Build Coastguard Worker {
186*35238bceSAndroid Build Coastguard Worker     return process->exitCode;
187*35238bceSAndroid Build Coastguard Worker }
188*35238bceSAndroid Build Coastguard Worker 
deProcess_setError(deProcess * process,const char * error)189*35238bceSAndroid Build Coastguard Worker static bool deProcess_setError(deProcess *process, const char *error)
190*35238bceSAndroid Build Coastguard Worker {
191*35238bceSAndroid Build Coastguard Worker     if (process->lastError)
192*35238bceSAndroid Build Coastguard Worker     {
193*35238bceSAndroid Build Coastguard Worker         deFree(process->lastError);
194*35238bceSAndroid Build Coastguard Worker         process->lastError = DE_NULL;
195*35238bceSAndroid Build Coastguard Worker     }
196*35238bceSAndroid Build Coastguard Worker 
197*35238bceSAndroid Build Coastguard Worker     process->lastError = deStrdup(error);
198*35238bceSAndroid Build Coastguard Worker     return process->lastError != DE_NULL;
199*35238bceSAndroid Build Coastguard Worker }
200*35238bceSAndroid Build Coastguard Worker 
deProcess_setErrorFromErrno(deProcess * process,const char * message)201*35238bceSAndroid Build Coastguard Worker static bool deProcess_setErrorFromErrno(deProcess *process, const char *message)
202*35238bceSAndroid Build Coastguard Worker {
203*35238bceSAndroid Build Coastguard Worker     char msgBuf[256];
204*35238bceSAndroid Build Coastguard Worker     int lastErr = errno;
205*35238bceSAndroid Build Coastguard Worker     deSprintf(msgBuf, sizeof(msgBuf), "%s, error %d: %s", message, lastErr, strerror(lastErr));
206*35238bceSAndroid Build Coastguard Worker     return deProcess_setError(process, message);
207*35238bceSAndroid Build Coastguard Worker }
208*35238bceSAndroid Build Coastguard Worker 
closePipe(int p[2])209*35238bceSAndroid Build Coastguard Worker static void closePipe(int p[2])
210*35238bceSAndroid Build Coastguard Worker {
211*35238bceSAndroid Build Coastguard Worker     if (p[0] >= 0)
212*35238bceSAndroid Build Coastguard Worker         close(p[0]);
213*35238bceSAndroid Build Coastguard Worker     if (p[1] >= 0)
214*35238bceSAndroid Build Coastguard Worker         close(p[1]);
215*35238bceSAndroid Build Coastguard Worker }
216*35238bceSAndroid Build Coastguard Worker 
deProcess_start(deProcess * process,const char * commandLine,const char * workingDirectory)217*35238bceSAndroid Build Coastguard Worker bool deProcess_start(deProcess *process, const char *commandLine, const char *workingDirectory)
218*35238bceSAndroid Build Coastguard Worker {
219*35238bceSAndroid Build Coastguard Worker     pid_t pid         = 0;
220*35238bceSAndroid Build Coastguard Worker     int pipeIn[2]     = {-1, -1};
221*35238bceSAndroid Build Coastguard Worker     int pipeOut[2]    = {-1, -1};
222*35238bceSAndroid Build Coastguard Worker     int pipeErr[2]    = {-1, -1};
223*35238bceSAndroid Build Coastguard Worker     int statusPipe[2] = {-1, -1};
224*35238bceSAndroid Build Coastguard Worker 
225*35238bceSAndroid Build Coastguard Worker     if (process->state == PROCESSSTATE_RUNNING)
226*35238bceSAndroid Build Coastguard Worker     {
227*35238bceSAndroid Build Coastguard Worker         deProcess_setError(process, "Process already running");
228*35238bceSAndroid Build Coastguard Worker         return false;
229*35238bceSAndroid Build Coastguard Worker     }
230*35238bceSAndroid Build Coastguard Worker     else if (process->state == PROCESSSTATE_FINISHED)
231*35238bceSAndroid Build Coastguard Worker     {
232*35238bceSAndroid Build Coastguard Worker         deProcess_cleanupHandles(process);
233*35238bceSAndroid Build Coastguard Worker         process->state = PROCESSSTATE_NOT_STARTED;
234*35238bceSAndroid Build Coastguard Worker     }
235*35238bceSAndroid Build Coastguard Worker 
236*35238bceSAndroid Build Coastguard Worker     if (pipe(pipeIn) < 0 || pipe(pipeOut) < 0 || pipe(pipeErr) < 0 || pipe(statusPipe) < 0)
237*35238bceSAndroid Build Coastguard Worker     {
238*35238bceSAndroid Build Coastguard Worker         deProcess_setErrorFromErrno(process, "pipe() failed");
239*35238bceSAndroid Build Coastguard Worker 
240*35238bceSAndroid Build Coastguard Worker         closePipe(pipeIn);
241*35238bceSAndroid Build Coastguard Worker         closePipe(pipeOut);
242*35238bceSAndroid Build Coastguard Worker         closePipe(pipeErr);
243*35238bceSAndroid Build Coastguard Worker         closePipe(statusPipe);
244*35238bceSAndroid Build Coastguard Worker 
245*35238bceSAndroid Build Coastguard Worker         return false;
246*35238bceSAndroid Build Coastguard Worker     }
247*35238bceSAndroid Build Coastguard Worker 
248*35238bceSAndroid Build Coastguard Worker     pid = fork();
249*35238bceSAndroid Build Coastguard Worker 
250*35238bceSAndroid Build Coastguard Worker     if (pid < 0)
251*35238bceSAndroid Build Coastguard Worker     {
252*35238bceSAndroid Build Coastguard Worker         deProcess_setErrorFromErrno(process, "fork() failed");
253*35238bceSAndroid Build Coastguard Worker 
254*35238bceSAndroid Build Coastguard Worker         closePipe(pipeIn);
255*35238bceSAndroid Build Coastguard Worker         closePipe(pipeOut);
256*35238bceSAndroid Build Coastguard Worker         closePipe(pipeErr);
257*35238bceSAndroid Build Coastguard Worker         closePipe(statusPipe);
258*35238bceSAndroid Build Coastguard Worker 
259*35238bceSAndroid Build Coastguard Worker         return false;
260*35238bceSAndroid Build Coastguard Worker     }
261*35238bceSAndroid Build Coastguard Worker 
262*35238bceSAndroid Build Coastguard Worker     if (pid == 0)
263*35238bceSAndroid Build Coastguard Worker     {
264*35238bceSAndroid Build Coastguard Worker         /* Child process. */
265*35238bceSAndroid Build Coastguard Worker 
266*35238bceSAndroid Build Coastguard Worker         /* Close unused endpoints. */
267*35238bceSAndroid Build Coastguard Worker         close(pipeIn[1]);
268*35238bceSAndroid Build Coastguard Worker         close(pipeOut[0]);
269*35238bceSAndroid Build Coastguard Worker         close(pipeErr[0]);
270*35238bceSAndroid Build Coastguard Worker         close(statusPipe[0]);
271*35238bceSAndroid Build Coastguard Worker 
272*35238bceSAndroid Build Coastguard Worker         /* Set status pipe to close on exec(). That way parent will know that exec() succeeded. */
273*35238bceSAndroid Build Coastguard Worker         if (fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC) != 0)
274*35238bceSAndroid Build Coastguard Worker             dieLastError(statusPipe[1], "Failed to set FD_CLOEXEC");
275*35238bceSAndroid Build Coastguard Worker 
276*35238bceSAndroid Build Coastguard Worker         /* Map stdin. */
277*35238bceSAndroid Build Coastguard Worker         if (pipeIn[0] != STDIN_FILENO && dup2(pipeIn[0], STDIN_FILENO) != STDIN_FILENO)
278*35238bceSAndroid Build Coastguard Worker             dieLastError(statusPipe[1], "dup2() failed");
279*35238bceSAndroid Build Coastguard Worker         close(pipeIn[0]);
280*35238bceSAndroid Build Coastguard Worker 
281*35238bceSAndroid Build Coastguard Worker         /* Stdout. */
282*35238bceSAndroid Build Coastguard Worker         if (pipeOut[1] != STDOUT_FILENO && dup2(pipeOut[1], STDOUT_FILENO) != STDOUT_FILENO)
283*35238bceSAndroid Build Coastguard Worker             dieLastError(statusPipe[1], "dup2() failed");
284*35238bceSAndroid Build Coastguard Worker         close(pipeOut[1]);
285*35238bceSAndroid Build Coastguard Worker 
286*35238bceSAndroid Build Coastguard Worker         /* Stderr. */
287*35238bceSAndroid Build Coastguard Worker         if (pipeErr[1] != STDERR_FILENO && dup2(pipeErr[1], STDERR_FILENO) != STDERR_FILENO)
288*35238bceSAndroid Build Coastguard Worker             dieLastError(statusPipe[1], "dup2() failed");
289*35238bceSAndroid Build Coastguard Worker         close(pipeErr[1]);
290*35238bceSAndroid Build Coastguard Worker 
291*35238bceSAndroid Build Coastguard Worker         /* Doesn't return. */
292*35238bceSAndroid Build Coastguard Worker         execProcess(commandLine, workingDirectory, statusPipe[1]);
293*35238bceSAndroid Build Coastguard Worker     }
294*35238bceSAndroid Build Coastguard Worker     else
295*35238bceSAndroid Build Coastguard Worker     {
296*35238bceSAndroid Build Coastguard Worker         /* Parent process. */
297*35238bceSAndroid Build Coastguard Worker 
298*35238bceSAndroid Build Coastguard Worker         /* Check status. */
299*35238bceSAndroid Build Coastguard Worker         {
300*35238bceSAndroid Build Coastguard Worker             char errBuf[256];
301*35238bceSAndroid Build Coastguard Worker             ssize_t result = 0;
302*35238bceSAndroid Build Coastguard Worker 
303*35238bceSAndroid Build Coastguard Worker             close(statusPipe[1]);
304*35238bceSAndroid Build Coastguard Worker             while ((result = read(statusPipe[0], errBuf, 1)) == -1)
305*35238bceSAndroid Build Coastguard Worker                 if (errno != EAGAIN && errno != EINTR)
306*35238bceSAndroid Build Coastguard Worker                     break;
307*35238bceSAndroid Build Coastguard Worker 
308*35238bceSAndroid Build Coastguard Worker             if (result > 0)
309*35238bceSAndroid Build Coastguard Worker             {
310*35238bceSAndroid Build Coastguard Worker                 int procStatus = 0;
311*35238bceSAndroid Build Coastguard Worker 
312*35238bceSAndroid Build Coastguard Worker                 /* Read full error msg. */
313*35238bceSAndroid Build Coastguard Worker                 int errPos = 1;
314*35238bceSAndroid Build Coastguard Worker                 while (errPos < DE_LENGTH_OF_ARRAY(errBuf))
315*35238bceSAndroid Build Coastguard Worker                 {
316*35238bceSAndroid Build Coastguard Worker                     result = read(statusPipe[0], errBuf + errPos, 1);
317*35238bceSAndroid Build Coastguard Worker                     if (result == -1)
318*35238bceSAndroid Build Coastguard Worker                         break; /* Done. */
319*35238bceSAndroid Build Coastguard Worker 
320*35238bceSAndroid Build Coastguard Worker                     errPos += 1;
321*35238bceSAndroid Build Coastguard Worker                 }
322*35238bceSAndroid Build Coastguard Worker 
323*35238bceSAndroid Build Coastguard Worker                 /* Make sure str is null-terminated. */
324*35238bceSAndroid Build Coastguard Worker                 errBuf[errPos] = 0;
325*35238bceSAndroid Build Coastguard Worker 
326*35238bceSAndroid Build Coastguard Worker                 /* Close handles. */
327*35238bceSAndroid Build Coastguard Worker                 close(statusPipe[0]);
328*35238bceSAndroid Build Coastguard Worker                 closePipe(pipeIn);
329*35238bceSAndroid Build Coastguard Worker                 closePipe(pipeOut);
330*35238bceSAndroid Build Coastguard Worker                 closePipe(pipeErr);
331*35238bceSAndroid Build Coastguard Worker 
332*35238bceSAndroid Build Coastguard Worker                 /* Run waitpid to clean up zombie. */
333*35238bceSAndroid Build Coastguard Worker                 waitpid(pid, &procStatus, 0);
334*35238bceSAndroid Build Coastguard Worker 
335*35238bceSAndroid Build Coastguard Worker                 deProcess_setError(process, errBuf);
336*35238bceSAndroid Build Coastguard Worker 
337*35238bceSAndroid Build Coastguard Worker                 return false;
338*35238bceSAndroid Build Coastguard Worker             }
339*35238bceSAndroid Build Coastguard Worker 
340*35238bceSAndroid Build Coastguard Worker             /* Status pipe is not needed. */
341*35238bceSAndroid Build Coastguard Worker             close(statusPipe[0]);
342*35238bceSAndroid Build Coastguard Worker         }
343*35238bceSAndroid Build Coastguard Worker 
344*35238bceSAndroid Build Coastguard Worker         /* Set running state. */
345*35238bceSAndroid Build Coastguard Worker         process->pid   = pid;
346*35238bceSAndroid Build Coastguard Worker         process->state = PROCESSSTATE_RUNNING;
347*35238bceSAndroid Build Coastguard Worker 
348*35238bceSAndroid Build Coastguard Worker         /* Stdin, stdout. */
349*35238bceSAndroid Build Coastguard Worker         close(pipeIn[0]);
350*35238bceSAndroid Build Coastguard Worker         close(pipeOut[1]);
351*35238bceSAndroid Build Coastguard Worker         close(pipeErr[1]);
352*35238bceSAndroid Build Coastguard Worker 
353*35238bceSAndroid Build Coastguard Worker         process->standardIn  = deFile_createFromHandle((uintptr_t)pipeIn[1]);
354*35238bceSAndroid Build Coastguard Worker         process->standardOut = deFile_createFromHandle((uintptr_t)pipeOut[0]);
355*35238bceSAndroid Build Coastguard Worker         process->standardErr = deFile_createFromHandle((uintptr_t)pipeErr[0]);
356*35238bceSAndroid Build Coastguard Worker 
357*35238bceSAndroid Build Coastguard Worker         if (!process->standardIn)
358*35238bceSAndroid Build Coastguard Worker             close(pipeIn[1]);
359*35238bceSAndroid Build Coastguard Worker 
360*35238bceSAndroid Build Coastguard Worker         if (!process->standardOut)
361*35238bceSAndroid Build Coastguard Worker             close(pipeOut[0]);
362*35238bceSAndroid Build Coastguard Worker 
363*35238bceSAndroid Build Coastguard Worker         if (!process->standardErr)
364*35238bceSAndroid Build Coastguard Worker             close(pipeErr[0]);
365*35238bceSAndroid Build Coastguard Worker     }
366*35238bceSAndroid Build Coastguard Worker 
367*35238bceSAndroid Build Coastguard Worker     return true;
368*35238bceSAndroid Build Coastguard Worker }
369*35238bceSAndroid Build Coastguard Worker 
deProcess_isRunning(deProcess * process)370*35238bceSAndroid Build Coastguard Worker bool deProcess_isRunning(deProcess *process)
371*35238bceSAndroid Build Coastguard Worker {
372*35238bceSAndroid Build Coastguard Worker     if (process->state == PROCESSSTATE_RUNNING)
373*35238bceSAndroid Build Coastguard Worker     {
374*35238bceSAndroid Build Coastguard Worker         int status = 0;
375*35238bceSAndroid Build Coastguard Worker 
376*35238bceSAndroid Build Coastguard Worker         if (waitpid(process->pid, &status, WNOHANG) == 0)
377*35238bceSAndroid Build Coastguard Worker             return true; /* No status available. */
378*35238bceSAndroid Build Coastguard Worker 
379*35238bceSAndroid Build Coastguard Worker         if (WIFEXITED(status) || WIFSIGNALED(status))
380*35238bceSAndroid Build Coastguard Worker         {
381*35238bceSAndroid Build Coastguard Worker             /* Child has finished. */
382*35238bceSAndroid Build Coastguard Worker             process->state = PROCESSSTATE_FINISHED;
383*35238bceSAndroid Build Coastguard Worker             return false;
384*35238bceSAndroid Build Coastguard Worker         }
385*35238bceSAndroid Build Coastguard Worker         else
386*35238bceSAndroid Build Coastguard Worker             return true;
387*35238bceSAndroid Build Coastguard Worker     }
388*35238bceSAndroid Build Coastguard Worker     else
389*35238bceSAndroid Build Coastguard Worker         return false;
390*35238bceSAndroid Build Coastguard Worker }
391*35238bceSAndroid Build Coastguard Worker 
deProcess_waitForFinish(deProcess * process)392*35238bceSAndroid Build Coastguard Worker bool deProcess_waitForFinish(deProcess *process)
393*35238bceSAndroid Build Coastguard Worker {
394*35238bceSAndroid Build Coastguard Worker     int status = 0;
395*35238bceSAndroid Build Coastguard Worker     pid_t waitResult;
396*35238bceSAndroid Build Coastguard Worker 
397*35238bceSAndroid Build Coastguard Worker     if (process->state != PROCESSSTATE_RUNNING)
398*35238bceSAndroid Build Coastguard Worker     {
399*35238bceSAndroid Build Coastguard Worker         deProcess_setError(process, "Process is not running");
400*35238bceSAndroid Build Coastguard Worker         return false;
401*35238bceSAndroid Build Coastguard Worker     }
402*35238bceSAndroid Build Coastguard Worker 
403*35238bceSAndroid Build Coastguard Worker     /* \note [pyry] HACK, apparently needed by some versions of OS X. */
404*35238bceSAndroid Build Coastguard Worker     while ((waitResult = waitpid(process->pid, &status, 0)) != process->pid)
405*35238bceSAndroid Build Coastguard Worker         if (errno != ENOENT)
406*35238bceSAndroid Build Coastguard Worker             break;
407*35238bceSAndroid Build Coastguard Worker 
408*35238bceSAndroid Build Coastguard Worker     if (waitResult != process->pid)
409*35238bceSAndroid Build Coastguard Worker     {
410*35238bceSAndroid Build Coastguard Worker         deProcess_setErrorFromErrno(process, "waitpid() failed");
411*35238bceSAndroid Build Coastguard Worker         return false; /* waitpid() failed. */
412*35238bceSAndroid Build Coastguard Worker     }
413*35238bceSAndroid Build Coastguard Worker 
414*35238bceSAndroid Build Coastguard Worker     if (!WIFEXITED(status) && !WIFSIGNALED(status))
415*35238bceSAndroid Build Coastguard Worker     {
416*35238bceSAndroid Build Coastguard Worker         deProcess_setErrorFromErrno(process, "waitpid() failed");
417*35238bceSAndroid Build Coastguard Worker         return false; /* Something strange happened. */
418*35238bceSAndroid Build Coastguard Worker     }
419*35238bceSAndroid Build Coastguard Worker 
420*35238bceSAndroid Build Coastguard Worker     process->exitCode = WEXITSTATUS(status);
421*35238bceSAndroid Build Coastguard Worker     process->state    = PROCESSSTATE_FINISHED;
422*35238bceSAndroid Build Coastguard Worker     return true;
423*35238bceSAndroid Build Coastguard Worker }
424*35238bceSAndroid Build Coastguard Worker 
deProcess_sendSignal(deProcess * process,int sigNum)425*35238bceSAndroid Build Coastguard Worker static bool deProcess_sendSignal(deProcess *process, int sigNum)
426*35238bceSAndroid Build Coastguard Worker {
427*35238bceSAndroid Build Coastguard Worker     if (process->state != PROCESSSTATE_RUNNING)
428*35238bceSAndroid Build Coastguard Worker     {
429*35238bceSAndroid Build Coastguard Worker         deProcess_setError(process, "Process is not running");
430*35238bceSAndroid Build Coastguard Worker         return false;
431*35238bceSAndroid Build Coastguard Worker     }
432*35238bceSAndroid Build Coastguard Worker 
433*35238bceSAndroid Build Coastguard Worker     if (kill(process->pid, sigNum) == 0)
434*35238bceSAndroid Build Coastguard Worker         return true;
435*35238bceSAndroid Build Coastguard Worker     else
436*35238bceSAndroid Build Coastguard Worker     {
437*35238bceSAndroid Build Coastguard Worker         deProcess_setErrorFromErrno(process, "kill() failed");
438*35238bceSAndroid Build Coastguard Worker         return false;
439*35238bceSAndroid Build Coastguard Worker     }
440*35238bceSAndroid Build Coastguard Worker }
441*35238bceSAndroid Build Coastguard Worker 
deProcess_terminate(deProcess * process)442*35238bceSAndroid Build Coastguard Worker bool deProcess_terminate(deProcess *process)
443*35238bceSAndroid Build Coastguard Worker {
444*35238bceSAndroid Build Coastguard Worker     return deProcess_sendSignal(process, SIGTERM);
445*35238bceSAndroid Build Coastguard Worker }
446*35238bceSAndroid Build Coastguard Worker 
deProcess_kill(deProcess * process)447*35238bceSAndroid Build Coastguard Worker bool deProcess_kill(deProcess *process)
448*35238bceSAndroid Build Coastguard Worker {
449*35238bceSAndroid Build Coastguard Worker     return deProcess_sendSignal(process, SIGKILL);
450*35238bceSAndroid Build Coastguard Worker }
451*35238bceSAndroid Build Coastguard Worker 
deProcess_getStdIn(deProcess * process)452*35238bceSAndroid Build Coastguard Worker deFile *deProcess_getStdIn(deProcess *process)
453*35238bceSAndroid Build Coastguard Worker {
454*35238bceSAndroid Build Coastguard Worker     return process->standardIn;
455*35238bceSAndroid Build Coastguard Worker }
456*35238bceSAndroid Build Coastguard Worker 
deProcess_getStdOut(deProcess * process)457*35238bceSAndroid Build Coastguard Worker deFile *deProcess_getStdOut(deProcess *process)
458*35238bceSAndroid Build Coastguard Worker {
459*35238bceSAndroid Build Coastguard Worker     return process->standardOut;
460*35238bceSAndroid Build Coastguard Worker }
461*35238bceSAndroid Build Coastguard Worker 
deProcess_getStdErr(deProcess * process)462*35238bceSAndroid Build Coastguard Worker deFile *deProcess_getStdErr(deProcess *process)
463*35238bceSAndroid Build Coastguard Worker {
464*35238bceSAndroid Build Coastguard Worker     return process->standardErr;
465*35238bceSAndroid Build Coastguard Worker }
466*35238bceSAndroid Build Coastguard Worker 
deProcess_closeStdIn(deProcess * process)467*35238bceSAndroid Build Coastguard Worker bool deProcess_closeStdIn(deProcess *process)
468*35238bceSAndroid Build Coastguard Worker {
469*35238bceSAndroid Build Coastguard Worker     if (process->standardIn)
470*35238bceSAndroid Build Coastguard Worker     {
471*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardIn);
472*35238bceSAndroid Build Coastguard Worker         process->standardIn = DE_NULL;
473*35238bceSAndroid Build Coastguard Worker         return true;
474*35238bceSAndroid Build Coastguard Worker     }
475*35238bceSAndroid Build Coastguard Worker     else
476*35238bceSAndroid Build Coastguard Worker         return false;
477*35238bceSAndroid Build Coastguard Worker }
478*35238bceSAndroid Build Coastguard Worker 
deProcess_closeStdOut(deProcess * process)479*35238bceSAndroid Build Coastguard Worker bool deProcess_closeStdOut(deProcess *process)
480*35238bceSAndroid Build Coastguard Worker {
481*35238bceSAndroid Build Coastguard Worker     if (process->standardOut)
482*35238bceSAndroid Build Coastguard Worker     {
483*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardOut);
484*35238bceSAndroid Build Coastguard Worker         process->standardOut = DE_NULL;
485*35238bceSAndroid Build Coastguard Worker         return true;
486*35238bceSAndroid Build Coastguard Worker     }
487*35238bceSAndroid Build Coastguard Worker     else
488*35238bceSAndroid Build Coastguard Worker         return false;
489*35238bceSAndroid Build Coastguard Worker }
490*35238bceSAndroid Build Coastguard Worker 
deProcess_closeStdErr(deProcess * process)491*35238bceSAndroid Build Coastguard Worker bool deProcess_closeStdErr(deProcess *process)
492*35238bceSAndroid Build Coastguard Worker {
493*35238bceSAndroid Build Coastguard Worker     if (process->standardErr)
494*35238bceSAndroid Build Coastguard Worker     {
495*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardErr);
496*35238bceSAndroid Build Coastguard Worker         process->standardErr = DE_NULL;
497*35238bceSAndroid Build Coastguard Worker         return true;
498*35238bceSAndroid Build Coastguard Worker     }
499*35238bceSAndroid Build Coastguard Worker     else
500*35238bceSAndroid Build Coastguard Worker         return false;
501*35238bceSAndroid Build Coastguard Worker }
502*35238bceSAndroid Build Coastguard Worker 
503*35238bceSAndroid Build Coastguard Worker #elif (DE_OS == DE_OS_WIN32)
504*35238bceSAndroid Build Coastguard Worker 
505*35238bceSAndroid Build Coastguard Worker #define VC_EXTRALEAN
506*35238bceSAndroid Build Coastguard Worker #define WIN32_LEAN_AND_MEAN
507*35238bceSAndroid Build Coastguard Worker #include <windows.h>
508*35238bceSAndroid Build Coastguard Worker #include <strsafe.h>
509*35238bceSAndroid Build Coastguard Worker 
510*35238bceSAndroid Build Coastguard Worker typedef enum ProcessState_e
511*35238bceSAndroid Build Coastguard Worker {
512*35238bceSAndroid Build Coastguard Worker     PROCESSSTATE_NOT_STARTED = 0,
513*35238bceSAndroid Build Coastguard Worker     PROCESSSTATE_RUNNING,
514*35238bceSAndroid Build Coastguard Worker     PROCESSSTATE_FINISHED,
515*35238bceSAndroid Build Coastguard Worker 
516*35238bceSAndroid Build Coastguard Worker     PROCESSSTATE_LAST
517*35238bceSAndroid Build Coastguard Worker } ProcessState;
518*35238bceSAndroid Build Coastguard Worker 
519*35238bceSAndroid Build Coastguard Worker struct deProcess_s
520*35238bceSAndroid Build Coastguard Worker {
521*35238bceSAndroid Build Coastguard Worker     ProcessState state;
522*35238bceSAndroid Build Coastguard Worker     char *lastError;
523*35238bceSAndroid Build Coastguard Worker     int exitCode;
524*35238bceSAndroid Build Coastguard Worker 
525*35238bceSAndroid Build Coastguard Worker     PROCESS_INFORMATION procInfo;
526*35238bceSAndroid Build Coastguard Worker     deFile *standardIn;
527*35238bceSAndroid Build Coastguard Worker     deFile *standardOut;
528*35238bceSAndroid Build Coastguard Worker     deFile *standardErr;
529*35238bceSAndroid Build Coastguard Worker };
530*35238bceSAndroid Build Coastguard Worker 
deProcess_setError(deProcess * process,const char * error)531*35238bceSAndroid Build Coastguard Worker static bool deProcess_setError(deProcess *process, const char *error)
532*35238bceSAndroid Build Coastguard Worker {
533*35238bceSAndroid Build Coastguard Worker     if (process->lastError)
534*35238bceSAndroid Build Coastguard Worker     {
535*35238bceSAndroid Build Coastguard Worker         deFree(process->lastError);
536*35238bceSAndroid Build Coastguard Worker         process->lastError = DE_NULL;
537*35238bceSAndroid Build Coastguard Worker     }
538*35238bceSAndroid Build Coastguard Worker 
539*35238bceSAndroid Build Coastguard Worker     process->lastError = deStrdup(error);
540*35238bceSAndroid Build Coastguard Worker     return process->lastError != DE_NULL;
541*35238bceSAndroid Build Coastguard Worker }
542*35238bceSAndroid Build Coastguard Worker 
deProcess_setErrorFromWin32(deProcess * process,const char * msg)543*35238bceSAndroid Build Coastguard Worker static bool deProcess_setErrorFromWin32(deProcess *process, const char *msg)
544*35238bceSAndroid Build Coastguard Worker {
545*35238bceSAndroid Build Coastguard Worker     DWORD error = GetLastError();
546*35238bceSAndroid Build Coastguard Worker     LPSTR msgBuf;
547*35238bceSAndroid Build Coastguard Worker     char errBuf[256];
548*35238bceSAndroid Build Coastguard Worker 
549*35238bceSAndroid Build Coastguard Worker #if defined(UNICODE)
550*35238bceSAndroid Build Coastguard Worker #error Unicode not supported.
551*35238bceSAndroid Build Coastguard Worker #endif
552*35238bceSAndroid Build Coastguard Worker 
553*35238bceSAndroid Build Coastguard Worker     if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
554*35238bceSAndroid Build Coastguard Worker                       error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msgBuf, 0, DE_NULL) > 0)
555*35238bceSAndroid Build Coastguard Worker     {
556*35238bceSAndroid Build Coastguard Worker         deSprintf(errBuf, sizeof(errBuf), "%s, error %d: %s", msg, error, msgBuf);
557*35238bceSAndroid Build Coastguard Worker         LocalFree(msgBuf);
558*35238bceSAndroid Build Coastguard Worker         return deProcess_setError(process, errBuf);
559*35238bceSAndroid Build Coastguard Worker     }
560*35238bceSAndroid Build Coastguard Worker     else
561*35238bceSAndroid Build Coastguard Worker     {
562*35238bceSAndroid Build Coastguard Worker         /* Failed to get error str. */
563*35238bceSAndroid Build Coastguard Worker         deSprintf(errBuf, sizeof(errBuf), "%s, error %d", msg, error);
564*35238bceSAndroid Build Coastguard Worker         return deProcess_setError(process, errBuf);
565*35238bceSAndroid Build Coastguard Worker     }
566*35238bceSAndroid Build Coastguard Worker }
567*35238bceSAndroid Build Coastguard Worker 
deProcess_create(void)568*35238bceSAndroid Build Coastguard Worker deProcess *deProcess_create(void)
569*35238bceSAndroid Build Coastguard Worker {
570*35238bceSAndroid Build Coastguard Worker     deProcess *process = (deProcess *)deCalloc(sizeof(deProcess));
571*35238bceSAndroid Build Coastguard Worker     if (!process)
572*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
573*35238bceSAndroid Build Coastguard Worker 
574*35238bceSAndroid Build Coastguard Worker     process->state = PROCESSSTATE_NOT_STARTED;
575*35238bceSAndroid Build Coastguard Worker 
576*35238bceSAndroid Build Coastguard Worker     return process;
577*35238bceSAndroid Build Coastguard Worker }
578*35238bceSAndroid Build Coastguard Worker 
deProcess_cleanupHandles(deProcess * process)579*35238bceSAndroid Build Coastguard Worker void deProcess_cleanupHandles(deProcess *process)
580*35238bceSAndroid Build Coastguard Worker {
581*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!deProcess_isRunning(process));
582*35238bceSAndroid Build Coastguard Worker 
583*35238bceSAndroid Build Coastguard Worker     if (process->standardErr)
584*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardErr);
585*35238bceSAndroid Build Coastguard Worker 
586*35238bceSAndroid Build Coastguard Worker     if (process->standardOut)
587*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardOut);
588*35238bceSAndroid Build Coastguard Worker 
589*35238bceSAndroid Build Coastguard Worker     if (process->standardIn)
590*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardIn);
591*35238bceSAndroid Build Coastguard Worker 
592*35238bceSAndroid Build Coastguard Worker     if (process->procInfo.hProcess)
593*35238bceSAndroid Build Coastguard Worker         CloseHandle(process->procInfo.hProcess);
594*35238bceSAndroid Build Coastguard Worker 
595*35238bceSAndroid Build Coastguard Worker     if (process->procInfo.hThread)
596*35238bceSAndroid Build Coastguard Worker         CloseHandle(process->procInfo.hThread);
597*35238bceSAndroid Build Coastguard Worker 
598*35238bceSAndroid Build Coastguard Worker     process->standardErr       = DE_NULL;
599*35238bceSAndroid Build Coastguard Worker     process->standardOut       = DE_NULL;
600*35238bceSAndroid Build Coastguard Worker     process->standardIn        = DE_NULL;
601*35238bceSAndroid Build Coastguard Worker     process->procInfo.hProcess = DE_NULL;
602*35238bceSAndroid Build Coastguard Worker     process->procInfo.hThread  = DE_NULL;
603*35238bceSAndroid Build Coastguard Worker }
604*35238bceSAndroid Build Coastguard Worker 
deProcess_destroy(deProcess * process)605*35238bceSAndroid Build Coastguard Worker void deProcess_destroy(deProcess *process)
606*35238bceSAndroid Build Coastguard Worker {
607*35238bceSAndroid Build Coastguard Worker     if (deProcess_isRunning(process))
608*35238bceSAndroid Build Coastguard Worker     {
609*35238bceSAndroid Build Coastguard Worker         deProcess_kill(process);
610*35238bceSAndroid Build Coastguard Worker         deProcess_waitForFinish(process);
611*35238bceSAndroid Build Coastguard Worker     }
612*35238bceSAndroid Build Coastguard Worker 
613*35238bceSAndroid Build Coastguard Worker     deProcess_cleanupHandles(process);
614*35238bceSAndroid Build Coastguard Worker     deFree(process->lastError);
615*35238bceSAndroid Build Coastguard Worker     deFree(process);
616*35238bceSAndroid Build Coastguard Worker }
617*35238bceSAndroid Build Coastguard Worker 
deProcess_getLastError(const deProcess * process)618*35238bceSAndroid Build Coastguard Worker const char *deProcess_getLastError(const deProcess *process)
619*35238bceSAndroid Build Coastguard Worker {
620*35238bceSAndroid Build Coastguard Worker     return process->lastError ? process->lastError : "No error";
621*35238bceSAndroid Build Coastguard Worker }
622*35238bceSAndroid Build Coastguard Worker 
deProcess_getExitCode(const deProcess * process)623*35238bceSAndroid Build Coastguard Worker int deProcess_getExitCode(const deProcess *process)
624*35238bceSAndroid Build Coastguard Worker {
625*35238bceSAndroid Build Coastguard Worker     return process->exitCode;
626*35238bceSAndroid Build Coastguard Worker }
627*35238bceSAndroid Build Coastguard Worker 
deProcess_start(deProcess * process,const char * commandLine,const char * workingDirectory)628*35238bceSAndroid Build Coastguard Worker bool deProcess_start(deProcess *process, const char *commandLine, const char *workingDirectory)
629*35238bceSAndroid Build Coastguard Worker {
630*35238bceSAndroid Build Coastguard Worker     SECURITY_ATTRIBUTES securityAttr;
631*35238bceSAndroid Build Coastguard Worker     STARTUPINFO startInfo;
632*35238bceSAndroid Build Coastguard Worker 
633*35238bceSAndroid Build Coastguard Worker     /* Pipes. */
634*35238bceSAndroid Build Coastguard Worker     HANDLE stdInRead   = DE_NULL;
635*35238bceSAndroid Build Coastguard Worker     HANDLE stdInWrite  = DE_NULL;
636*35238bceSAndroid Build Coastguard Worker     HANDLE stdOutRead  = DE_NULL;
637*35238bceSAndroid Build Coastguard Worker     HANDLE stdOutWrite = DE_NULL;
638*35238bceSAndroid Build Coastguard Worker     HANDLE stdErrRead  = DE_NULL;
639*35238bceSAndroid Build Coastguard Worker     HANDLE stdErrWrite = DE_NULL;
640*35238bceSAndroid Build Coastguard Worker 
641*35238bceSAndroid Build Coastguard Worker     if (process->state == PROCESSSTATE_RUNNING)
642*35238bceSAndroid Build Coastguard Worker     {
643*35238bceSAndroid Build Coastguard Worker         deProcess_setError(process, "Process already running");
644*35238bceSAndroid Build Coastguard Worker         return false;
645*35238bceSAndroid Build Coastguard Worker     }
646*35238bceSAndroid Build Coastguard Worker     else if (process->state == PROCESSSTATE_FINISHED)
647*35238bceSAndroid Build Coastguard Worker     {
648*35238bceSAndroid Build Coastguard Worker         /* Process finished, clean up old cruft. */
649*35238bceSAndroid Build Coastguard Worker         deProcess_cleanupHandles(process);
650*35238bceSAndroid Build Coastguard Worker         process->state = PROCESSSTATE_NOT_STARTED;
651*35238bceSAndroid Build Coastguard Worker     }
652*35238bceSAndroid Build Coastguard Worker 
653*35238bceSAndroid Build Coastguard Worker     deMemset(&startInfo, 0, sizeof(startInfo));
654*35238bceSAndroid Build Coastguard Worker     deMemset(&securityAttr, 0, sizeof(securityAttr));
655*35238bceSAndroid Build Coastguard Worker 
656*35238bceSAndroid Build Coastguard Worker     /* Security attributes for inheriting handle. */
657*35238bceSAndroid Build Coastguard Worker     securityAttr.nLength              = sizeof(SECURITY_ATTRIBUTES);
658*35238bceSAndroid Build Coastguard Worker     securityAttr.bInheritHandle       = TRUE;
659*35238bceSAndroid Build Coastguard Worker     securityAttr.lpSecurityDescriptor = DE_NULL;
660*35238bceSAndroid Build Coastguard Worker 
661*35238bceSAndroid Build Coastguard Worker     /* Create pipes. \todo [2011-10-03 pyry] Clean up handles on error! */
662*35238bceSAndroid Build Coastguard Worker     if (!CreatePipe(&stdInRead, &stdInWrite, &securityAttr, 0) ||
663*35238bceSAndroid Build Coastguard Worker         !SetHandleInformation(stdInWrite, HANDLE_FLAG_INHERIT, 0))
664*35238bceSAndroid Build Coastguard Worker     {
665*35238bceSAndroid Build Coastguard Worker         deProcess_setErrorFromWin32(process, "CreatePipe() failed");
666*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdInRead);
667*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdInWrite);
668*35238bceSAndroid Build Coastguard Worker         return false;
669*35238bceSAndroid Build Coastguard Worker     }
670*35238bceSAndroid Build Coastguard Worker 
671*35238bceSAndroid Build Coastguard Worker     if (!CreatePipe(&stdOutRead, &stdOutWrite, &securityAttr, 0) ||
672*35238bceSAndroid Build Coastguard Worker         !SetHandleInformation(stdOutRead, HANDLE_FLAG_INHERIT, 0))
673*35238bceSAndroid Build Coastguard Worker     {
674*35238bceSAndroid Build Coastguard Worker         deProcess_setErrorFromWin32(process, "CreatePipe() failed");
675*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdInRead);
676*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdInWrite);
677*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdOutRead);
678*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdOutWrite);
679*35238bceSAndroid Build Coastguard Worker         return false;
680*35238bceSAndroid Build Coastguard Worker     }
681*35238bceSAndroid Build Coastguard Worker 
682*35238bceSAndroid Build Coastguard Worker     if (!CreatePipe(&stdErrRead, &stdErrWrite, &securityAttr, 0) ||
683*35238bceSAndroid Build Coastguard Worker         !SetHandleInformation(stdErrRead, HANDLE_FLAG_INHERIT, 0))
684*35238bceSAndroid Build Coastguard Worker     {
685*35238bceSAndroid Build Coastguard Worker         deProcess_setErrorFromWin32(process, "CreatePipe() failed");
686*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdInRead);
687*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdInWrite);
688*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdOutRead);
689*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdOutWrite);
690*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdErrRead);
691*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdErrWrite);
692*35238bceSAndroid Build Coastguard Worker         return false;
693*35238bceSAndroid Build Coastguard Worker     }
694*35238bceSAndroid Build Coastguard Worker 
695*35238bceSAndroid Build Coastguard Worker     /* Setup startup info. */
696*35238bceSAndroid Build Coastguard Worker     startInfo.cb         = sizeof(startInfo);
697*35238bceSAndroid Build Coastguard Worker     startInfo.hStdError  = stdErrWrite;
698*35238bceSAndroid Build Coastguard Worker     startInfo.hStdOutput = stdOutWrite;
699*35238bceSAndroid Build Coastguard Worker     startInfo.hStdInput  = stdInRead;
700*35238bceSAndroid Build Coastguard Worker     startInfo.dwFlags |= STARTF_USESTDHANDLES;
701*35238bceSAndroid Build Coastguard Worker 
702*35238bceSAndroid Build Coastguard Worker     if (!CreateProcess(DE_NULL, (LPTSTR)commandLine, DE_NULL, DE_NULL, TRUE /* inherit handles */, 0, DE_NULL,
703*35238bceSAndroid Build Coastguard Worker                        workingDirectory, &startInfo, &process->procInfo))
704*35238bceSAndroid Build Coastguard Worker     {
705*35238bceSAndroid Build Coastguard Worker         /* Store error info. */
706*35238bceSAndroid Build Coastguard Worker         deProcess_setErrorFromWin32(process, "CreateProcess() failed");
707*35238bceSAndroid Build Coastguard Worker 
708*35238bceSAndroid Build Coastguard Worker         /* Close all handles. */
709*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdInRead);
710*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdInWrite);
711*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdOutRead);
712*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdOutWrite);
713*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdErrRead);
714*35238bceSAndroid Build Coastguard Worker         CloseHandle(stdErrWrite);
715*35238bceSAndroid Build Coastguard Worker 
716*35238bceSAndroid Build Coastguard Worker         return false;
717*35238bceSAndroid Build Coastguard Worker     }
718*35238bceSAndroid Build Coastguard Worker 
719*35238bceSAndroid Build Coastguard Worker     process->state = PROCESSSTATE_RUNNING;
720*35238bceSAndroid Build Coastguard Worker 
721*35238bceSAndroid Build Coastguard Worker     /* Close our ends of handles.*/
722*35238bceSAndroid Build Coastguard Worker     CloseHandle(stdErrWrite);
723*35238bceSAndroid Build Coastguard Worker     CloseHandle(stdOutWrite);
724*35238bceSAndroid Build Coastguard Worker     CloseHandle(stdInRead);
725*35238bceSAndroid Build Coastguard Worker 
726*35238bceSAndroid Build Coastguard Worker     /* Construct stdio file objects \note May fail, not detected. */
727*35238bceSAndroid Build Coastguard Worker     process->standardIn  = deFile_createFromHandle((uintptr_t)stdInWrite);
728*35238bceSAndroid Build Coastguard Worker     process->standardOut = deFile_createFromHandle((uintptr_t)stdOutRead);
729*35238bceSAndroid Build Coastguard Worker     process->standardErr = deFile_createFromHandle((uintptr_t)stdErrRead);
730*35238bceSAndroid Build Coastguard Worker 
731*35238bceSAndroid Build Coastguard Worker     return true;
732*35238bceSAndroid Build Coastguard Worker }
733*35238bceSAndroid Build Coastguard Worker 
deProcess_isRunning(deProcess * process)734*35238bceSAndroid Build Coastguard Worker bool deProcess_isRunning(deProcess *process)
735*35238bceSAndroid Build Coastguard Worker {
736*35238bceSAndroid Build Coastguard Worker     if (process->state == PROCESSSTATE_RUNNING)
737*35238bceSAndroid Build Coastguard Worker     {
738*35238bceSAndroid Build Coastguard Worker         int exitCode;
739*35238bceSAndroid Build Coastguard Worker         BOOL result = GetExitCodeProcess(process->procInfo.hProcess, (LPDWORD)&exitCode);
740*35238bceSAndroid Build Coastguard Worker 
741*35238bceSAndroid Build Coastguard Worker         if (result != TRUE)
742*35238bceSAndroid Build Coastguard Worker         {
743*35238bceSAndroid Build Coastguard Worker             deProcess_setErrorFromWin32(process, "GetExitCodeProcess() failed");
744*35238bceSAndroid Build Coastguard Worker             return false;
745*35238bceSAndroid Build Coastguard Worker         }
746*35238bceSAndroid Build Coastguard Worker 
747*35238bceSAndroid Build Coastguard Worker         if (exitCode == STILL_ACTIVE)
748*35238bceSAndroid Build Coastguard Worker             return true;
749*35238bceSAndroid Build Coastguard Worker         else
750*35238bceSAndroid Build Coastguard Worker         {
751*35238bceSAndroid Build Coastguard Worker             /* Done. */
752*35238bceSAndroid Build Coastguard Worker             process->exitCode = exitCode;
753*35238bceSAndroid Build Coastguard Worker             process->state    = PROCESSSTATE_FINISHED;
754*35238bceSAndroid Build Coastguard Worker             return false;
755*35238bceSAndroid Build Coastguard Worker         }
756*35238bceSAndroid Build Coastguard Worker     }
757*35238bceSAndroid Build Coastguard Worker     else
758*35238bceSAndroid Build Coastguard Worker         return false;
759*35238bceSAndroid Build Coastguard Worker }
760*35238bceSAndroid Build Coastguard Worker 
deProcess_waitForFinish(deProcess * process)761*35238bceSAndroid Build Coastguard Worker bool deProcess_waitForFinish(deProcess *process)
762*35238bceSAndroid Build Coastguard Worker {
763*35238bceSAndroid Build Coastguard Worker     if (process->state == PROCESSSTATE_RUNNING)
764*35238bceSAndroid Build Coastguard Worker     {
765*35238bceSAndroid Build Coastguard Worker         if (WaitForSingleObject(process->procInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
766*35238bceSAndroid Build Coastguard Worker         {
767*35238bceSAndroid Build Coastguard Worker             deProcess_setErrorFromWin32(process, "WaitForSingleObject() failed");
768*35238bceSAndroid Build Coastguard Worker             return false;
769*35238bceSAndroid Build Coastguard Worker         }
770*35238bceSAndroid Build Coastguard Worker         return !deProcess_isRunning(process);
771*35238bceSAndroid Build Coastguard Worker     }
772*35238bceSAndroid Build Coastguard Worker     else
773*35238bceSAndroid Build Coastguard Worker     {
774*35238bceSAndroid Build Coastguard Worker         deProcess_setError(process, "Process is not running");
775*35238bceSAndroid Build Coastguard Worker         return false;
776*35238bceSAndroid Build Coastguard Worker     }
777*35238bceSAndroid Build Coastguard Worker }
778*35238bceSAndroid Build Coastguard Worker 
stopProcess(deProcess * process,bool kill)779*35238bceSAndroid Build Coastguard Worker static bool stopProcess(deProcess *process, bool kill)
780*35238bceSAndroid Build Coastguard Worker {
781*35238bceSAndroid Build Coastguard Worker     if (process->state == PROCESSSTATE_RUNNING)
782*35238bceSAndroid Build Coastguard Worker     {
783*35238bceSAndroid Build Coastguard Worker         if (!TerminateProcess(process->procInfo.hProcess, kill ? -1 : 0))
784*35238bceSAndroid Build Coastguard Worker         {
785*35238bceSAndroid Build Coastguard Worker             deProcess_setErrorFromWin32(process, "TerminateProcess() failed");
786*35238bceSAndroid Build Coastguard Worker             return false;
787*35238bceSAndroid Build Coastguard Worker         }
788*35238bceSAndroid Build Coastguard Worker         else
789*35238bceSAndroid Build Coastguard Worker             return true;
790*35238bceSAndroid Build Coastguard Worker     }
791*35238bceSAndroid Build Coastguard Worker     else
792*35238bceSAndroid Build Coastguard Worker     {
793*35238bceSAndroid Build Coastguard Worker         deProcess_setError(process, "Process is not running");
794*35238bceSAndroid Build Coastguard Worker         return false;
795*35238bceSAndroid Build Coastguard Worker     }
796*35238bceSAndroid Build Coastguard Worker }
797*35238bceSAndroid Build Coastguard Worker 
deProcess_terminate(deProcess * process)798*35238bceSAndroid Build Coastguard Worker bool deProcess_terminate(deProcess *process)
799*35238bceSAndroid Build Coastguard Worker {
800*35238bceSAndroid Build Coastguard Worker     return stopProcess(process, false);
801*35238bceSAndroid Build Coastguard Worker }
802*35238bceSAndroid Build Coastguard Worker 
deProcess_kill(deProcess * process)803*35238bceSAndroid Build Coastguard Worker bool deProcess_kill(deProcess *process)
804*35238bceSAndroid Build Coastguard Worker {
805*35238bceSAndroid Build Coastguard Worker     return stopProcess(process, true);
806*35238bceSAndroid Build Coastguard Worker }
807*35238bceSAndroid Build Coastguard Worker 
deProcess_getStdIn(deProcess * process)808*35238bceSAndroid Build Coastguard Worker deFile *deProcess_getStdIn(deProcess *process)
809*35238bceSAndroid Build Coastguard Worker {
810*35238bceSAndroid Build Coastguard Worker     return process->standardIn;
811*35238bceSAndroid Build Coastguard Worker }
812*35238bceSAndroid Build Coastguard Worker 
deProcess_getStdOut(deProcess * process)813*35238bceSAndroid Build Coastguard Worker deFile *deProcess_getStdOut(deProcess *process)
814*35238bceSAndroid Build Coastguard Worker {
815*35238bceSAndroid Build Coastguard Worker     return process->standardOut;
816*35238bceSAndroid Build Coastguard Worker }
817*35238bceSAndroid Build Coastguard Worker 
deProcess_getStdErr(deProcess * process)818*35238bceSAndroid Build Coastguard Worker deFile *deProcess_getStdErr(deProcess *process)
819*35238bceSAndroid Build Coastguard Worker {
820*35238bceSAndroid Build Coastguard Worker     return process->standardErr;
821*35238bceSAndroid Build Coastguard Worker }
822*35238bceSAndroid Build Coastguard Worker 
deProcess_closeStdIn(deProcess * process)823*35238bceSAndroid Build Coastguard Worker bool deProcess_closeStdIn(deProcess *process)
824*35238bceSAndroid Build Coastguard Worker {
825*35238bceSAndroid Build Coastguard Worker     if (process->standardIn)
826*35238bceSAndroid Build Coastguard Worker     {
827*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardIn);
828*35238bceSAndroid Build Coastguard Worker         process->standardIn = DE_NULL;
829*35238bceSAndroid Build Coastguard Worker         return true;
830*35238bceSAndroid Build Coastguard Worker     }
831*35238bceSAndroid Build Coastguard Worker     else
832*35238bceSAndroid Build Coastguard Worker         return false;
833*35238bceSAndroid Build Coastguard Worker }
834*35238bceSAndroid Build Coastguard Worker 
deProcess_closeStdOut(deProcess * process)835*35238bceSAndroid Build Coastguard Worker bool deProcess_closeStdOut(deProcess *process)
836*35238bceSAndroid Build Coastguard Worker {
837*35238bceSAndroid Build Coastguard Worker     if (process->standardOut)
838*35238bceSAndroid Build Coastguard Worker     {
839*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardOut);
840*35238bceSAndroid Build Coastguard Worker         process->standardOut = DE_NULL;
841*35238bceSAndroid Build Coastguard Worker         return true;
842*35238bceSAndroid Build Coastguard Worker     }
843*35238bceSAndroid Build Coastguard Worker     else
844*35238bceSAndroid Build Coastguard Worker         return false;
845*35238bceSAndroid Build Coastguard Worker }
846*35238bceSAndroid Build Coastguard Worker 
deProcess_closeStdErr(deProcess * process)847*35238bceSAndroid Build Coastguard Worker bool deProcess_closeStdErr(deProcess *process)
848*35238bceSAndroid Build Coastguard Worker {
849*35238bceSAndroid Build Coastguard Worker     if (process->standardErr)
850*35238bceSAndroid Build Coastguard Worker     {
851*35238bceSAndroid Build Coastguard Worker         deFile_destroy(process->standardErr);
852*35238bceSAndroid Build Coastguard Worker         process->standardErr = DE_NULL;
853*35238bceSAndroid Build Coastguard Worker         return true;
854*35238bceSAndroid Build Coastguard Worker     }
855*35238bceSAndroid Build Coastguard Worker     else
856*35238bceSAndroid Build Coastguard Worker         return false;
857*35238bceSAndroid Build Coastguard Worker }
858*35238bceSAndroid Build Coastguard Worker 
859*35238bceSAndroid Build Coastguard Worker #else
860*35238bceSAndroid Build Coastguard Worker #error Implement deProcess for your OS.
861*35238bceSAndroid Build Coastguard Worker #endif
862