X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=lib%2Fsystem%2Fsystem.c;h=7bb49973333f3ebebcd4eec0a87fe37994acc67c;hb=c20a0460f3c9057aa920949414f8c3bd6529f927;hp=1b506d2edaf6b5e84f9ea4211e0cac1b189f3d31;hpb=604a1ccf072f9f33326fb6dc919c1b6233d40866;p=petitboot diff --git a/lib/system/system.c b/lib/system/system.c index 1b506d2..7bb4997 100644 --- a/lib/system/system.c +++ b/lib/system/system.c @@ -17,15 +17,17 @@ #include "system.h" const struct pb_system_apps pb_system_apps = { - .prefix = PREFIX, - .cp = "/bin/cp", - .kexec = "/sbin/kexec", - .mount = "/bin/mount", - .shutdown = "/sbin/shutdown", - .sftp = "/usr/bin/sftp", - .tftp = "/usr/bin/tftp", - .umount = "/bin/umount", - .wget = "/usr/bin/wget", + .prefix = PREFIX, + .cp = HOST_PROG_CP, + .kexec = HOST_PROG_KEXEC, + .mount = HOST_PROG_MOUNT, + .shutdown = HOST_PROG_SHUTDOWN, + .sftp = HOST_PROG_SFTP, + .tftp = HOST_PROG_TFTP, + .umount = HOST_PROG_UMOUNT, + .wget = HOST_PROG_WGET, + .ip = HOST_PROG_IP, + .udhcpc = HOST_PROG_UDHCPC, }; int pb_mkdir_recursive(const char *dir) @@ -100,32 +102,96 @@ int pb_rmdir_recursive(const char *base, const char *dir) return 0; } +static int read_pipe(void *ctx, int fd, char **bufp, int *lenp) +{ + int rc, len, alloc_len; + char *buf; + + alloc_len = 4096; + len = 0; + + buf = talloc_array(ctx, char, alloc_len); + + for (;;) { + rc = read(fd, buf, alloc_len - len - 1); + if (rc <= 0) + break; + + len += rc; + if (len == alloc_len - 1) { + alloc_len *= 2; + buf = talloc_realloc(ctx, buf, char, alloc_len); + } + } + + if (rc < 0) { + talloc_free(buf); + return rc; + } + + buf[len] = '\0'; + *bufp = buf; + *lenp = len; + + return 0; +} + /** * pb_run_cmd - Run the supplied command. * @cmd_argv: An argument list array for execv. + * @wait: Wait for the child process to complete before returning. + * @dry_run: Don't actually fork and exec. */ -int pb_run_cmd(const char *const *cmd_argv, int wait) +int pb_run_cmd(const char *const *cmd_argv, int wait, int dry_run) +{ + return pb_run_cmd_pipe(cmd_argv, wait, dry_run, NULL, NULL, NULL); +} + +int pb_run_cmd_pipe(const char *const *cmd_argv, int wait, int dry_run, + void *ctx, char **stdout_buf, int *stdout_buf_len) { #if defined(DEBUG) enum {do_debug = 1}; #else enum {do_debug = 0}; #endif - int status; + int status, pipefd[2]; pid_t pid; + assert(!wait && stdout_buf); + assert(!!ctx != !!stdout_buf); + assert(!!stdout_buf != !!stdout_buf_len); + if (do_debug) { const char *const *p = cmd_argv; - pb_log("%s: ", __func__); + pb_log("%s: %s", __func__, (dry_run ? "(dry-run) " : "")); + while (*p) { pb_log("%s ", *p); p++; } pb_log("\n"); } else - pb_log("%s: %s\n", __func__, cmd_argv[0]); + pb_log("%s: %s%s\n", __func__, (dry_run ? "(dry-run) " : ""), + cmd_argv[0]); + + if (stdout_buf) { + *stdout_buf = NULL; + *stdout_buf_len = 0; + } + + if (dry_run) + return 0; + + if (stdout_buf) { + status = pipe(pipefd); + if (status) { + pb_log("pipe failed"); + return -1; + } + } pid = fork(); @@ -134,12 +200,17 @@ int pb_run_cmd(const char *const *cmd_argv, int wait) return -1; } + if (pid == 0) { int log = fileno(pb_log_get_stream()); /* Redirect child output to log. */ - status = dup2(log, STDOUT_FILENO); + if (stdout_buf) { + status = dup2(pipefd[1], STDOUT_FILENO); + } else { + status = dup2(log, STDOUT_FILENO); + } assert(status != -1); status = dup2(log, STDERR_FILENO); @@ -153,6 +224,13 @@ int pb_run_cmd(const char *const *cmd_argv, int wait) if (!wait && !waitpid(pid, &status, WNOHANG)) return 0; + if (stdout_buf) { + close(pipefd[1]); + status = read_pipe(ctx, pipefd[0], stdout_buf, stdout_buf_len); + if (status) + return -1; + } + if (waitpid(pid, &status, 0) == -1) { pb_log("%s: waitpid failed: %s\n", __func__, strerror(errno));