diff options
Diffstat (limited to 'src/execute.cc')
-rw-r--r-- | src/execute.cc | 206 |
1 files changed, 201 insertions, 5 deletions
diff --git a/src/execute.cc b/src/execute.cc index cbae899..3d8fe62 100644 --- a/src/execute.cc +++ b/src/execute.cc @@ -5,12 +5,22 @@ #include "ctor.h" -#include <unistd.h> -#include <cstring> -#include <sys/types.h> -#include <sys/wait.h> -#include <spawn.h> +#if !defined(_WIN32) + #include <unistd.h> + #include <sys/types.h> + #include <sys/wait.h> + #include <spawn.h> +#else + #define WINDOWS_LEAN_AND_MEAN + #include <windows.h> + #undef max +#endif + #include <iostream> +#include <cstring> +#include <vector> +#include <deque> +#include <filesystem> /* https://blog.famzah.net/2009/11/20/a-much-faster-popen-and-system-implementation-for-linux/ @@ -22,6 +32,7 @@ https://stackoverflow.com/questions/4259629/what-is-the-difference-between-fork- namespace { +/* class Env : public std::vector<char*> { @@ -30,7 +41,27 @@ public: { for(const auto& arg : args) { + string_data.push_back(arg); + push_back(string_data.back().data()); + } + } + + std::deque<std::string> string_data; +}; +*/ +class Env + : public std::vector<char*> +{ +public: + Env(const std::vector<std::string>& args) + { + for(const auto& arg : args) + { +#if !defined(_WIN32) push_back(strdup(arg.data())); +#else + push_back(_strdup(arg.data())); +#endif } push_back(nullptr); } @@ -44,6 +75,7 @@ public: } }; +#if !defined(_WIN32) int parent_waitpid(pid_t pid) { int status{}; @@ -55,6 +87,7 @@ int parent_waitpid(pid_t pid) return WEXITSTATUS(status); } +#endif //_WIN32 } // namespace :: extern char **environ; // see 'man environ' @@ -92,6 +125,8 @@ int execute(const ctor::settings& settings, std::cout << cmd << std::endl; } +#if !defined(_WIN32) + #if 1 auto pid = vfork(); if(pid == 0) @@ -133,5 +168,166 @@ int execute(const ctor::settings& settings, return system(cmd.data()); #endif +#else // _WIN32 + 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{}; +// si.hStdInput = GetStdHandle(((DWORD)-10)/*STD_INPUT_HANDLE*/); +// si.hStdOutput = GetStdHandle(((DWORD)-11)/*STD_OUTPUT_HANDLE*/); +// si.hStdError = GetStdHandle(((DWORD)-12)/*STD_ERROR_HANDLE*/); +// si.dwFlags = /*STARTF_USESTDHANDLES*/0x00000100; + + PROCESS_INFORMATION pi{}; + + si.cb = sizeof(si); + + // TODO: Use SetDllDirectory(...) to set DLL search directory + + if(terminate) + { + char tmpdir[MAX_PATH+1]; + int cnt{0}; + + // The returned string ends with a backslash + if(GetTempPathA(sizeof(tmpdir), tmpdir) == 0) + { + std::cerr << "Could not read TMP folder\n"; + return GetLastError(); + } + + char source[MAX_PATH]; + HMODULE module = GetModuleHandle(0); + GetModuleFileNameA(module, source, MAX_PATH); + + while(true) + { + if(cnt > 10) // If we need to try more than 10 times something is wrong + { + return 1; + } + + std::filesystem::path tmp_file = settings.builddir; + tmp_file /= "tmp"; + std::string target = tmp_file.string() + "-" + std::to_string(cnt); + std::cout << "move " << source << " => " << target <<std::endl; + if(MoveFileA(source, target.data())) + { + break; // success + } + + auto err = GetLastError(); + if(err == ERROR_ALREADY_EXISTS) + { + if(DeleteFileA(target.data())) + { + continue; // Try again + } + + err = GetLastError(); + if(err != ERROR_ACCESS_DENIED) + { + std::cerr << "Could not delete file\n"; + return err; + } + + cnt++; + continue; // Increment and try again + } + else + { + std::cerr << "Could not move file\n"; + return err; + } + } + } + + if(!CreateProcess(nullptr, // lpApplicationName + (char*)cmd.data(), // lpCommandLine + nullptr, // lpProcessAttributes + nullptr, // lpThreadAttributes + TRUE, // bInheritHandles + INHERIT_PARENT_AFFINITY | + //DETACHED_PROCESS | + ///*DEBUG_PROCESS*/ 0x00000001 | + ///*CREATE_NO_WINDOW*/ 0x08000000 | + ///*CREATE_BREAKAWAY_FROM_JOB*/ 0x01000000 | + /*CREATE_NEW_PROCESS_GROUP*/ 0x00000200 | + 0, // dwCreationFlags + env_str.data(), // lpEnvironment + nullptr, // lpCurrentDirectory + &si, // lpStartupInfo + &pi)) // lpProcessInformation + { + 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 // _WIN32 + return 1; } |