13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Utility Library
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ----------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Process abstraction.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deProcess.h"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN)
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deCommandLine.h"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sys/types.h>
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sys/wait.h>
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <unistd.h>
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <stdlib.h>
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <signal.h>
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <fcntl.h>
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <errno.h>
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef enum ProcessState_e
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PROCESSSTATE_NOT_STARTED = 0,
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PROCESSSTATE_RUNNING,
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PROCESSSTATE_FINISHED,
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PROCESSSTATE_LAST
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} ProcessState;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct deProcess_s
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProcessState	state;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				exitCode;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char*			lastError;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pid_t			pid;
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFile*			standardIn;
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFile*			standardOut;
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFile*			standardErr;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void die (int statusPipe, const char* message)
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int msgLen = strlen(message);
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int res = 0;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	printf("Process launch failed: %s\n", message);
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res = (int)write(statusPipe, message, msgLen+1);
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(res); /* No need to check result. */
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	exit(-1);
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void dieLastError (int statusPipe, const char* message)
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char	msgBuf[256];
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		lastErr	= errno;
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSprintf(msgBuf, sizeof(msgBuf), "%s, error %d: %s", message, lastErr, strerror(lastErr));
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	die(statusPipe, msgBuf);
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDE_INLINE deBool beginsWithPath (const char* fileName, const char* pathPrefix)
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int pathLen = strlen(pathPrefix);
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Strip trailing / */
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (pathLen > 0 && pathPrefix[pathLen-1] == '/')
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pathLen -= 1;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pathLen > 0 && deMemoryEqual(fileName, pathPrefix, pathLen) && fileName[pathLen] == '/';
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void stripLeadingPath (char* fileName, const char* pathPrefix)
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int pathLen		= strlen(pathPrefix);
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int fileNameLen	= strlen(fileName);
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(beginsWithPath(fileName, pathPrefix));
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Strip trailing / */
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (pathLen > 0 && pathPrefix[pathLen-1] == '/')
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pathLen -= 1;
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(pathLen > 0);
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(fileName[pathLen] == '/');
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	memmove(&fileName[0], &fileName[0]+pathLen+1, fileNameLen-pathLen);
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* Doesn't return on success. */
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void execProcess (const char* commandLine, const char* workingDirectory, int statusPipe)
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deCommandLine*	cmdLine		= deCommandLine_parse(commandLine);
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char**			argList		= cmdLine ? (char**)deCalloc(sizeof(char*)*(cmdLine->numArgs+1)) : DE_NULL;
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!cmdLine || !argList)
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		die(statusPipe, "Command line parsing failed (out of memory)");
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (workingDirectory && chdir(workingDirectory) != 0)
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dieLastError(statusPipe, "chdir() failed");
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int argNdx;
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (argNdx = 0; argNdx < cmdLine->numArgs; argNdx++)
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			argList[argNdx] = cmdLine->args[argNdx];
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		argList[argNdx] = DE_NULL; /* Terminate with 0. */
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (workingDirectory && beginsWithPath(argList[0], workingDirectory))
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		stripLeadingPath(argList[0], workingDirectory);
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	execv(argList[0], argList);
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Failed. */
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dieLastError(statusPipe, "execv() failed");
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1353c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeProcess* deProcess_create (void)
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deProcess* process = (deProcess*)deCalloc(sizeof(deProcess));
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!process)
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->state = PROCESSSTATE_NOT_STARTED;
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process;
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void deProcess_cleanupHandles (deProcess* process)
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardIn)
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardIn);
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardOut)
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardOut);
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardErr)
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardErr);
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->pid			= 0;
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->standardIn		= DE_NULL;
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->standardOut	= DE_NULL;
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->standardErr	= DE_NULL;
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deProcess_destroy (deProcess* process)
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Never leave child processes running. Otherwise we'll have zombies. */
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (deProcess_isRunning(process))
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_kill(process);
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_waitForFinish(process);
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deProcess_cleanupHandles(process);
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(process->lastError);
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(process);
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* deProcess_getLastError (const deProcess* process)
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->lastError ? process->lastError : "No error";
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deProcess_getExitCode (const deProcess* process)
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->exitCode;
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool deProcess_setError (deProcess* process, const char* error)
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->lastError)
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFree(process->lastError);
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->lastError = DE_NULL;
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->lastError = deStrdup(error);
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->lastError != DE_NULL;
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool deProcess_setErrorFromErrno (deProcess* process, const char* message)
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char	msgBuf[256];
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		lastErr		= errno;
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSprintf(msgBuf, sizeof(msgBuf), "%s, error %d: %s", message, lastErr, strerror(lastErr));
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deProcess_setError(process, message);
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void closePipe (int p[2])
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (p[0] >= 0)
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(p[0]);
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (p[1] >= 0)
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(p[1]);
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2153c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_start (deProcess* process, const char* commandLine, const char* workingDirectory)
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pid_t		pid				= 0;
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			pipeIn[2]		= { -1, -1 };
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			pipeOut[2]		= { -1, -1 };
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			pipeErr[2]		= { -1, -1 };
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			statusPipe[2]	= { -1, -1 };
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->state == PROCESSSTATE_RUNNING)
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setError(process, "Process already running");
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (process->state == PROCESSSTATE_FINISHED)
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_cleanupHandles(process);
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->state = PROCESSSTATE_NOT_STARTED;
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pipe(pipeIn) < 0 || pipe(pipeOut) < 0 || pipe(pipeErr) < 0 || pipe(statusPipe) < 0)
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setErrorFromErrno(process, "pipe() failed");
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		closePipe(pipeIn);
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		closePipe(pipeOut);
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		closePipe(pipeErr);
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		closePipe(statusPipe);
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pid = fork();
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pid < 0)
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setErrorFromErrno(process, "fork() failed");
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		closePipe(pipeIn);
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		closePipe(pipeOut);
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		closePipe(pipeErr);
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		closePipe(statusPipe);
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pid == 0)
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Child process. */
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Close unused endpoints. */
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(pipeIn[1]);
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(pipeOut[0]);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(pipeErr[0]);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(statusPipe[0]);
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Set status pipe to close on exec(). That way parent will know that exec() succeeded. */
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC) != 0)
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dieLastError(statusPipe[1], "Failed to set FD_CLOEXEC");
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Map stdin. */
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pipeIn[0] != STDIN_FILENO &&
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dup2(pipeIn[0], STDIN_FILENO) != STDIN_FILENO)
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dieLastError(statusPipe[1], "dup2() failed");
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(pipeIn[0]);
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Stdout. */
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pipeOut[1] != STDOUT_FILENO &&
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dup2(pipeOut[1], STDOUT_FILENO) != STDOUT_FILENO)
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dieLastError(statusPipe[1], "dup2() failed");
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(pipeOut[1]);
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Stderr. */
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pipeErr[1] != STDERR_FILENO &&
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dup2(pipeErr[1], STDERR_FILENO) != STDERR_FILENO)
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dieLastError(statusPipe[1], "dup2() failed");
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(pipeErr[1]);
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Doesn't return. */
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		execProcess(commandLine, workingDirectory, statusPipe[1]);
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Parent process. */
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Check status. */
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			char	errBuf[256];
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		result	= 0;
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			close(statusPipe[1]);
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			while ((result = read(statusPipe[0], errBuf, 1)) == -1)
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (errno != EAGAIN && errno != EINTR) break;
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (result > 0)
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				/* Read full error msg. */
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int errPos = 1;
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				while (errPos < DE_LENGTH_OF_ARRAY(errBuf))
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					result = read(statusPipe[0], errBuf+errPos, 1);
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (result == -1)
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break; /* Done. */
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errPos += 1;
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				/* Make sure str is null-terminated. */
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				errBuf[errPos] = 0;
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				/* Close handles. */
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				close(statusPipe[0]);
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				closePipe(pipeIn);
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				closePipe(pipeOut);
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				closePipe(pipeErr);
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				/* Run waitpid to clean up zombie. */
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				waitpid(pid, &result, 0);
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deProcess_setError(process, errBuf);
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return DE_FALSE;
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			/* Status pipe is not needed. */
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			close(statusPipe[0]);
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Set running state. */
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->pid		= pid;
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->state		= PROCESSSTATE_RUNNING;
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Stdin, stdout. */
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(pipeIn[0]);
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(pipeOut[1]);
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(pipeErr[1]);
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->standardIn		= deFile_createFromHandle(pipeIn[1]);
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->standardOut	= deFile_createFromHandle(pipeOut[0]);
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->standardErr	= deFile_createFromHandle(pipeErr[0]);
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!process->standardIn)
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			close(pipeIn[1]);
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!process->standardOut)
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			close(pipeOut[0]);
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!process->standardErr)
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			close(pipeErr[0]);
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3683c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_isRunning (deProcess* process)
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->state == PROCESSSTATE_RUNNING)
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int status = 0;
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (waitpid(process->pid, &status, WNOHANG) == 0)
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_TRUE; /* No status available. */
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (WIFEXITED(status) || WIFSIGNALED(status))
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			/* Child has finished. */
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			process->state = PROCESSSTATE_FINISHED;
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_TRUE;
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3903c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_waitForFinish (deProcess* process)
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		status = 0;
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pid_t	waitResult;
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->state != PROCESSSTATE_RUNNING)
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setError(process, "Process is not running");
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* \note [pyry] Crazy hack for OS X Lion. Stupid Apple. */
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while ((waitResult = waitpid(process->pid, &status, 0)) != process->pid)
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (errno != ENOENT) break;
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (waitResult != process->pid)
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setErrorFromErrno(process, "waitpid() failed");
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE; /* waitpid() failed. */
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!WIFEXITED(status) && !WIFSIGNALED(status))
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setErrorFromErrno(process, "waitpid() failed");
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE; /* Something strange happened. */
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->exitCode	= WEXITSTATUS(status);
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->state		= PROCESSSTATE_FINISHED;
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool deProcess_sendSignal (deProcess* process, int sigNum)
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->state != PROCESSSTATE_RUNNING)
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setError(process, "Process is not running");
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (kill(process->pid, sigNum) == 0)
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_TRUE;
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setErrorFromErrno(process, "kill() failed");
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4393c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_terminate (deProcess* process)
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deProcess_sendSignal(process, SIGTERM);
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4443c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_kill (deProcess* process)
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deProcess_sendSignal(process, SIGKILL);
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4493c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeFile* deProcess_getStdIn (deProcess* process)
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->standardIn;
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4543c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeFile* deProcess_getStdOut (deProcess* process)
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->standardOut;
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4593c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeFile* deProcess_getStdErr (deProcess* process)
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->standardErr;
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_closeStdIn (deProcess* process)
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardIn)
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardIn);
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->standardIn	= DE_NULL;
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_TRUE;
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4763c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_closeStdOut (deProcess* process)
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardOut)
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardOut);
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->standardOut = DE_NULL;
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_TRUE;
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4883c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_closeStdErr (deProcess* process)
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardErr)
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardErr);
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->standardErr = DE_NULL;
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_TRUE;
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#elif (DE_OS == DE_OS_WIN32)
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define VC_EXTRALEAN
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define WIN32_LEAN_AND_MEAN
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <windows.h>
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <strsafe.h>
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef enum ProcessState_e
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PROCESSSTATE_NOT_STARTED = 0,
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PROCESSSTATE_RUNNING,
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PROCESSSTATE_FINISHED,
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PROCESSSTATE_LAST
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} ProcessState;
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct deProcess_s
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ProcessState			state;
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char*					lastError;
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						exitCode;
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PROCESS_INFORMATION		procInfo;
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFile*					standardIn;
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFile*					standardOut;
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFile*					standardErr;
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool deProcess_setError (deProcess* process, const char* error)
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->lastError)
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFree(process->lastError);
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->lastError = DE_NULL;
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->lastError = deStrdup(error);
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->lastError != DE_NULL;
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool deProcess_setErrorFromWin32 (deProcess* process, const char* msg)
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DWORD		error	= GetLastError();
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LPSTR		msgBuf;
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char		errBuf[256];
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(UNICODE)
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	error Unicode not supported.
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msgBuf, 0, DE_NULL) > 0)
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSprintf(errBuf, sizeof(errBuf), "%s, error %d: %s", msg, error, msgBuf);
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		LocalFree(msgBuf);
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return deProcess_setError(process, errBuf);
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Failed to get error str. */
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSprintf(errBuf, sizeof(errBuf), "%s, error %d", msg, error);
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return deProcess_setError(process, errBuf);
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5653c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeProcess* deProcess_create (void)
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deProcess* process = (deProcess*)deCalloc(sizeof(deProcess));
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!process)
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->state = PROCESSSTATE_NOT_STARTED;
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process;
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deProcess_cleanupHandles (deProcess* process)
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!deProcess_isRunning(process));
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardErr)
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardErr);
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardOut)
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardOut);
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardIn)
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardIn);
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->procInfo.hProcess)
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(process->procInfo.hProcess);
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->procInfo.hThread)
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(process->procInfo.hThread);
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->standardErr		= DE_NULL;
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->standardOut		= DE_NULL;
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->standardIn			= DE_NULL;
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->procInfo.hProcess	= DE_NULL;
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->procInfo.hThread	= DE_NULL;
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deProcess_destroy (deProcess* process)
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (deProcess_isRunning(process))
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_kill(process);
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_waitForFinish(process);
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deProcess_cleanupHandles(process);
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(process->lastError);
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(process);
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* deProcess_getLastError (const deProcess* process)
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->lastError ? process->lastError : "No error";
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deProcess_getExitCode (const deProcess* process)
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->exitCode;
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6253c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_start (deProcess* process, const char* commandLine, const char* workingDirectory)
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SECURITY_ATTRIBUTES	securityAttr;
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	STARTUPINFO			startInfo;
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Pipes. */
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdInRead	= DE_NULL;
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdInWrite	= DE_NULL;
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdOutRead	= DE_NULL;
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdOutWrite	= DE_NULL;
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdErrRead	= DE_NULL;
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdErrWrite	= DE_NULL;
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->state == PROCESSSTATE_RUNNING)
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setError(process, "Process already running");
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (process->state == PROCESSSTATE_FINISHED)
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Process finished, clean up old cruft. */
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_cleanupHandles(process);
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->state = PROCESSSTATE_NOT_STARTED;
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemset(&startInfo, 0, sizeof(startInfo));
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemset(&securityAttr, 0, sizeof(securityAttr));
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Security attributes for inheriting handle. */
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	securityAttr.nLength				= sizeof(SECURITY_ATTRIBUTES);
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	securityAttr.bInheritHandle			= TRUE;
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	securityAttr.lpSecurityDescriptor	= DE_NULL;
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Create pipes. \todo [2011-10-03 pyry] Clean up handles on error! */
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!CreatePipe(&stdInRead, &stdInWrite, &securityAttr, 0) ||
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!SetHandleInformation(stdInWrite, HANDLE_FLAG_INHERIT, 0))
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setErrorFromWin32(process, "CreatePipe() failed");
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdInRead);
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdInWrite);
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!CreatePipe(&stdOutRead, &stdOutWrite, &securityAttr, 0) ||
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!SetHandleInformation(stdOutRead, HANDLE_FLAG_INHERIT, 0))
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setErrorFromWin32(process, "CreatePipe() failed");
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdInRead);
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdInWrite);
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdOutRead);
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdOutWrite);
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!CreatePipe(&stdErrRead, &stdErrWrite, &securityAttr, 0) ||
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!SetHandleInformation(stdErrRead, HANDLE_FLAG_INHERIT, 0))
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setErrorFromWin32(process, "CreatePipe() failed");
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdInRead);
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdInWrite);
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdOutRead);
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdOutWrite);
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdErrRead);
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdErrWrite);
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Setup startup info. */
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	startInfo.cb = sizeof(startInfo);
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	startInfo.hStdError		 = stdErrWrite;
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	startInfo.hStdOutput	 = stdOutWrite;
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	startInfo.hStdInput		 = stdInRead;
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	startInfo.dwFlags		|= STARTF_USESTDHANDLES;
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!CreateProcess(DE_NULL, (LPTSTR)commandLine, DE_NULL, DE_NULL, TRUE /* inherit handles */, 0, DE_NULL, workingDirectory, &startInfo, &process->procInfo))
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Store error info. */
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setErrorFromWin32(process, "CreateProcess() failed");
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Close all handles. */
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdInRead);
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdInWrite);
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdOutRead);
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdOutWrite);
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdErrRead);
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(stdErrWrite);
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->state = PROCESSSTATE_RUNNING;
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Close our ends of handles.*/
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CloseHandle(stdErrWrite);
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CloseHandle(stdOutWrite);
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CloseHandle(stdInRead);
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Construct stdio file objects \note May fail, not detected. */
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->standardIn		= deFile_createFromHandle((deUintptr)stdInWrite);
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->standardOut	= deFile_createFromHandle((deUintptr)stdOutRead);
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	process->standardErr	= deFile_createFromHandle((deUintptr)stdErrRead);
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7303c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_isRunning (deProcess* process)
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->state == PROCESSSTATE_RUNNING)
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int exitCode;
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BOOL result = GetExitCodeProcess(process->procInfo.hProcess, (LPDWORD)&exitCode);
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (result != TRUE)
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deProcess_setErrorFromWin32(process, "GetExitCodeProcess() failed");
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (exitCode == STILL_ACTIVE)
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_TRUE;
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			/* Done. */
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			process->exitCode	= exitCode;
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			process->state		= PROCESSSTATE_FINISHED;
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7573c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_waitForFinish (deProcess* process)
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->state == PROCESSSTATE_RUNNING)
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (WaitForSingleObject(process->procInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deProcess_setErrorFromWin32(process, "WaitForSingleObject() failed");
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return !deProcess_isRunning(process);
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setError(process, "Process is not running");
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool stopProcess (deProcess* process, deBool kill)
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->state == PROCESSSTATE_RUNNING)
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!TerminateProcess(process->procInfo.hProcess, kill ? -1 : 0))
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deProcess_setErrorFromWin32(process, "TerminateProcess() failed");
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_TRUE;
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deProcess_setError(process, "Process is not running");
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7943c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_terminate (deProcess* process)
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return stopProcess(process, DE_FALSE);
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7993c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_kill (deProcess* process)
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return stopProcess(process, DE_TRUE);
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8043c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeFile* deProcess_getStdIn (deProcess* process)
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->standardIn;
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8093c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeFile* deProcess_getStdOut (deProcess* process)
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->standardOut;
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8143c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeFile* deProcess_getStdErr (deProcess* process)
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return process->standardErr;
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8193c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_closeStdIn (deProcess* process)
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardIn)
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardIn);
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->standardIn	= DE_NULL;
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_TRUE;
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8313c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_closeStdOut (deProcess* process)
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardOut)
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardOut);
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->standardOut = DE_NULL;
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_TRUE;
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8433c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deProcess_closeStdErr (deProcess* process)
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (process->standardErr)
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFile_destroy(process->standardErr);
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		process->standardErr = DE_NULL;
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_TRUE;
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	error Implement deProcess for your OS.
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
858