summaryrefslogtreecommitdiff
path: root/src/execute.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/execute.cc')
-rw-r--r--src/execute.cc133
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
}