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