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) {
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;

98
src/terminal.cc

@ -8,57 +8,74 @@
#include <iostream> //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<void(int exit_code)> 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();

17
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");

3
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;c<executable_path_spaces_fixed.size();c++) {
@ -264,7 +262,6 @@ void Window::create_menu() {
if(cmake.project_path!="") {
compiling=true;
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){
compiling=false;
});

Loading…
Cancel
Save