From 8c57ce3e43966dd145b63c2df1d55ebbc3126069 Mon Sep 17 00:00:00 2001 From: Sanel Zukan Date: Fri, 31 Aug 2007 13:41:27 +0000 Subject: [PATCH] Commands can contain $TERM to allow running apps in terminal. Some heuristic gui/console determination, but pretty sucks for now. --- evoke/EvokeService.cpp | 85 ++++++++++++++++++++++++++++++++++++++++-- evoke/EvokeService.h | 3 +- evoke/Spawn.cpp | 12 ++++-- evoke/Spawn.h | 3 +- 4 files changed, 94 insertions(+), 9 deletions(-) diff --git a/evoke/EvokeService.cpp b/evoke/EvokeService.cpp index 98c8bce..22368e4 100644 --- a/evoke/EvokeService.cpp +++ b/evoke/EvokeService.cpp @@ -19,6 +19,7 @@ #include "Autostart.h" #include +#include #include #include #include @@ -465,16 +466,93 @@ void EvokeService::service_watcher(int pid, int signum) { * Execute program. It's return status * will be reported via service_watcher() */ -void EvokeService::run_program(const char* cmd) { +void EvokeService::run_program(const char* cmd, bool enable_vars) { EASSERT(cmd != NULL); + edelib::String scmd(cmd); pid_t child; - int r = spawn_program_with_core(cmd, service_watcher_cb, &child); + + if(enable_vars && scmd.length() > 6) { + if(scmd.substr(0, 6) == "$TERM ") { + char* term = getenv("TERM"); + if(!term) + term = "xterm"; + + edelib::String tmp(term); + tmp += " -e "; + tmp += scmd.substr(6, scmd.length()); + + scmd = tmp; + } + } + + int r = spawn_program_with_core(scmd.c_str(), service_watcher_cb, &child); if(r != 0) edelib::alert("Unable to start %s. Got code %i", cmd, r); else - register_process(cmd, child); + register_process(scmd.c_str(), child); +} + +void EvokeService::heuristic_run_program(const char* cmd) { + if(strncmp(cmd, "$TERM ", 6) == 0) { + run_program(cmd); + return; + } + + edelib::String ldd = edelib::file_path("ldd"); + if(ldd.empty()) { + run_program(cmd); + return; + } + + ldd += " "; + ldd += edelib::file_path(cmd); + + int r = spawn_program(ldd.c_str(), 0, 0, "/tmp/eshrun"); + printf("%s\n", ldd.c_str()); + if(r != 0) { + printf("spawn %i\n", r); + return; + } + + sleep(1); + + //edelib::File f; + FILE* f = fopen("/tmp/eshrun", "r"); + if(!f) { + puts("File::open"); + return; + } else { + puts("opened /tmp/eshrun"); + } + + edelib::Regex rx; + rx.compile("^\\s*libX11"); + char buff[1024]; + bool is_gui = 0; + + while(fgets(buff, sizeof(buff)-1, f)) { + printf("checking %s\n", buff); + + if(rx.match(buff)) { + printf("found libX11\n"); + is_gui = 1; + //break; + } + } + + fclose(f); + + edelib::String fcmd; + if(!is_gui) { + fcmd = "$TERM "; + fcmd += cmd; + } else { + fcmd = cmd; + } + + run_program(fcmd.c_str()); } void EvokeService::register_process(const char* cmd, pid_t pid) { @@ -545,6 +623,7 @@ int EvokeService::handle(const XEvent* ev) { if(get_string_property_value(_ede_spawn, buff, sizeof(buff))) { logfile->printf("Got _EVOKE_SPAWN with %s. Starting client...\n", buff); run_program(buff); + //heuristic_run_program(buff); } else { logfile->printf("Got _EVOKE_SPAWN with malformed data. Ignoring...\n"); } diff --git a/evoke/EvokeService.h b/evoke/EvokeService.h index 39a43d4..4f33608 100644 --- a/evoke/EvokeService.h +++ b/evoke/EvokeService.h @@ -79,7 +79,8 @@ class EvokeService { void unregister_top(void) { top_win = NULL; } void service_watcher(int pid, int signum); - void run_program(const char* cmd); + void run_program(const char* cmd, bool enable_vars = 1); + void heuristic_run_program(const char* cmd); void register_process(const char* cmd, pid_t pid); void unregister_process(pid_t pid); bool find_and_unregister_process(pid_t pid, EvokeProcess& pc); diff --git a/evoke/Spawn.cpp b/evoke/Spawn.cpp index 33a4cc1..5b97605 100644 --- a/evoke/Spawn.cpp +++ b/evoke/Spawn.cpp @@ -49,7 +49,7 @@ void sigchld_handler(int sig) { } while(pid <= 0 && errno == EINTR); } -int spawn_program(const char* cmd, SignalWatch wf, pid_t* child_pid_ret) { +int spawn_program(const char* cmd, SignalWatch wf, pid_t* child_pid_ret, const char* ofile) { if(!cmd) return SPAWN_EMPTY; @@ -84,15 +84,19 @@ int spawn_program(const char* cmd, SignalWatch wf, pid_t* child_pid_ret) { * The following is to avoid X locking when executing * terminal based application that requires user input */ - if((nulldev = open("/dev/null", O_RDWR)) == -1) - return SPAWN_FORK_FAILED; + if(ofile) + nulldev = open(ofile, O_WRONLY | O_TRUNC | O_CREAT, 0770); + else + nulldev = open("/dev/null", O_RDWR); + + if(nulldev == -1) + return SPAWN_OPEN_FAILED; /* TODO: redirect these to EvokeService log */ close(0); dup(nulldev); close(1); dup(nulldev); close(2); dup(nulldev); - if(execve(argv[0], argv, environ) == -1) { close(nulldev); // should not get here diff --git a/evoke/Spawn.h b/evoke/Spawn.h index 4d8b5e7..426508a 100644 --- a/evoke/Spawn.h +++ b/evoke/Spawn.h @@ -26,13 +26,14 @@ #define SPAWN_FORK_FAILED 1 #define SPAWN_EMPTY 2 #define SPAWN_EXECVE_FAILED 3 +#define SPAWN_OPEN_FAILED 4 #define SPAWN_CHILD_CRASHED -2 #define SPAWN_CHILD_KILLED -3 typedef void (SignalWatch)(int pid, int status); -int spawn_program(const char* cmd, SignalWatch* wf = 0, pid_t* child_pid_ret = 0); +int spawn_program(const char* cmd, SignalWatch* wf = 0, pid_t* child_pid_ret = 0, const char* ofile = 0); int spawn_program_with_core(const char* cmd, SignalWatch* wf = 0, pid_t* child_pid_ret = 0); int spawn_backtrace(const char* program, const char* core, const char* output, const char* script);