/* execute a compiler backend, capturing all output to the given paths the full path to the compiler to run is in argv[0] */ int execute(char **argv, const char *path_stdout, const char *path_stderr) { pid_t pid; int status; cc_log_argv("Executing ", argv); pid = fork(); if (pid == -1) fatal("Failed to fork: %s", strerror(errno)); if (pid == 0) { int fd; tmp_unlink(path_stdout); fd = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd == -1) { cc_log("Error creating %s: %s", path_stdout, strerror(errno)); exit(FAILED_TO_CREATE_STDOUT); } dup2(fd, 1); close(fd); tmp_unlink(path_stderr); fd = open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd == -1) { cc_log("Error creating %s: %s", path_stderr, strerror(errno)); exit(FAILED_TO_CREATE_STDERR); } dup2(fd, 2); close(fd); exit(execv(argv[0], argv)); } if (waitpid(pid, &status, 0) != pid) { fatal("waitpid failed: %s", strerror(errno)); } if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) { return -1; } if (status == FAILED_TO_CREATE_STDOUT) { fatal("Could not create %s (permission denied?)", path_stdout); } else if (status == FAILED_TO_CREATE_STDERR) { fatal("Could not create %s (permission denied?)", path_stderr); } return WEXITSTATUS(status); }
/* execute a compiler backend, capturing all output to the given paths the full path to the compiler to run is in argv[0] */ int execute(char **argv, const char *path_stdout, const char *path_stderr) { pid_t pid; int status, fd_out, fd_err; cc_log_argv("Executing ", argv); tmp_unlink(path_stdout); fd_out = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd_out == -1) { fatal("Error creating %s: %s", path_stdout, strerror(errno)); } tmp_unlink(path_stderr); fd_err = open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd_err == -1) { fatal("Error creating %s: %s", path_stderr, strerror(errno)); } pid = fork(); if (pid == -1) fatal("Failed to fork: %s", strerror(errno)); if (pid == 0) { /* Child. */ dup2(fd_out, 1); close(fd_out); dup2(fd_err, 2); close(fd_err); exit(execv(argv[0], argv)); } close(fd_out); close(fd_err); if (waitpid(pid, &status, 0) != pid) { fatal("waitpid failed: %s", strerror(errno)); } if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) { return -1; } return WEXITSTATUS(status); }
/* execute a compiler backend, capturing all output to the given paths the full path to the compiler to run is in argv[0] */ int execute(char **argv, const char *path_stdout, const char *path_stderr) { pid_t pid; int status; cc_log_argv("Executing ", argv); pid = fork(); if (pid == -1) fatal("Failed to fork"); if (pid == 0) { int fd; tmp_unlink(path_stdout); fd = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd == -1) { exit(1); } dup2(fd, 1); close(fd); tmp_unlink(path_stderr); fd = open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd == -1) { exit(1); } dup2(fd, 2); close(fd); exit(execv(argv[0], argv)); } if (waitpid(pid, &status, 0) != pid) { fatal("waitpid failed"); } if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) { return -1; } return WEXITSTATUS(status); }
/* Execute a compiler backend, capturing all output to the given paths the full * path to the compiler to run is in argv[0]. */ int execute(char **argv, int fd_out, int fd_err, pid_t *pid) { int status; cc_log_argv("Executing ", argv); block_signals(); *pid = fork(); unblock_signals(); if (*pid == -1) { fatal("Failed to fork: %s", strerror(errno)); } if (*pid == 0) { /* Child. */ dup2(fd_out, 1); close(fd_out); dup2(fd_err, 2); close(fd_err); x_exit(execv(argv[0], argv)); } close(fd_out); close(fd_err); if (waitpid(*pid, &status, 0) != *pid) { fatal("waitpid failed: %s", strerror(errno)); } block_signals(); *pid = 0; unblock_signals(); if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) { return -1; } return WEXITSTATUS(status); }
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 }