X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=daemon%2Fguestfsd.c;h=db0bff926de99cb89d4003e6c5ed3c9a9917aa42;hb=b296287daf9b884aa38646717725f5a389f96ca5;hp=8c39c39c66b3ae39b62b53a610220008eec2e74f;hpb=6a14f1c2502f58ff7bed8cb451f95a83f5ee920a;p=libguestfs.git diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 8c39c39..db0bff9 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -38,6 +38,8 @@ #include #include "c-ctype.h" +#include "ignore-value.h" + #include "daemon.h" static char *read_cmdline (void); @@ -224,7 +226,7 @@ main (int argc, char *argv[]) /* Connect to vmchannel. */ int sock = -1; - if (strncmp (vmchannel, "tcp:", 4) == 0) { + if (STREQLEN (vmchannel, "tcp:", 4)) { /* Resolve the hostname. */ struct addrinfo *res, *rr; struct addrinfo hints; @@ -508,13 +510,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 +548,7 @@ command (char **stdoutput, char **stderror, const char *name, ...) va_end (args); - r = commandv (stdoutput, stderror, (char **) argv); + r = commandvf (stdoutput, stderror, flags, (const char * const*) argv); /* NB: Mustn't free the strings which are on the stack. */ free (argv); @@ -561,7 +561,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 +595,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 +605,43 @@ 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 *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]; @@ -654,9 +678,13 @@ commandrv (char **stdoutput, char **stderror, char const* const *argv) if (pid == 0) { /* Child process. */ close (0); + 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]); @@ -717,15 +745,20 @@ commandrv (char **stdoutput, char **stderror, char const* const *argv) } if (r == 0) { FD_CLR (se_fd[0], &rset); quit++; } - if (r > 0 && stderror) { - se_size += r; - p = realloc (*stderror, se_size); - if (p == NULL) { - perror ("realloc"); - goto quit; + if (r > 0) { + if (verbose) + ignore_value (write (2, buf, r)); + + if (stderror) { + se_size += r; + p = realloc (*stderror, se_size); + if (p == NULL) { + perror ("realloc"); + goto quit; + } + *stderror = p; + memcpy (*stderror + se_size - r, buf, r); } - *stderror = p; - memcpy (*stderror + se_size - r, buf, r); } } } @@ -798,7 +831,7 @@ split_lines (char *str) int size = 0, alloc = 0; char *p, *pend; - if (strcmp (str, "") == 0) + if (STREQ (str, "")) goto empty_list; p = str; @@ -912,7 +945,7 @@ device_name_translation (char *device, const char *func) } /* If the name begins with "/dev/sd" then try the alternatives. */ - if (strncmp (device, "/dev/sd", 7) != 0) + if (STRNEQLEN (device, "/dev/sd", 7)) goto error; device[5] = 'h'; /* /dev/hd (old IDE driver) */