From 33527e065d9506e05f61c020a473544123c0601b Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 14 Jan 2014 15:44:10 +0800 Subject: [PATCH] lib/process: Add add_stderr flag to process module For some process execution functions, we'd like to capture stderr as well as stdout. Currently, we unconditionally redirect subprocess stderr to the petitboot log file. This change adds an add_stderr flag to struct process, which indicates to the process library that we want stderr as well as stdout. If this is specified, the subprocess' stderr is captured to stdout_buf. Signed-off-by: Jeremy Kerr --- lib/process/process.c | 5 ++- lib/process/process.h | 1 + test/lib/Makefile.am | 2 + test/lib/test-process-stderr-stdout.c | 57 +++++++++++++++++++++++++++ test/lib/test-process-stderr.c | 54 +++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 test/lib/test-process-stderr-stdout.c create mode 100644 test/lib/test-process-stderr.c diff --git a/lib/process/process.c b/lib/process/process.c index 1a16fb6..3c81b29 100644 --- a/lib/process/process.c +++ b/lib/process/process.c @@ -125,7 +125,10 @@ static void process_setup_stdout_child(struct process_info *procinfo) else dup2(log, STDOUT_FILENO); - dup2(log, STDERR_FILENO); + if (procinfo->process.keep_stdout && procinfo->process.add_stderr) + dup2(procinfo->stdout_pipe[1], STDERR_FILENO); + else + dup2(log, STDERR_FILENO); } static void process_finish_stdout(struct process_info *procinfo) diff --git a/lib/process/process.h b/lib/process/process.h index caeda92..ae7fe32 100644 --- a/lib/process/process.h +++ b/lib/process/process.h @@ -31,6 +31,7 @@ struct process { const char *path; const char **argv; bool keep_stdout; + bool add_stderr; process_exit_cb exit_cb; void *data; diff --git a/test/lib/Makefile.am b/test/lib/Makefile.am index 3606710..ae6027f 100644 --- a/test/lib/Makefile.am +++ b/test/lib/Makefile.am @@ -26,6 +26,8 @@ check_PROGRAMS = list-test \ test-process-noargs \ test-process-sync \ test-process-sync-stdout \ + test-process-stderr \ + test-process-stderr-stdout \ test-process-async \ test-process-async-stdout \ test-process-parent-stdout \ diff --git a/test/lib/test-process-stderr-stdout.c b/test/lib/test-process-stderr-stdout.c new file mode 100644 index 0000000..3192306 --- /dev/null +++ b/test/lib/test-process-stderr-stdout.c @@ -0,0 +1,57 @@ + +#include +#include +#include + +#include +#include +#include + +static int do_child(void) +{ + fprintf(stderr, "forty "); + fflush(stderr); + fprintf(stdout, "two\n"); + fflush(stdout); + return 42; +} + +int main(int argc, char **argv) +{ + struct waitset *waitset; + struct process *process; + const char *child_argv[3]; + void *ctx; + + if (argc == 2 && !strcmp(argv[1], "child")) + return do_child(); + + ctx = talloc_new(NULL); + + waitset = waitset_create(ctx); + + process_init(ctx, waitset, false); + + child_argv[0] = argv[0]; + child_argv[1] = "child"; + child_argv[2] = NULL; + + process = process_create(ctx); + process->path = child_argv[0]; + process->argv = child_argv; + process->keep_stdout = true; + process->add_stderr = true; + + process_run_sync(process); + + assert(WIFEXITED(process->exit_status)); + assert(WEXITSTATUS(process->exit_status) == 42); + + assert(process->stdout_len == strlen("forty two\n")); + assert(!memcmp(process->stdout_buf, "forty two\n", + process->stdout_len)); + + talloc_free(ctx); + + return EXIT_SUCCESS; +} diff --git a/test/lib/test-process-stderr.c b/test/lib/test-process-stderr.c new file mode 100644 index 0000000..a165caa --- /dev/null +++ b/test/lib/test-process-stderr.c @@ -0,0 +1,54 @@ + +#include +#include +#include + +#include +#include +#include + +static int do_child(void) +{ + fprintf(stderr, "forty two\n"); + return 42; +} + +int main(int argc, char **argv) +{ + struct waitset *waitset; + struct process *process; + const char *child_argv[3]; + void *ctx; + + if (argc == 2 && !strcmp(argv[1], "child")) + return do_child(); + + ctx = talloc_new(NULL); + + waitset = waitset_create(ctx); + + process_init(ctx, waitset, false); + + child_argv[0] = argv[0]; + child_argv[1] = "child"; + child_argv[2] = NULL; + + process = process_create(ctx); + process->path = child_argv[0]; + process->argv = child_argv; + process->keep_stdout = true; + process->add_stderr = true; + + process_run_sync(process); + + assert(WIFEXITED(process->exit_status)); + assert(WEXITSTATUS(process->exit_status) == 42); + + assert(process->stdout_len == strlen("forty two\n")); + assert(!memcmp(process->stdout_buf, "forty two\n", + process->stdout_len)); + + talloc_free(ctx); + + return EXIT_SUCCESS; +} -- 2.39.2