X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=lib%2Fsystem%2Fsystem.c;h=528e134127f307f17d9dcfaa70b2b1ef60eb7a52;hb=a70807730ef59efc4116556ecabe1b9f70ce605b;hp=d77159d5a7b882470648c740aa301b0314fd67c6;hpb=52b9db95764fcdee9195113d7df225634a19c9f4;p=petitboot diff --git a/lib/system/system.c b/lib/system/system.c index d77159d..528e134 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,6 +102,40 @@ 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. @@ -108,15 +144,25 @@ int pb_rmdir_recursive(const char *base, const char *dir) */ 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(!stdout_buf || wait); + assert(!stdout_buf || ctx); + assert(!stdout_buf || stdout_buf_len); + if (do_debug) { const char *const *p = cmd_argv; @@ -131,9 +177,22 @@ int pb_run_cmd(const char *const *cmd_argv, int wait, int dry_run) 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(); if (pid == -1) { @@ -141,12 +200,17 @@ int pb_run_cmd(const char *const *cmd_argv, int wait, int dry_run) 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); @@ -160,6 +224,13 @@ int pb_run_cmd(const char *const *cmd_argv, int wait, int dry_run) 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));