static int os_exec_process_posix(const char *exe, ZigList<const char *> &args, int *return_code, Buf *out_stderr, Buf *out_stdout) { int stdin_pipe[2]; int stdout_pipe[2]; int stderr_pipe[2]; int err; if ((err = pipe(stdin_pipe))) zig_panic("pipe failed"); if ((err = pipe(stdout_pipe))) zig_panic("pipe failed"); if ((err = pipe(stderr_pipe))) zig_panic("pipe failed"); pid_t pid = fork(); if (pid == -1) zig_panic("fork failed"); if (pid == 0) { // child if (dup2(stdin_pipe[0], STDIN_FILENO) == -1) zig_panic("dup2 failed"); if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1) zig_panic("dup2 failed"); if (dup2(stderr_pipe[1], STDERR_FILENO) == -1) zig_panic("dup2 failed"); const char **argv = allocate<const char *>(args.length + 2); argv[0] = exe; argv[args.length + 1] = nullptr; for (int i = 0; i < args.length; i += 1) { argv[i + 1] = args.at(i); } execvp(exe, const_cast<char * const *>(argv)); if (errno == ENOENT) { return ErrorFileNotFound; } else { zig_panic("execvp failed: %s", strerror(errno)); } } else { // parent close(stdin_pipe[0]); close(stdout_pipe[1]); close(stderr_pipe[1]); waitpid(pid, return_code, 0); os_fetch_file(fdopen(stdout_pipe[0], "rb"), out_stdout); os_fetch_file(fdopen(stderr_pipe[0], "rb"), out_stderr); return 0; } }
static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, int *return_code) { pid_t pid = fork(); if (pid == -1) zig_panic("fork failed"); if (pid == 0) { // child const char **argv = allocate<const char *>(args.length + 2); argv[0] = exe; argv[args.length + 1] = nullptr; for (int i = 0; i < args.length; i += 1) { argv[i + 1] = args.at(i); } execvp(exe, const_cast<char * const *>(argv)); zig_panic("execvp failed: %s", strerror(errno)); } else { // parent waitpid(pid, return_code, 0); } }
static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, Termination *term) { pid_t pid = fork(); if (pid == -1) zig_panic("fork failed"); if (pid == 0) { // child const char **argv = allocate<const char *>(args.length + 2); argv[0] = exe; argv[args.length + 1] = nullptr; for (size_t i = 0; i < args.length; i += 1) { argv[i + 1] = args.at(i); } execvp(exe, const_cast<char * const *>(argv)); zig_panic("execvp failed: %s", strerror(errno)); } else { // parent int status; waitpid(pid, &status, 0); populate_termination(term, status); } }
static int os_exec_process_windows(const char *exe, ZigList<const char *> &args, int *return_code, Buf *out_stderr, Buf *out_stdout) { Buf command_line = BUF_INIT; buf_resize(&command_line, 0); buf_append_char(&command_line, '\"'); buf_append_str(&command_line, exe); buf_append_char(&command_line, '\"'); for (int arg_i = 0; arg_i < args.length; arg_i += 1) { buf_append_str(&command_line, " \""); const char *arg = args.at(arg_i); int arg_len = strlen(arg); for (int c_i = 0; c_i < arg_len; c_i += 1) { if (arg[c_i] == '\"') { zig_panic("TODO"); } buf_append_char(&command_line, arg[c_i]); } buf_append_char(&command_line, '\"'); } HANDLE g_hChildStd_IN_Rd = NULL; HANDLE g_hChildStd_IN_Wr = NULL; HANDLE g_hChildStd_OUT_Rd = NULL; HANDLE g_hChildStd_OUT_Wr = NULL; HANDLE g_hChildStd_ERR_Rd = NULL; HANDLE g_hChildStd_ERR_Wr = NULL; SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) { zig_panic("StdoutRd CreatePipe"); } if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { zig_panic("Stdout SetHandleInformation"); } if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0)) { zig_panic("stderr CreatePipe"); } if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) { zig_panic("stderr SetHandleInformation"); } if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) { zig_panic("Stdin CreatePipe"); } if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) { zig_panic("Stdin SetHandleInformation"); } PROCESS_INFORMATION piProcInfo = {0}; STARTUPINFO siStartInfo = {0}; siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = g_hChildStd_ERR_Wr; siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; siStartInfo.hStdInput = g_hChildStd_IN_Rd; siStartInfo.dwFlags |= STARTF_USESTDHANDLES; BOOL success = CreateProcess(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &siStartInfo, &piProcInfo); if (!success) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); return ErrorFileNotFound; } zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line)); } if (!CloseHandle(g_hChildStd_IN_Wr)) { zig_panic("stdinwr closehandle"); } CloseHandle(g_hChildStd_IN_Rd); CloseHandle(g_hChildStd_ERR_Wr); CloseHandle(g_hChildStd_OUT_Wr); static const int BUF_SIZE = 4 * 1024; { DWORD dwRead; char chBuf[BUF_SIZE]; buf_resize(out_stdout, 0); for (;;) { success = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUF_SIZE, &dwRead, NULL); if (!success || dwRead == 0) break; buf_append_mem(out_stdout, chBuf, dwRead); } CloseHandle(g_hChildStd_OUT_Rd); } { DWORD dwRead; char chBuf[BUF_SIZE]; buf_resize(out_stderr, 0); for (;;) { success = ReadFile( g_hChildStd_ERR_Rd, chBuf, BUF_SIZE, &dwRead, NULL); if (!success || dwRead == 0) break; buf_append_mem(out_stderr, chBuf, dwRead); } CloseHandle(g_hChildStd_ERR_Rd); } WaitForSingleObject(piProcInfo.hProcess, INFINITE); DWORD exit_code; if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) { zig_panic("GetExitCodeProcess failed"); } *return_code = exit_code; CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); return 0; }