]> git.ozlabs.org Git - petitboot/blobdiff - lib/process/process.c
discover/grub2: Allow to separate the --id argument using a space char
[petitboot] / lib / process / process.c
index 1fa0bb0dd347aafa48f4844ed00d15487dacd9bb..7bd29b8219eb386ba4f575f744eb0539925a640c 100644 (file)
@@ -50,6 +50,7 @@ struct process_info {
        int                     stdout_buf_len;
        struct waiter           *stdout_waiter;
        int                     stdout_pipe[2];
        int                     stdout_buf_len;
        struct waiter           *stdout_waiter;
        int                     stdout_pipe[2];
+       int                     stdin_pipe[2];
        void                    *orig_ctx;
 };
 
        void                    *orig_ctx;
 };
 
@@ -130,12 +131,37 @@ static int process_setup_stdout_pipe(struct process_info *procinfo)
        return 0;
 }
 
        return 0;
 }
 
+static void process_setup_stdin_parent(struct process_info *procinfo)
+{
+       FILE *in;
+
+       if (!procinfo->process.pipe_stdin)
+               return;
+
+       close(procinfo->stdin_pipe[0]);
+       in = fdopen(procinfo->stdin_pipe[1], "w");
+       if (!in) {
+               pb_log_fn("Failed to open stdin\n");
+               return;
+       }
+       fputs(procinfo->process.pipe_stdin, in);
+       fflush(in);
+}
+
+static void process_setup_stdin_child(struct process_info *procinfo)
+{
+       if (procinfo->process.pipe_stdin) {
+               close(procinfo->stdin_pipe[1]);
+               dup2(procinfo->stdin_pipe[0], STDIN_FILENO);
+       }
+}
 static void process_setup_stdout_parent(struct process_info *procinfo)
 {
        if (!procinfo->process.keep_stdout || procinfo->process.raw_stdout)
                return;
 
        close(procinfo->stdout_pipe[1]);
 static void process_setup_stdout_parent(struct process_info *procinfo)
 {
        if (!procinfo->process.keep_stdout || procinfo->process.raw_stdout)
                return;
 
        close(procinfo->stdout_pipe[1]);
+
 }
 
 static void process_setup_stdout_child(struct process_info *procinfo)
 }
 
 static void process_setup_stdout_child(struct process_info *procinfo)
@@ -178,28 +204,7 @@ static int process_read_stdout(struct process_info *procinfo)
        return rc < 0 ? rc : 0;
 }
 
        return rc < 0 ? rc : 0;
 }
 
-static int process_stdout_cb(void *arg)
-{
-       struct process_info *procinfo = arg;
-       int rc;
-
-       rc = process_read_stdout_once(procinfo, NULL);
-
-       /* if we're going to signal to the waitset that we're done (ie, non-zero
-        * return value), then the waiters will remove us, so we drop the
-        * reference */
-       if (rc < 0) {
-               talloc_unlink(procset, procinfo);
-               procinfo->stdout_waiter = NULL;
-               rc = -1;
-       } else {
-               rc = 0;
-       }
-
-       return rc;
-}
-
-int process_stdout_custom(struct process_info *procinfo, char **line)
+int process_process_stdout(struct process_info *procinfo, char **line)
 {
        int rc;
 
 {
        int rc;
 
@@ -371,6 +376,11 @@ static int process_run_common(struct process_info *procinfo)
        rc = process_setup_stdout_pipe(procinfo);
        if (rc)
                return rc;
        rc = process_setup_stdout_pipe(procinfo);
        if (rc)
                return rc;
+       if (procinfo->process.pipe_stdin) {
+               rc = pipe(procinfo->stdin_pipe);
+               if (rc)
+                       return rc;
+       }
 
        pid = fork();
        if (pid < 0) {
 
        pid = fork();
        if (pid < 0) {
@@ -380,6 +390,7 @@ static int process_run_common(struct process_info *procinfo)
 
        if (pid == 0) {
                process_setup_stdout_child(procinfo);
 
        if (pid == 0) {
                process_setup_stdout_child(procinfo);
+               process_setup_stdin_child(procinfo);
                if (procset->dry_run)
                        exit(EXIT_SUCCESS);
                execvp(process->path, (char * const *)process->argv);
                if (procset->dry_run)
                        exit(EXIT_SUCCESS);
                execvp(process->path, (char * const *)process->argv);
@@ -387,6 +398,7 @@ static int process_run_common(struct process_info *procinfo)
        }
 
        process_setup_stdout_parent(procinfo);
        }
 
        process_setup_stdout_parent(procinfo);
+       process_setup_stdin_parent(procinfo);
        process->pid = pid;
 
        return 0;
        process->pid = pid;
 
        return 0;
@@ -417,10 +429,14 @@ int process_run_sync(struct process *process)
        return 0;
 }
 
        return 0;
 }
 
+static int process_stdout_cb(struct process_info *procinfo)
+{
+       return process_process_stdout(procinfo, NULL);
+}
+
 int process_run_async(struct process *process)
 {
        struct process_info *procinfo = get_info(process);
 int process_run_async(struct process *process)
 {
        struct process_info *procinfo = get_info(process);
-       waiter_cb stdout_cb;
        int rc;
 
        rc = process_run_common(procinfo);
        int rc;
 
        rc = process_run_common(procinfo);
@@ -428,7 +444,8 @@ int process_run_async(struct process *process)
                return rc;
 
        if (process->keep_stdout) {
                return rc;
 
        if (process->keep_stdout) {
-               stdout_cb = process->stdout_cb ?: process_stdout_cb;
+               waiter_cb stdout_cb = process->stdout_cb ?:
+                       (waiter_cb)process_stdout_cb;
                procinfo->stdout_waiter = waiter_register_io(procset->waitset,
                                                procinfo->stdout_pipe[0],
                                                WAIT_IN, stdout_cb, procinfo);
                procinfo->stdout_waiter = waiter_register_io(procset->waitset,
                                                procinfo->stdout_pipe[0],
                                                WAIT_IN, stdout_cb, procinfo);
@@ -468,48 +485,76 @@ void process_stop_async_all(void)
        }
 }
 
        }
 }
 
-int process_run_simple_argv(void *ctx, const char *argv[])
+int process_get_stdout_argv(void *ctx, struct process_stdout **stdout,
+       const char *argv[])
 {
 {
-       struct process *process;
+       struct process *p;
        int rc;
 
        int rc;
 
-       process = process_create(ctx);
+       p = process_create(NULL);
+       p->path = argv[0];
+       p->argv = argv;
 
 
-       process->path = argv[0];
-       process->argv = argv;
+       if (stdout) {
+               p->keep_stdout = true;
+               *stdout = NULL;
+       }
 
 
-       rc = process_run_sync(process);
+       rc = process_run_sync(p);
 
        if (!rc)
 
        if (!rc)
-               rc = process->exit_status;
+               rc = p->exit_status;
+       else {
+               pb_debug("%s: process_run_sync failed: %s.\n", __func__,
+                       p->path);
+               if (stdout)
+                       pb_debug("%s: stdout: %s\n\n", __func__, p->stdout_buf);
+               goto exit;
+       }
+
+       if (!stdout)
+               goto exit;
+
+       *stdout = talloc(ctx, struct process_stdout);
+
+       if (!*stdout) {
+               rc = -1;
+               goto exit;
+       }
 
 
-       process_release(process);
+       (*stdout)->len = p->stdout_len;
+       (*stdout)->buf = talloc_memdup(*stdout, p->stdout_buf,
+               p->stdout_len + 1);
+       (*stdout)->buf[p->stdout_len] = 0;
 
 
+exit:
+       process_release(p);
        return rc;
 }
 
        return rc;
 }
 
-int process_run_simple(void *ctx, const char *name, ...)
+int process_get_stdout(void *ctx, struct process_stdout **stdout,
+       const char *path, ...)
 {
        int rc, i, n_argv = 1;
        const char **argv;
        va_list ap;
 
 {
        int rc, i, n_argv = 1;
        const char **argv;
        va_list ap;
 
-       va_start(ap, name);
+       va_start(ap, path);
        while (va_arg(ap, char *))
                n_argv++;
        va_end(ap);
 
        argv = talloc_array(ctx, const char *, n_argv + 1);
        while (va_arg(ap, char *))
                n_argv++;
        va_end(ap);
 
        argv = talloc_array(ctx, const char *, n_argv + 1);
-       argv[0] = name;
+       argv[0] = path;
 
 
-       va_start(ap, name);
+       va_start(ap, path);
        for (i = 1; i < n_argv; i++)
                argv[i] = va_arg(ap, const char *);
        va_end(ap);
 
        argv[i] = NULL;
 
        for (i = 1; i < n_argv; i++)
                argv[i] = va_arg(ap, const char *);
        va_end(ap);
 
        argv[i] = NULL;
 
-       rc = process_run_simple_argv(ctx, argv);
+       rc = process_get_stdout_argv(ctx, stdout, argv);
 
        talloc_free(argv);
 
 
        talloc_free(argv);