Browse Source

Some cleanup.

merge-requests/365/head
eidheim 10 years ago
parent
commit
bc6785fcee
  1. 1
      src/cmake.cc
  2. 98
      src/terminal.cc
  3. 17
      src/terminal_win.cc
  4. 3
      src/window.cc

1
src/cmake.cc

@ -46,7 +46,6 @@ CMake::CMake(const boost::filesystem::path &path) {
bool CMake::create_compile_commands(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"); 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) { 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 #ifdef _WIN32 //Temporary fix to MSYS2's libclang
auto compile_commands_path=path; auto compile_commands_path=path;

98
src/terminal.cc

@ -8,57 +8,74 @@
#include <iostream> //TODO: remove #include <iostream> //TODO: remove
using namespace std; //TODO: remove using namespace std; //TODO: remove
//TODO: Windows...
//A working implementation of popen3, with all pipes getting closed properly. //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 //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; 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) { if(stdin_fd!=nullptr && pipe(stdin_p)!=0) {
close(p_stdin[0]); close(stdin_p[0]);
close(p_stdout[0]); close(stdin_p[1]);
close(p_stderr[0]); return -1;
close(p_stdin[1]); }
close(p_stdout[1]); if(stdout_fd!=nullptr && pipe(stdout_p)!=0) {
close(p_stderr[1]); 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; return -1;
} }
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
close(p_stdin[0]); if(stdin_fd!=nullptr) close(stdin_p[0]);
close(p_stdout[0]); if(stdin_fd!=nullptr) close(stdin_p[1]);
close(p_stderr[0]); if(stdout_fd!=nullptr) close(stdout_p[0]);
close(p_stdin[1]); if(stdout_fd!=nullptr) close(stdout_p[1]);
close(p_stdout[1]); if(stderr_fd!=nullptr) close(stderr_p[0]);
close(p_stderr[1]); if(stderr_fd!=nullptr) close(stderr_p[1]);
return pid; return pid;
} }
else if (pid == 0) { else if (pid == 0) {
close(p_stdin[1]); if(stdin_fd!=nullptr) close(stdin_p[1]);
close(p_stdout[0]); if(stdout_fd!=nullptr) close(stdout_p[0]);
close(p_stderr[0]); if(stderr_fd!=nullptr) close(stderr_p[0]);
dup2(p_stdin[0], 0); if(stdin_fd!=nullptr) dup2(stdin_p[0], 0);
dup2(p_stdout[1], 1); if(stdout_fd!=nullptr) dup2(stdout_p[1], 1);
dup2(p_stderr[1], 2); if(stderr_fd!=nullptr) dup2(stderr_p[1], 2);
setpgid(0, 0); 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: 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 //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"); perror("execl");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
close(p_stdin[0]); if(stdin_fd!=nullptr) close(stdin_p[0]);
close(p_stdout[1]); if(stdout_fd!=nullptr) close(stdout_p[1]);
close(p_stderr[1]); if(stderr_fd!=nullptr) close(stderr_p[1]);
stdin_fd = p_stdin[1]; if(stdin_fd!=nullptr) *stdin_fd = stdin_p[1];
stdout_fd = p_stdout[0]; if(stdout_fd!=nullptr) *stdout_fd = stdout_p[0];
stderr_fd = p_stderr[0]; if(stderr_fd!=nullptr) *stderr_fd = stderr_p[0];
return pid; return pid;
} }
@ -137,16 +154,8 @@ Terminal::Terminal() {
} }
int Terminal::execute(const std::string &command, const boost::filesystem::path &path) { 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; 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) { if (pid<=0) {
async_print("Error: Failed to run command: " + command + "\n"); 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<void(int exit_code)> callback) { void Terminal::async_execute(const std::string &command, const boost::filesystem::path &path, std::function<void(int exit_code)> callback) {
std::thread async_execute_thread([this, command, path, 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; int stdin_fd, stdout_fd, stderr_fd;
async_executes_mutex.lock(); async_executes_mutex.lock();
stdin_buffer.clear(); 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.emplace_back(pid, stdin_fd);
async_executes_mutex.unlock(); async_executes_mutex.unlock();

17
src/terminal_win.cc

@ -10,7 +10,7 @@ using namespace std; //TODO: remove
#define BUFSIZE 1024 #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_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL; HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = 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=="") if(path=="")
path_ptr=NULL; path_ptr=NULL;
else { else {
auto path_str=path.string(); path_ptr=new char[path.size()+1];
path_ptr=new char[path_str.size()+1]; std::strcpy(path_ptr, path.c_str());
std::strcpy(path_ptr, path_str.c_str());
} }
char* command_cstr=new char[command.size()+1]; char* command_cstr=new char[command.size()+1];
std::strcpy(command_cstr, command.c_str()); 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); CloseHandle(g_hChildStd_ERR_Wr);
} }
stdin_h=g_hChildStd_IN_Wr; *stdin_h=g_hChildStd_IN_Wr;
stdout_h=g_hChildStd_OUT_Rd; *stdout_h=g_hChildStd_OUT_Rd;
stderr_h=g_hChildStd_ERR_Rd; *stderr_h=g_hChildStd_ERR_Rd;
return process_info.hProcess; return process_info.hProcess;
} }
@ -195,7 +194,7 @@ Terminal::Terminal() {
int Terminal::execute(const std::string &command, const boost::filesystem::path &path) { int Terminal::execute(const std::string &command, const boost::filesystem::path &path) {
HANDLE stdin_h, stdout_h, stderr_h; 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) { if(process==NULL) {
async_print("Error: Failed to run command: " + command + "\n"); async_print("Error: Failed to run command: " + command + "\n");
return -1; return -1;
@ -249,7 +248,7 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem
async_executes_mutex.lock(); async_executes_mutex.lock();
stdin_buffer.clear(); 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) { if(process==NULL) {
async_executes_mutex.unlock(); async_executes_mutex.unlock();
async_print("Error: Failed to run command: " + command + "\n"); async_print("Error: Failed to run command: " + command + "\n");

3
src/window.cc

@ -229,12 +229,10 @@ void Window::create_menu() {
if(executable_path!="") { if(executable_path!="") {
compiling=true; compiling=true;
Singleton::terminal()->print("Compiling and running "+executable_path.string()+"\n"); Singleton::terminal()->print("Compiling and running "+executable_path.string()+"\n");
//TODO: Windows...
auto project_path=cmake.project_path; 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){ Singleton::terminal()->async_execute(Singleton::Config::terminal()->make_command, cmake.project_path, [this, executable_path, project_path](int exit_code){
compiling=false; compiling=false;
if(exit_code==EXIT_SUCCESS) { if(exit_code==EXIT_SUCCESS) {
//TODO: Windows...
auto executable_path_spaces_fixed=executable_path.string(); auto executable_path_spaces_fixed=executable_path.string();
char last_char=0; char last_char=0;
for(size_t c=0;c<executable_path_spaces_fixed.size();c++) { for(size_t c=0;c<executable_path_spaces_fixed.size();c++) {
@ -264,7 +262,6 @@ void Window::create_menu() {
if(cmake.project_path!="") { if(cmake.project_path!="") {
compiling=true; compiling=true;
Singleton::terminal()->print("Compiling project "+cmake.project_path.string()+"\n"); Singleton::terminal()->print("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){ Singleton::terminal()->async_execute(Singleton::Config::terminal()->make_command, cmake.project_path, [this](int exit_code){
compiling=false; compiling=false;
}); });

Loading…
Cancel
Save