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