aboutsummaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'util.c')
-rw-r--r--util.c76
1 files changed, 76 insertions, 0 deletions
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;
+}