lib/process: Add process_get_stdout
authorGeoff Levand <geoff@infradead.org>
Thu, 2 Aug 2018 17:29:35 +0000 (17:29 +0000)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 7 Aug 2018 01:30:36 +0000 (11:30 +1000)
Add a new structure 'struct process_stdout' and optional parameter
'stdout' to the process_run_simple functions to allow the caller
to get a buffer filled with the stdout from the child process.

Rename the process_run_simple functions to process_get_stdout
and add wrappers for the old process_run_simple function names.

Signed-off-by: Geoff Levand <geoff@infradead.org>
Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
lib/process/process.c
lib/process/process.h

index bc392dc779510245a315c0061b4a14f5d3c06f24..02b6f490dad8318744ba8b4f43b30c6362ceae09 100644 (file)
@@ -452,48 +452,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;
 
-       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)
-               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;
 }
 
-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;
 
-       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);
-       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;
 
-       rc = process_run_simple_argv(ctx, argv);
+       rc = process_get_stdout_argv(ctx, stdout, argv);
 
        talloc_free(argv);
 
index 003ff8ed1329d282942b03bc7a56962d683e4192..9473a0d492b00e0e644b4e957fa78f1f8599764a 100644 (file)
@@ -27,6 +27,11 @@ struct process_info;
 
 typedef void   (*process_exit_cb)(struct process *);
 
+struct process_stdout {
+       size_t len;
+       char *buf;
+};
+
 struct process {
        /* caller-provided configuration */
        const char              *path;
@@ -63,13 +68,24 @@ struct process *process_create(void *ctx);
  */
 void process_release(struct process *process);
 
-/* Synchronous interface. These functions will all block while waiting for
- * the process to exit.
+/* Synchronous interface. The process_run_sync, process_run_simple and
+ * process_get_stdout functions will all block while waiting for the child
+ * process to exit.  Calls to the variadic versions must have a NULL terminating
+ * argument.  For the process_get_stdout calls stderr will go to the log.
  */
 int process_run_sync(struct process *process);
-int process_run_simple_argv(void *ctx, const char *argv[]);
-int process_run_simple(void *ctx, const char *name, ...)
-       __attribute__((sentinel(0)));
+int process_get_stdout_argv(void *ctx, struct process_stdout **stdout,
+       const char *argv[]);
+int process_get_stdout(void *ctx, struct process_stdout **stdout,
+       const char *path, ...) __attribute__((sentinel(0)));
+
+static inline int process_run_simple_argv(void *ctx, const char *argv[])
+{
+       return process_get_stdout_argv(ctx, NULL, argv);
+}
+#define process_run_simple(_ctx, _path, args...) \
+       process_get_stdout(_ctx, NULL, _path, args)
+
 
 /* Asynchronous interface. When a process is run with process_run_async, the
  * function returns without wait()ing for the child process to exit. If the