ProcHandle runInteractiveProcess (wchar_t *cmd, wchar_t *workingDirectory, void *environment, int fdStdIn, int fdStdOut, int fdStdErr, int *pfdStdInput, int *pfdStdOutput, int *pfdStdError, int close_fds) { STARTUPINFO sInfo; PROCESS_INFORMATION pInfo; HANDLE hStdInputRead = INVALID_HANDLE_VALUE; HANDLE hStdInputWrite = INVALID_HANDLE_VALUE; HANDLE hStdOutputRead = INVALID_HANDLE_VALUE; HANDLE hStdOutputWrite = INVALID_HANDLE_VALUE; HANDLE hStdErrorRead = INVALID_HANDLE_VALUE; HANDLE hStdErrorWrite = INVALID_HANDLE_VALUE; DWORD flags; BOOL status; BOOL inherit; ZeroMemory(&sInfo, sizeof(sInfo)); sInfo.cb = sizeof(sInfo); sInfo.dwFlags = STARTF_USESTDHANDLES; if (fdStdIn == -1) { if (!mkAnonPipe(&hStdInputRead, TRUE, &hStdInputWrite, FALSE)) goto cleanup_err; sInfo.hStdInput = hStdInputRead; } else if (fdStdIn == 0) { // Don't duplicate stdin, as console handles cannot be // duplicated and inherited. urg. sInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); } else { // The handle might not be inheritable, so duplicate it status = DuplicateHandle(GetCurrentProcess(), (HANDLE) _get_osfhandle(fdStdIn), GetCurrentProcess(), &hStdInputRead, 0, TRUE, /* inheritable */ DUPLICATE_SAME_ACCESS); if (!status) goto cleanup_err; sInfo.hStdInput = hStdInputRead; } if (fdStdOut == -1) { if (!mkAnonPipe(&hStdOutputRead, FALSE, &hStdOutputWrite, TRUE)) goto cleanup_err; sInfo.hStdOutput = hStdOutputWrite; } else if (fdStdOut == 1) { // Don't duplicate stdout, as console handles cannot be // duplicated and inherited. urg. sInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); } else { // The handle might not be inheritable, so duplicate it status = DuplicateHandle(GetCurrentProcess(), (HANDLE) _get_osfhandle(fdStdOut), GetCurrentProcess(), &hStdOutputWrite, 0, TRUE, /* inheritable */ DUPLICATE_SAME_ACCESS); if (!status) goto cleanup_err; sInfo.hStdOutput = hStdOutputWrite; } if (fdStdErr == -1) { if (!mkAnonPipe(&hStdErrorRead, TRUE, &hStdErrorWrite, TRUE)) goto cleanup_err; sInfo.hStdError = hStdErrorWrite; } else if (fdStdErr == 2) { // Don't duplicate stderr, as console handles cannot be // duplicated and inherited. urg. sInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); } else { /* The handle might not be inheritable, so duplicate it */ status = DuplicateHandle(GetCurrentProcess(), (HANDLE) _get_osfhandle(fdStdErr), GetCurrentProcess(), &hStdErrorWrite, 0, TRUE, /* inheritable */ DUPLICATE_SAME_ACCESS); if (!status) goto cleanup_err; sInfo.hStdError = hStdErrorWrite; } if (sInfo.hStdInput != GetStdHandle(STD_INPUT_HANDLE) && sInfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE) && sInfo.hStdError != GetStdHandle(STD_ERROR_HANDLE)) flags = CREATE_NO_WINDOW; // Run without console window only when both output and error are redirected else flags = 0; // See #3231 if (close_fds && fdStdIn == 0 && fdStdOut == 1 && fdStdErr == 2) { inherit = FALSE; } else { inherit = TRUE; } if (!CreateProcess(NULL, cmd, NULL, NULL, inherit, flags, environment, workingDirectory, &sInfo, &pInfo)) { goto cleanup_err; } CloseHandle(pInfo.hThread); // Close the ends of the pipes that were inherited by the // child process. This is important, otherwise we won't see // EOF on these pipes when the child process exits. if (hStdInputRead != INVALID_HANDLE_VALUE) CloseHandle(hStdInputRead); if (hStdOutputWrite != INVALID_HANDLE_VALUE) CloseHandle(hStdOutputWrite); if (hStdErrorWrite != INVALID_HANDLE_VALUE) CloseHandle(hStdErrorWrite); *pfdStdInput = _open_osfhandle((intptr_t) hStdInputWrite, _O_WRONLY); *pfdStdOutput = _open_osfhandle((intptr_t) hStdOutputRead, _O_RDONLY); *pfdStdError = _open_osfhandle((intptr_t) hStdErrorRead, _O_RDONLY); return (int) pInfo.hProcess; cleanup_err: if (hStdInputRead != INVALID_HANDLE_VALUE) CloseHandle(hStdInputRead); if (hStdInputWrite != INVALID_HANDLE_VALUE) CloseHandle(hStdInputWrite); if (hStdOutputRead != INVALID_HANDLE_VALUE) CloseHandle(hStdOutputRead); if (hStdOutputWrite != INVALID_HANDLE_VALUE) CloseHandle(hStdOutputWrite); if (hStdErrorRead != INVALID_HANDLE_VALUE) CloseHandle(hStdErrorRead); if (hStdErrorWrite != INVALID_HANDLE_VALUE) CloseHandle(hStdErrorWrite); maperrno(); return -1; }
ProcHandle runInteractiveProcess (char *cmd, char *workingDirectory, void *environment, int *pfdStdInput, int *pfdStdOutput, int *pfdStdError) { STARTUPINFO sInfo; PROCESS_INFORMATION pInfo; HANDLE hStdInputRead, hStdInputWrite; HANDLE hStdOutputRead, hStdOutputWrite; HANDLE hStdErrorRead, hStdErrorWrite; if (!mkAnonPipe(&hStdInputRead, TRUE, &hStdInputWrite, FALSE)) return -1; if (!mkAnonPipe(&hStdOutputRead, FALSE, &hStdOutputWrite, TRUE)) { CloseHandle(hStdInputRead); CloseHandle(hStdInputWrite); return -1; } if (!mkAnonPipe(&hStdErrorRead, FALSE, &hStdErrorWrite, TRUE)) { CloseHandle(hStdInputRead); CloseHandle(hStdInputWrite); CloseHandle(hStdOutputRead); CloseHandle(hStdOutputWrite); return -1; } ZeroMemory(&sInfo, sizeof(sInfo)); sInfo.cb = sizeof(sInfo); sInfo.dwFlags = STARTF_USESTDHANDLES; sInfo.hStdInput = hStdInputRead; sInfo.hStdOutput= hStdOutputWrite; sInfo.hStdError = hStdErrorWrite; if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, environment, workingDirectory, &sInfo, &pInfo)) { maperrno(); CloseHandle(hStdInputRead); CloseHandle(hStdInputWrite); CloseHandle(hStdOutputRead); CloseHandle(hStdOutputWrite); CloseHandle(hStdErrorRead); CloseHandle(hStdErrorWrite); return -1; } CloseHandle(pInfo.hThread); // Close the ends of the pipes that were inherited by the // child process. This is important, otherwise we won't see // EOF on these pipes when the child process exits. CloseHandle(hStdInputRead); CloseHandle(hStdOutputWrite); CloseHandle(hStdErrorWrite); *pfdStdInput = _open_osfhandle((intptr_t) hStdInputWrite, _O_WRONLY); *pfdStdOutput = _open_osfhandle((intptr_t) hStdOutputRead, _O_RDONLY); *pfdStdError = _open_osfhandle((intptr_t) hStdErrorRead, _O_RDONLY); return (int) pInfo.hProcess; }