1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
// usage: run "prog arg args ..." "prog2 arg arg ..."
#include <unistd.h>
#include <sys/wait.h>
#include <sys/errno.h>
#include <string>
#include <vector>
#include <list>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef std::vector<std::string> prog_t;
typedef std::list<prog_t> progs_t;
typedef std::vector<pid_t> pids_t;
int wait(const pids_t& pids);
void run(pids_t& pids, const prog_t& prog);
prog_t split(const char* in);
int main(int argc, char* argv[])
{
progs_t progs;
std::for_each(argv + 1, argv + argc, [&](char *arg) { progs.push_back(split(arg)); });
pids_t pids;
for (auto& prog : progs) run(pids, prog);
return wait(pids);
}
int wait(const pids_t& pids)
{
int ret = 0;
int stat;
for (pid_t pid : pids) {
waitpid(pid, &stat, 0);
ret = ret || WEXITSTATUS(stat);
}
return ret;
}
void run(pids_t& pids, const prog_t& prog)
{
int pid = fork();
if (pid == 0) {
// build arg vector
std::vector<char*> args;
for (const std::string& arg : prog) args.push_back(strdup(arg.c_str()));
args.push_back(nullptr);
execv(args[0], args.data()); // if exec works, this program instance ends here
for (char* arg : args) free(arg);
fprintf(stderr, "%s: execv failed: %s\n", args[0], strerror(errno));
}
else if (pid > 0)
pids.push_back(pid);
}
prog_t split(const char* in)
{
prog_t out;
for (const char* begin = in;;) {
const char* end = strchr(begin, ' ');
if (!end) {
if (*begin) out.emplace_back(begin); // append final string
break;
}
out.emplace_back(begin, end);
begin = end + 1; // next entry
while (isspace(*begin)) ++begin; // skip spaces
}
return out;
}
|