From ad95012be993664e062e7724155c54a482a51315 Mon Sep 17 00:00:00 2001 From: N-R-K <79544946+N-R-K@users.noreply.github.com> Date: Sun, 20 Feb 2022 15:54:29 +0000 Subject: Add reuseable abstraction over fork/exec/dup2 (#211) --- util.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'util.c') diff --git a/util.c b/util.c index ef0ec43..d580839 100644 --- a/util.c +++ b/util.c @@ -211,3 +211,79 @@ int r_mkdir(char *path) } return 0; } + +void construct_argv(char **argv, unsigned int len, ...) +{ + unsigned int i; + va_list args; + + va_start(args, len); + for (i = 0; i < len; ++i) + argv[i] = va_arg(args, char *); + va_end(args); + if (argv[len-1] != NULL) + error(EXIT_FAILURE, 0, "argv not NULL terminated"); +} + +spawn_t spawn(const char *cmd, char *const argv[], unsigned int flags) +{ + pid_t pid; + spawn_t status = { -1, -1, -1 }; + int pfd_read[2] = { -1, -1 }; + int pfd_write[2] = { -1, -1 }; + const bool r = flags & X_READ; + const bool w = flags & X_WRITE; + + if (cmd == NULL || argv == NULL || flags == 0) + return status; + + if (r && pipe(pfd_read) < 0) { + error(0, errno, "pipe: %s", cmd); + return status; + } + + if (w && pipe(pfd_write) < 0) { + if (r) { + close(pfd_read[0]); + close(pfd_read[1]); + } + error(0, errno, "pipe: %s", cmd); + return status; + } + + if ((pid = fork()) == 0) { + bool err = (r && dup2(pfd_read[1], 1) < 0) || (w && dup2(pfd_write[0], 0) < 0); + if (r) { + close(pfd_read[0]); + close(pfd_read[1]); + } + if (w) { + close(pfd_write[0]); + close(pfd_write[1]); + } + + if (err) + error(EXIT_FAILURE, errno, "dup2: %s", cmd); + execv(cmd, argv); + error(EXIT_FAILURE, errno, "exec: %s", cmd); + } + + if (r) + close(pfd_read[1]); + if (w) + close(pfd_write[0]); + + if (pid < 0) { + if (r) + close(pfd_read[0]); + if (w) + close(pfd_write[1]); + error(0, errno, "fork: %s", cmd); + return status; + } + + status.pid = pid; + status.readfd = pfd_read[0]; + status.writefd = pfd_write[1]; + return status; +} -- cgit v1.2.3-54-g00ecf