diff options
Diffstat (limited to 'src/execute.cc')
-rw-r--r-- | src/execute.cc | 133 |
1 files changed, 115 insertions, 18 deletions
diff --git a/src/execute.cc b/src/execute.cc index 610ccdd..5e59ff6 100644 --- a/src/execute.cc +++ b/src/execute.cc @@ -3,11 +3,17 @@ // See accompanying file LICENSE for details. #include "execute.h" -#include <unistd.h> #include <cstring> +#if !defined(_WIN32) +#include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <spawn.h> +#else +#include <processthreadsapi.h> +#include <synchapi.h> +#include <processenv.h> +#endif #include <iostream> /* @@ -18,6 +24,7 @@ https://stackoverflow.com/questions/4259629/what-is-the-difference-between-fork- */ +#if !defined(_WIN32) namespace { int parent_waitpid(pid_t pid) @@ -32,9 +39,11 @@ int parent_waitpid(pid_t pid) return WEXITSTATUS(status); } } // namespace :: +#endif int execute(const std::string& command, const std::vector<std::string>& args, + const std::map<std::string, std::string>& env, bool verbose) { std::vector<const char*> argv; @@ -45,46 +54,134 @@ int execute(const std::string& command, } argv.push_back(nullptr); - if(verbose) + std::string cmd; + for(const auto& arg : argv) { - std::string cmd; - for(const auto& arg : argv) + if(arg == nullptr) { - if(arg == nullptr) - { - break; - } - if(!cmd.empty()) - { - cmd += " "; - } - cmd += arg; + break; + } + if(!cmd.empty()) + { + cmd += " "; } + cmd += arg; + } + if(verbose) + { std::cout << cmd << "\n"; } +#if !defined(_WIN32) + #if 1 auto pid = vfork(); if(pid == 0) { + for(const auto& [key, value] : env) + { + setenv(key, value); + } + // TODO: use execvpe to set LD_LIBRARY_PATH execv(command.data(), (char**)argv.data()); std::cout << "Could not execute " << command << ": " << strerror(errno) << "\n"; _exit(1); // execv only returns if an error occurred } - auto ret = parent_waitpid(pid); + + return parent_waitpid(pid); #elif 0 pid_t pid; + const char * envp[] = {nullptr}; // TODO: use this to set LD_LIBRARY_PATH if(posix_spawn(&pid, command.data(), nullptr, nullptr, - (char**)argv.data(), nullptr)) + (char**)argv.data(), envp)) { return 1; } - auto ret = parent_waitpid(pid); + return parent_waitpid(pid); #else - auto ret = system(cmd.data()); + return system(cmd.data()); #endif - return ret; +#else + std::map<std::string, std::string> new_env; + auto env_strings = GetEnvironmentStrings(); + const char* ptr = env_strings; + std::string key; + std::string value; + bool key_state{true}; + while(true) + { + if(key_state) // searching for key + { + if(*ptr == '\0') + { + break; + } + + if(*ptr != '=') + { + key += *ptr; + } + else + { + key_state = false; + } + } + else + { + if(*ptr != '\0') + { + value += *ptr; + } + else + { + new_env.insert({key, value}); + key = {}; + value = {}; + key_state = true; + } + } + ++ptr; + } + FreeEnvironmentStrings(env_strings); + + // add new env vars (if any) + for(const auto& [key, value] : env) + { + //if(key == "CL" || key == "LINK" || key == "LIB") + { + new_env[key] = value; + } + } + + std::string env_str; + for(const auto& [k,v] : new_env) + { + env_str += k + "=" + v; + env_str += '\0'; + } + env_str += '\0'; + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory(&si,sizeof(si)); + si.cb=sizeof(si); + ZeroMemory(&pi,sizeof(pi)); + // TODO: Use SetDllDirectory(...) to set DLL search directory + if(!CreateProcess(nullptr, //"C:/WINDOWS/notepad.exe", + //"notepad.exe c:/readme.txt",0,0,0,0,0,0,&si,&pi)) + (char*)cmd.data(),0,0,0,0,env_str.data(),0,&si,&pi)) + { + return 1; // Could not start process; + } + + // Now 'pi.hProcess' contains the process HANDLE, which you can use to + // wait for it like this: + const DWORD infinite = 0xFFFFFFFF; + WaitForSingleObject(pi.hProcess, infinite); + DWORD exitCode{0}; + GetExitCodeProcess(pi.hProcess, &exitCode); + return exitCode; +#endif } |