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