summaryrefslogtreecommitdiff
path: root/src/execute.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/execute.cc')
-rw-r--r--src/execute.cc82
1 files changed, 63 insertions, 19 deletions
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<char*>
+{
+public:
+ Env(const std::vector<std::string>& 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<std::string>& args,
+ const std::map<std::string, std::string>& env,
bool verbose)
{
std::vector<const char*> 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<std::string> 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<std::string> 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;
}