Migrate exec function to C++ arrays

This commit is contained in:
topjohnwu
2018-11-03 04:03:11 -04:00
parent 6339ba6bfb
commit 4351de503f
6 changed files with 90 additions and 112 deletions

View File

@@ -193,3 +193,78 @@ ssize_t __getline(char **lineptr, size_t *n, FILE *stream) {
int __fsetxattr(int fd, const char *name, const void *value, size_t size, int flags) {
return (int) syscall(__NR_fsetxattr, fd, name, value, size, flags);
}
/*
fd == NULL -> Ignore output
*fd < 0 -> Open pipe and set *fd to the read end
*fd >= 0 -> STDOUT (or STDERR) will be redirected to *fd
*cb -> A callback function which calls after forking
*/
int exec_array(int err, int *fd, void (*cb)(void), const char *argv[]) {
int pipefd[2], write_end = -1;
if (fd) {
if (*fd < 0) {
if (xpipe2(pipefd, O_CLOEXEC) == -1)
return -1;
write_end = pipefd[1];
} else {
write_end = *fd;
}
}
int pid = xfork();
if (pid != 0) {
if (fd && *fd < 0) {
// Give the read end and close write end
*fd = pipefd[0];
close(pipefd[1]);
}
return pid;
}
if (fd) {
xdup2(write_end, STDOUT_FILENO);
if (err)
xdup2(write_end, STDERR_FILENO);
}
// Setup environment
if (cb)
cb();
execvp(argv[0], (char **) argv);
PLOGE("execvp %s", argv[0]);
return -1;
}
static int v_exec_command(int err, int *fd, void (*cb)(void), const char *argv0, va_list argv) {
// Collect va_list into vector
Array<const char *> args;
args.push_back(argv0);
for (const char *arg = va_arg(argv, char*); arg; arg = va_arg(argv, char*))
args.push_back(arg);
args.push_back(nullptr);
int pid = exec_array(err, fd, cb, args.data());
return pid;
}
int exec_command_sync(const char *argv0, ...) {
va_list argv;
va_start(argv, argv0);
int pid, status;
pid = v_exec_command(0, NULL, NULL, argv0, argv);
va_end(argv);
if (pid < 0)
return pid;
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
}
int exec_command(int err, int *fd, void (*cb)(void), const char *argv0, ...) {
va_list argv;
va_start(argv, argv0);
int pid = v_exec_command(err, fd, cb, argv0, argv);
va_end(argv);
return pid;
}