#include "Utilities.h" #include #include #include #include #include #include namespace fs = boost::filesystem; using std::string; using std::vector; int ChildProcess(string program, vector args, int timeout) { std::vector argv; argv.push_back(program.c_str()); for(string& s : args) argv.push_back(s.c_str()); argv.push_back(NULL); pid_t pid = fork(); if(pid < 0) { perror("unable to fork"); return 1; } else if(pid == 0) { pid_t worker_pid = timeout ? fork() : 0; if(worker_pid < 0) { perror("unable to fork"); _exit(1); } if(worker_pid == 0) { execvp(argv[0], const_cast (argv.data())); perror("exec failed"); std::cerr << "Tried to execute: " << program; for(auto a : args) std::cerr << " " << a; std::cerr << std::endl; _exit(1); } pid_t timeout_pid = fork(); if(timeout_pid < 0) { perror("unable to fork"); _exit(1); } if(timeout_pid == 0) { sleep(timeout); _exit(0); } int wstatus; pid_t exited_pid = wait(&wstatus); if(exited_pid == worker_pid) { kill(timeout_pid, SIGKILL); wait(NULL); if(!WIFEXITED(wstatus)) { return 1; } else { int exitcode = WEXITSTATUS(wstatus); _exit(exitcode); } } else { kill(worker_pid, SIGKILL); wait(NULL); _exit(1); } } else { int wstatus; int result = 0; do { result = waitpid(pid, &wstatus, 0); } while(result == -1 && errno == EINTR); if(!WIFEXITED(wstatus)) { return 1; } else { int exitcode = WEXITSTATUS(wstatus); return exitcode; } } } bool CheckExecutable(std::string program) { if(access(program.c_str(), X_OK) == 0) return true; if(program.find("/") != std::string::npos) return false; const char *PATH = getenv("PATH"); if(PATH) { bool endFound = false; do { const char *end = strchr(PATH, ':'); if(!end) { end = strchr(PATH, '\0'); endFound = true; } std::string pathElement(PATH, end); if(pathElement == "") pathElement = "."; fs::path f = fs::path(pathElement) / program; if(access(f.string().c_str(), X_OK) == 0) return true; PATH = end + 1; } while(!endFound); } return false; } vector SplitArguments(std::string str) { bool backslash = false; bool quote = false; bool begun = false; vector args; for(char c : str) { if(!backslash && !quote && isspace(c)) { begun = false; } else if(!backslash && c == '"') { quote = !quote; if(quote && !begun) { args.emplace_back(); begun = true; } } else if(!backslash && c == '\\') { backslash = true; } else { backslash = false; if(!begun) { args.emplace_back(); begun = true; } args.back() += c; } } return args; } vector SplitArguments(vector strs) { vector args; for(string str : strs) { vector args1 = SplitArguments(str); args.insert(args.end(), args1.begin(), args1.end()); } return args; }