From a5585150f0ff8d27ddd22792f521f1374a3eedd8 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Fri, 20 Jan 2023 08:37:29 +0100 Subject: Add env to execute function. --- src/execute.cc | 82 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 19 deletions(-) (limited to 'src/execute.cc') diff --git a/src/execute.cc b/src/execute.cc index 20a4a02..b4013d0 100644 --- a/src/execute.cc +++ b/src/execute.cc @@ -20,6 +20,28 @@ https://stackoverflow.com/questions/4259629/what-is-the-difference-between-fork- namespace { +class Env + : public std::vector +{ +public: + Env(const std::vector& args) + { + for(const auto& arg : args) + { + push_back(strdup(arg.data())); + } + push_back(nullptr); + } + + ~Env() + { + for(auto ptr : *this) + { + free(ptr); + } + } +}; + int parent_waitpid(pid_t pid) { int status; @@ -33,8 +55,11 @@ int parent_waitpid(pid_t pid) } } // namespace :: +extern char **environ; // see 'man environ' + int execute(const std::string& command, const std::vector& args, + const std::map& env, bool verbose) { std::vector argv; @@ -45,22 +70,22 @@ 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 << std::endl; } @@ -68,23 +93,42 @@ int execute(const std::string& command, auto pid = vfork(); if(pid == 0) { - execv(command.data(), (char**)argv.data()); + std::vector venv; + for(const auto& [key, value] : env) + { + venv.push_back(key + "=" + value); + } + + for(auto current = environ; *current; ++current) + { + venv.push_back(*current); + } + + Env penv(venv); + execve(command.data(), (char**)argv.data(), penv.data()); std::cout << "Could not execute " << command << ": " << strerror(errno) << "\n"; - _exit(1); // execv only returns if an error occurred + _exit(1); // execve only returns if an error occurred } - auto ret = parent_waitpid(pid); + return parent_waitpid(pid); #elif 0 pid_t pid; + std::vector venv; + for(const auto& [key, value] : env) + { + venv.push_back(key + "=" + value); + } + Env penv(venv); if(posix_spawn(&pid, command.data(), nullptr, nullptr, - (char**)argv.data(), nullptr)) + (char**)argv.data(), penv.data())) { return 1; } - auto ret = parent_waitpid(pid); + return parent_waitpid(pid); #else - auto ret = system(cmd.data()); + (void)parent_waitpid; + return system(cmd.data()); #endif - return ret; + return 1; } -- cgit v1.2.3