diff options
Diffstat (limited to 'src/execute.cc')
-rw-r--r-- | src/execute.cc | 76 |
1 files changed, 42 insertions, 34 deletions
diff --git a/src/execute.cc b/src/execute.cc index b4013d0..c050732 100644 --- a/src/execute.cc +++ b/src/execute.cc @@ -3,6 +3,9 @@ // See accompanying file LICENSE for details. #include "execute.h" +#include "ctor.h" +#include "pointerlist.h" + #include <unistd.h> #include <cstring> #include <sys/types.h> @@ -20,47 +23,53 @@ https://stackoverflow.com/questions/4259629/what-is-the-difference-between-fork- namespace { -class Env - : public std::vector<char*> + +int parent_waitpid(pid_t pid) { -public: - Env(const std::vector<std::string>& args) + int status{}; + + auto rc_pid = waitpid(pid, &status, 0); + + if(rc_pid > 0) { - for(const auto& arg : args) + if(WIFEXITED(status)) { - push_back(strdup(arg.data())); + // Child exited with normally + return WEXITSTATUS(status); } - push_back(nullptr); - } - - ~Env() - { - for(auto ptr : *this) + if(WIFSIGNALED(status)) { - free(ptr); + // Child exited via signal (segfault, abort, ...) + std::cerr << strsignal(status) << '\n'; + return WTERMSIG(status); } } -}; - -int parent_waitpid(pid_t pid) -{ - int status; - - if(waitpid(pid, &status, 0) != pid) - { - return 1; + else + { // No PID returned, this is an error + if(errno == ECHILD) + { + // No children exist. + return 1; + } + else + { + // Unexpected error. + abort(); + } } - return WEXITSTATUS(status); + // Should never happen... + return 1; } } // namespace :: extern char **environ; // see 'man environ' -int execute(const std::string& command, +int execute(const ctor::settings& settings, + const std::string& command, const std::vector<std::string>& args, const std::map<std::string, std::string>& env, - bool verbose) + [[maybe_unused]] bool terminate) { std::vector<const char*> argv; argv.push_back(command.data()); @@ -84,7 +93,7 @@ int execute(const std::string& command, cmd += arg; } - if(verbose) + if(settings.verbose > 0) { std::cout << cmd << std::endl; } @@ -93,19 +102,18 @@ int execute(const std::string& command, auto pid = vfork(); if(pid == 0) { - std::vector<std::string> venv; + EnvMap envmap((const char**)environ); for(const auto& [key, value] : env) { - venv.push_back(key + "=" + value); + envmap.insert(key + "=" + value); } - - for(auto current = environ; *current; ++current) + if(settings.dry_run) { - venv.push_back(*current); + _exit(0); } - - Env penv(venv); - execve(command.data(), (char**)argv.data(), penv.data()); + auto [_, envv] = envmap.get(); + execve(command.data(), const_cast<char* const *>(argv.data()), + const_cast<char* const *>(envv)); std::cout << "Could not execute " << command << ": " << strerror(errno) << "\n"; _exit(1); // execve only returns if an error occurred |