From bc6785fcee3a0da64e2dfb92841de3c75f2d12d9 Mon Sep 17 00:00:00 2001 From: eidheim Date: Fri, 28 Aug 2015 08:10:23 +0200 Subject: [PATCH] Some cleanup. --- src/cmake.cc | 1 - src/terminal.cc | 98 ++++++++++++++++++++++----------------------- src/terminal_win.cc | 17 ++++---- src/window.cc | 3 -- 4 files changed, 57 insertions(+), 62 deletions(-) diff --git a/src/cmake.cc b/src/cmake.cc index 521eefa..d112a26 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -46,7 +46,6 @@ CMake::CMake(const boost::filesystem::path &path) { bool CMake::create_compile_commands(const boost::filesystem::path &path) { Singleton::terminal()->print("Creating "+path.string()+"/compile_commands.json\n"); - //TODO: Windows... if(Singleton::terminal()->execute(Singleton::Config::terminal()->cmake_command+" . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", path)==EXIT_SUCCESS) { #ifdef _WIN32 //Temporary fix to MSYS2's libclang auto compile_commands_path=path; diff --git a/src/terminal.cc b/src/terminal.cc index 4df8e24..aed5906 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -8,57 +8,74 @@ #include //TODO: remove using namespace std; //TODO: remove -//TODO: Windows... //A working implementation of popen3, with all pipes getting closed properly. //TODO: Eidheim is going to publish this one on his github, along with example uses -pid_t popen3(const char *command, int &stdin_fd, int &stdout_fd, int &stderr_fd) { +pid_t popen3(const std::string &command, const std::string &path, int *stdin_fd, int *stdout_fd, int *stderr_fd) { pid_t pid; - int p_stdin[2], p_stdout[2], p_stderr[2]; + int stdin_p[2], stdout_p[2], stderr_p[2]; - if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0 || pipe(p_stderr) != 0) { - close(p_stdin[0]); - close(p_stdout[0]); - close(p_stderr[0]); - close(p_stdin[1]); - close(p_stdout[1]); - close(p_stderr[1]); + if(stdin_fd!=nullptr && pipe(stdin_p)!=0) { + close(stdin_p[0]); + close(stdin_p[1]); return -1; } - + if(stdout_fd!=nullptr && pipe(stdout_p)!=0) { + if(stdin_fd!=nullptr) close(stdin_p[0]); + if(stdin_fd!=nullptr) close(stdin_p[1]); + close(stdout_p[0]); + close(stdout_p[1]); + return -1; + } + if(stderr_fd!=nullptr && pipe(stderr_p)!=0) { + if(stdin_fd!=nullptr) close(stdin_p[0]); + if(stdin_fd!=nullptr) close(stdin_p[1]); + if(stdout_fd!=nullptr) close(stdout_p[0]); + if(stdout_fd!=nullptr) close(stdout_p[1]); + close(stderr_p[0]); + close(stderr_p[1]); + return -1; + } + pid = fork(); if (pid < 0) { - close(p_stdin[0]); - close(p_stdout[0]); - close(p_stderr[0]); - close(p_stdin[1]); - close(p_stdout[1]); - close(p_stderr[1]); + if(stdin_fd!=nullptr) close(stdin_p[0]); + if(stdin_fd!=nullptr) close(stdin_p[1]); + if(stdout_fd!=nullptr) close(stdout_p[0]); + if(stdout_fd!=nullptr) close(stdout_p[1]); + if(stderr_fd!=nullptr) close(stderr_p[0]); + if(stderr_fd!=nullptr) close(stderr_p[1]); return pid; } else if (pid == 0) { - close(p_stdin[1]); - close(p_stdout[0]); - close(p_stderr[0]); - dup2(p_stdin[0], 0); - dup2(p_stdout[1], 1); - dup2(p_stderr[1], 2); + if(stdin_fd!=nullptr) close(stdin_p[1]); + if(stdout_fd!=nullptr) close(stdout_p[0]); + if(stderr_fd!=nullptr) close(stderr_p[0]); + if(stdin_fd!=nullptr) dup2(stdin_p[0], 0); + if(stdout_fd!=nullptr) dup2(stdout_p[1], 1); + if(stderr_fd!=nullptr) dup2(stderr_p[1], 2); setpgid(0, 0); //TODO: See here on how to emulate tty for colors: http://stackoverflow.com/questions/1401002/trick-an-application-into-thinking-its-stdin-is-interactive-not-a-pipe //TODO: One solution is: echo "command;exit"|script -q /dev/null - execl("/bin/sh", "sh", "-c", command, NULL); + std::string cd_path_and_command; + if(path!="") { + cd_path_and_command="cd \""+path+"\" && "+command; + } + else + cd_path_and_command=command; + execl("/bin/sh", "sh", "-c", cd_path_and_command.c_str(), NULL); perror("execl"); exit(EXIT_FAILURE); } - close(p_stdin[0]); - close(p_stdout[1]); - close(p_stderr[1]); + if(stdin_fd!=nullptr) close(stdin_p[0]); + if(stdout_fd!=nullptr) close(stdout_p[1]); + if(stderr_fd!=nullptr) close(stderr_p[1]); - stdin_fd = p_stdin[1]; - stdout_fd = p_stdout[0]; - stderr_fd = p_stderr[0]; + if(stdin_fd!=nullptr) *stdin_fd = stdin_p[1]; + if(stdout_fd!=nullptr) *stdout_fd = stdout_p[0]; + if(stderr_fd!=nullptr) *stderr_fd = stderr_p[0]; return pid; } @@ -137,16 +154,8 @@ Terminal::Terminal() { } int Terminal::execute(const std::string &command, const boost::filesystem::path &path) { - std::string cd_path_and_command; - if(path!="") { - //TODO: Windows... - cd_path_and_command="cd \""+path.string()+"\" && "+command; - } - else - cd_path_and_command=command; - int stdin_fd, stdout_fd, stderr_fd; - auto pid=popen3(cd_path_and_command.c_str(), stdin_fd, stdout_fd, stderr_fd); + auto pid=popen3(command, path.string(), &stdin_fd, &stdout_fd, &stderr_fd); if (pid<=0) { async_print("Error: Failed to run command: " + command + "\n"); @@ -189,19 +198,10 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path void Terminal::async_execute(const std::string &command, const boost::filesystem::path &path, std::function callback) { std::thread async_execute_thread([this, command, path, callback](){ - std::string cd_path_and_command; - if(path!="") { - - //TODO: Windows... - cd_path_and_command="cd \""+path.string()+"\" && "+command; - } - else - cd_path_and_command=command; - int stdin_fd, stdout_fd, stderr_fd; async_executes_mutex.lock(); stdin_buffer.clear(); - auto pid=popen3(cd_path_and_command.c_str(), stdin_fd, stdout_fd, stderr_fd); + auto pid=popen3(command, path.string(), &stdin_fd, &stdout_fd, &stderr_fd); async_executes.emplace_back(pid, stdin_fd); async_executes_mutex.unlock(); diff --git a/src/terminal_win.cc b/src/terminal_win.cc index 2a8b2de..e79014d 100644 --- a/src/terminal_win.cc +++ b/src/terminal_win.cc @@ -10,7 +10,7 @@ using namespace std; //TODO: remove #define BUFSIZE 1024 -HANDLE popen3(const std::string &command, const boost::filesystem::path &path, HANDLE &stdin_h, HANDLE &stdout_h, HANDLE &stderr_h) { +HANDLE popen3(const std::string &command, const std::string &path, HANDLE *stdin_h, HANDLE *stdout_h, HANDLE *stderr_h) { HANDLE g_hChildStd_IN_Rd = NULL; HANDLE g_hChildStd_IN_Wr = NULL; HANDLE g_hChildStd_OUT_Rd = NULL; @@ -76,9 +76,8 @@ HANDLE popen3(const std::string &command, const boost::filesystem::path &path, H if(path=="") path_ptr=NULL; else { - auto path_str=path.string(); - path_ptr=new char[path_str.size()+1]; - std::strcpy(path_ptr, path_str.c_str()); + path_ptr=new char[path.size()+1]; + std::strcpy(path_ptr, path.c_str()); } char* command_cstr=new char[command.size()+1]; std::strcpy(command_cstr, command.c_str()); @@ -112,9 +111,9 @@ HANDLE popen3(const std::string &command, const boost::filesystem::path &path, H CloseHandle(g_hChildStd_ERR_Wr); } - stdin_h=g_hChildStd_IN_Wr; - stdout_h=g_hChildStd_OUT_Rd; - stderr_h=g_hChildStd_ERR_Rd; + *stdin_h=g_hChildStd_IN_Wr; + *stdout_h=g_hChildStd_OUT_Rd; + *stderr_h=g_hChildStd_ERR_Rd; return process_info.hProcess; } @@ -195,7 +194,7 @@ Terminal::Terminal() { int Terminal::execute(const std::string &command, const boost::filesystem::path &path) { HANDLE stdin_h, stdout_h, stderr_h; - auto process=popen3(command, path, stdin_h, stdout_h, stderr_h); + auto process=popen3(command, path.string(), &stdin_h, &stdout_h, &stderr_h); if(process==NULL) { async_print("Error: Failed to run command: " + command + "\n"); return -1; @@ -249,7 +248,7 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem async_executes_mutex.lock(); stdin_buffer.clear(); - auto process=popen3(command, path, stdin_h, stdout_h, stderr_h); + auto process=popen3(command, path.string(), &stdin_h, &stdout_h, &stderr_h); if(process==NULL) { async_executes_mutex.unlock(); async_print("Error: Failed to run command: " + command + "\n"); diff --git a/src/window.cc b/src/window.cc index 75c528a..b3a7b18 100644 --- a/src/window.cc +++ b/src/window.cc @@ -229,12 +229,10 @@ void Window::create_menu() { if(executable_path!="") { compiling=true; Singleton::terminal()->print("Compiling and running "+executable_path.string()+"\n"); - //TODO: Windows... auto project_path=cmake.project_path; Singleton::terminal()->async_execute(Singleton::Config::terminal()->make_command, cmake.project_path, [this, executable_path, project_path](int exit_code){ compiling=false; if(exit_code==EXIT_SUCCESS) { - //TODO: Windows... auto executable_path_spaces_fixed=executable_path.string(); char last_char=0; for(size_t c=0;cprint("Compiling project "+cmake.project_path.string()+"\n"); - //TODO: Windows... Singleton::terminal()->async_execute(Singleton::Config::terminal()->make_command, cmake.project_path, [this](int exit_code){ compiling=false; });