>From 1813b2df03ff6a4fe36d72c46827cf380185ca38 Mon Sep 17 00:00:00 2001 From: Richard W.M. Jones Date: Fri, 6 Nov 2009 13:19:26 +0000 Subject: [PATCH 1/2] daemon: Add flags argument to command*() functions. This adds new variations of the command*() functions which take a 'flags' argument. Currently the only flag available is defined as follows: COMMAND_FLAG_FOLD_STDOUT_ON_STDERR: For broken external commands that send error messages to stdout (hello, parted) but that don't have any useful stdout information, use this flag to capture the error messages in the *stderror buffer. If using this flag, you should pass stdoutput as NULL because nothing could ever be captured in that buffer. This patch also adds some documentation for command*() function. --- daemon/daemon.h | 21 +++++++++++++++------ daemon/guestfsd.c | 48 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/daemon/daemon.h b/daemon/daemon.h index 86c6876..f082690 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -47,12 +47,21 @@ extern void sort_strings (char **argv, int len); extern void free_strings (char **argv); extern void free_stringslen (char **argv, int len); -extern int command (char **stdoutput, char **stderror, const char *name, ...); -extern int commandr (char **stdoutput, char **stderror, const char *name, ...); -extern int commandv (char **stdoutput, char **stderror, - char *const *argv); -extern int commandrv (char **stdoutput, char **stderror, - char const* const *argv); +#define command(out,err,name,...) commandf((out),(err),0,(name),__VA_ARGS__) +#define commandr(out,err,name,...) commandrf((out),(err),0,(name),__VA_ARGS__) +#define commandv(out,err,argv) commandvf((out),(err),0,(argv)) +#define commandrv(out,err,argv) commandrvf((out),(err),0,(argv)) + +#define COMMAND_FLAG_FOLD_STDOUT_ON_STDERR 1 + +extern int commandf (char **stdoutput, char **stderror, int flags, + const char *name, ...); +extern int commandrf (char **stdoutput, char **stderror, int flags, + const char *name, ...); +extern int commandvf (char **stdoutput, char **stderror, int flags, + char *const *argv); +extern int commandrvf (char **stdoutput, char **stderror, int flags, + char const* const *argv); extern char **split_lines (char *str); diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 649a630..bf06c73 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -508,13 +508,11 @@ free_stringslen (char **argv, int len) free (argv); } -/* This is a more sane version of 'system(3)' for running external - * commands. It uses fork/execvp, so we don't need to worry about - * quoting of parameters, and it allows us to capture any error - * messages in a buffer. +/* Easy ways to run external commands. For full documentation, see + * 'commandrvf' below. */ int -command (char **stdoutput, char **stderror, const char *name, ...) +commandf (char **stdoutput, char **stderror, int flags, const char *name, ...) { va_list args; const char **argv; @@ -548,7 +546,7 @@ command (char **stdoutput, char **stderror, const char *name, ...) va_end (args); - r = commandv (stdoutput, stderror, (char **) argv); + r = commandvf (stdoutput, stderror, flags, (char **) argv); /* NB: Mustn't free the strings which are on the stack. */ free (argv); @@ -561,7 +559,7 @@ command (char **stdoutput, char **stderror, const char *name, ...) * We still return -1 if there was some other error. */ int -commandr (char **stdoutput, char **stderror, const char *name, ...) +commandrf (char **stdoutput, char **stderror, int flags, const char *name, ...) { va_list args; const char **argv; @@ -595,7 +593,7 @@ commandr (char **stdoutput, char **stderror, const char *name, ...) va_end (args); - r = commandrv (stdoutput, stderror, argv); + r = commandrvf (stdoutput, stderror, flags, argv); /* NB: Mustn't free the strings which are on the stack. */ free (argv); @@ -605,19 +603,42 @@ commandr (char **stdoutput, char **stderror, const char *name, ...) /* Same as 'command', but passing an argv. */ int -commandv (char **stdoutput, char **stderror, char *const *argv) +commandvf (char **stdoutput, char **stderror, int flags, char *const *argv) { int r; - r = commandrv (stdoutput, stderror, (void *) argv); + r = commandrvf (stdoutput, stderror, flags, (void *) argv); if (r == 0) return 0; else return -1; } +/* This is a more sane version of 'system(3)' for running external + * commands. It uses fork/execvp, so we don't need to worry about + * quoting of parameters, and it allows us to capture any error + * messages in a buffer. + * + * If stdoutput is not NULL, then *stdoutput will return the stdout + * of the command. + * + * If stderror is not NULL, then *stderror will return the stderr + * of the command. If there is a final \n character, it is removed + * so you can use the error string directly in a call to + * reply_with_error. + * + * Flags: + * + * COMMAND_FLAG_FOLD_STDOUT_ON_STDERR: For broken external commands + * that send error messages to stdout (hello, parted) but that don't + * have any useful stdout information, use this flag to capture the + * error messages in the *stderror buffer. If using this flag, + * you should pass stdoutput as NULL because nothing could ever be + * captured in that buffer. + */ int -commandrv (char **stdoutput, char **stderror, char const* const *argv) +commandrvf (char **stdoutput, char **stderror, int flags, + char const* const *argv) { int so_size = 0, se_size = 0; int so_fd[2], se_fd[2]; @@ -657,7 +678,10 @@ commandrv (char **stdoutput, char **stderror, char const* const *argv) open ("/dev/null", O_RDONLY); /* Set stdin to /dev/null (ignore failure) */ close (so_fd[0]); close (se_fd[0]); - dup2 (so_fd[1], 1); + if (!(flags & COMMAND_FLAG_FOLD_STDOUT_ON_STDERR)) + dup2 (so_fd[1], 1); + else + dup2 (se_fd[1], 1); dup2 (se_fd[1], 2); close (so_fd[1]); close (se_fd[1]); -- 1.6.2.5