int win32execute(char *path, char **argv, int doreturn, const char *path_stdout, const char *path_stderr) { PROCESS_INFORMATION pi; STARTUPINFO si; BOOL ret; DWORD exitcode; char *sh = NULL; char *args; memset(&pi, 0x00, sizeof(pi)); memset(&si, 0x00, sizeof(si)); sh = win32getshell(path); if (sh) path = sh; si.cb = sizeof(STARTUPINFO); if (path_stdout) { SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; si.hStdOutput = CreateFile(path_stdout, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_SEQUENTIAL_SCAN, NULL); si.hStdError = CreateFile(path_stderr, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_SEQUENTIAL_SCAN, NULL); si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.dwFlags = STARTF_USESTDHANDLES; if (si.hStdOutput == INVALID_HANDLE_VALUE || si.hStdError == INVALID_HANDLE_VALUE) return -1; } args = win32argvtos(sh, argv); ret = CreateProcess(path, args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi); free(args); if (path_stdout) { CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); } if (ret == 0) return -1; WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (!doreturn) exit(exitcode); return exitcode; }
int win32execute(char *path, char **argv, int doreturn, int fd_stdout, int fd_stderr) { PROCESS_INFORMATION pi; memset(&pi, 0x00, sizeof(pi)); STARTUPINFO si; memset(&si, 0x00, sizeof(si)); char *sh = win32getshell(path); if (sh) { path = sh; } si.cb = sizeof(STARTUPINFO); if (fd_stdout != -1) { si.hStdOutput = (HANDLE)_get_osfhandle(fd_stdout); si.hStdError = (HANDLE)_get_osfhandle(fd_stderr); si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.dwFlags = STARTF_USESTDHANDLES; if (si.hStdOutput == INVALID_HANDLE_VALUE || si.hStdError == INVALID_HANDLE_VALUE) { return -1; } } else { // Redirect subprocess stdout, stderr into current process. si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.dwFlags = STARTF_USESTDHANDLES; if (si.hStdOutput == INVALID_HANDLE_VALUE || si.hStdError == INVALID_HANDLE_VALUE) { return -1; } } char *args = win32argvtos(sh, argv); const char *ext = strrchr(path, '.'); char full_path_win_ext[MAX_PATH] = {0}; add_exe_ext_if_no_to_fullpath(full_path_win_ext, MAX_PATH, ext, path); BOOL ret = CreateProcess(full_path_win_ext, args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi); if (fd_stdout != -1) { close(fd_stdout); close(fd_stderr); } free(args); if (ret == 0) { LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); LPVOID lpDisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) __FILE__) + 200) * sizeof(TCHAR)); _snprintf((LPTSTR) lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %lu: %s"), __FILE__, dw, (const char *)lpMsgBuf); cc_log("can't execute %s; OS returned error: %s", full_path_win_ext, (char *)lpDisplayBuf); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); return -1; } WaitForSingleObject(pi.hProcess, INFINITE); DWORD exitcode; GetExitCodeProcess(pi.hProcess, &exitcode); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (!doreturn) { x_exit(exitcode); } return exitcode; }
bool hash_command_output(struct mdfour *hash, const char *command, const char *compiler) { #ifdef _WIN32 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; HANDLE pipe_out[2]; PROCESS_INFORMATION pi; STARTUPINFO si; DWORD exitcode; bool cmd = false; char *sh = NULL; char *win32args; char *path; BOOL ret; bool ok; int fd; #else pid_t pid; int pipefd[2]; #endif #ifdef _WIN32 /* trim leading space */ while (isspace(*command)) { command++; } /* add "echo" command */ if (str_startswith(command, "echo")) { command = format("cmd.exe /c \"%s\"", command); cmd = true; } else if (str_startswith(command, "%compiler%") && str_eq(compiler, "echo")) { command = format("cmd.exe /c \"%s%s\"", compiler, command + 10); cmd = true; } else { command = x_strdup(command); } #endif struct args *args = args_init_from_string(command); int i; for (i = 0; i < args->argc; i++) { if (str_eq(args->argv[i], "%compiler%")) { args_set(args, i, compiler); } } cc_log_argv("Executing compiler check command ", args->argv); #ifdef _WIN32 memset(&pi, 0x00, sizeof(pi)); memset(&si, 0x00, sizeof(si)); path = find_executable(args->argv[0], NULL); if (!path) { path = args->argv[0]; } sh = win32getshell(path); if (sh) { path = sh; } si.cb = sizeof(STARTUPINFO); CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0); SetHandleInformation(pipe_out[0], HANDLE_FLAG_INHERIT, 0); si.hStdOutput = pipe_out[1]; si.hStdError = pipe_out[1]; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.dwFlags = STARTF_USESTDHANDLES; if (!cmd) { win32args = win32argvtos(sh, args->argv); } else { win32args = (char *) command; /* quoted */ } ret = CreateProcess(path, win32args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi); CloseHandle(pipe_out[1]); args_free(args); free(win32args); if (cmd) { free((char *) command); /* original argument was replaced above */ } if (ret == 0) { stats_update(STATS_COMPCHECK); return false; } fd = _open_osfhandle((intptr_t) pipe_out[0], O_BINARY); ok = hash_fd(hash, fd); if (!ok) { cc_log("Error hashing compiler check command output: %s", strerror(errno)); stats_update(STATS_COMPCHECK); } WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); CloseHandle(pipe_out[0]); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (exitcode != 0) { cc_log("Compiler check command returned %d", (int) exitcode); stats_update(STATS_COMPCHECK); return false; } return ok; #else if (pipe(pipefd) == -1) { fatal("pipe failed"); } pid = fork(); if (pid == -1) { fatal("fork failed"); } if (pid == 0) { /* Child. */ close(pipefd[0]); close(0); dup2(pipefd[1], 1); dup2(pipefd[1], 2); _exit(execvp(args->argv[0], args->argv)); return false; /* Never reached. */ } else { /* Parent. */ int status; bool ok; args_free(args); close(pipefd[1]); ok = hash_fd(hash, pipefd[0]); if (!ok) { cc_log("Error hashing compiler check command output: %s", strerror(errno)); stats_update(STATS_COMPCHECK); } close(pipefd[0]); if (waitpid(pid, &status, 0) != pid) { cc_log("waitpid failed"); return false; } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { cc_log("Compiler check command returned %d", WEXITSTATUS(status)); stats_update(STATS_COMPCHECK); return false; } return ok; } #endif }