X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=daemon%2Fguestfsd.c;h=99055a92e2ad703a78df80fa589b3f0f6d4be4fa;hp=a9576836b0d7ea35339933f68cb9a8cef29888ef;hb=e118c14b9552de311cbc1734e03a3226b484c1e8;hpb=2069ade88144d8efd272a74be24b5c9ff49844dc diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index a957683..99055a9 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "daemon.h" @@ -66,6 +68,7 @@ main (int argc, char *argv[]) struct addrinfo hints; XDR xdr; uint32_t len; + struct sigaction sa; for (;;) { c = getopt_long (argc, argv, options, long_options, NULL); @@ -140,6 +143,13 @@ main (int argc, char *argv[]) port = VMCHANNEL_PORT; } + /* Make sure SIGPIPE doesn't kill us. */ + memset (&sa, 0, sizeof sa); + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + if (sigaction (SIGPIPE, &sa, NULL) == -1) + perror ("sigaction SIGPIPE"); /* but try to continue anyway ... */ + /* Resolve the hostname. */ memset (&hints, 0, sizeof hints); hints.ai_socktype = SOCK_STREAM; @@ -329,27 +339,85 @@ int command (char **stdoutput, char **stderror, const char *name, ...) { va_list args; - char **argv; + char **argv, **p; char *s; int i, r; /* Collect the command line arguments into an array. */ + i = 2; + argv = malloc (sizeof (char *) * i); + if (argv == NULL) { + perror ("malloc"); + return -1; + } + argv[0] = (char *) name; + argv[1] = NULL; + va_start (args, name); + while ((s = va_arg (args, char *)) != NULL) { + p = realloc (argv, sizeof (char *) * (++i)); + if (p == NULL) { + perror ("realloc"); + free (argv); + va_end (args); + return -1; + } + argv = p; + argv[i-2] = s; + argv[i-1] = NULL; + } + + va_end (args); + + r = commandv (stdoutput, stderror, argv); + + /* NB: Mustn't free the strings which are on the stack. */ + free (argv); + + return r; +} + +/* Same as 'command', but we allow the status code from the + * subcommand to be non-zero, and return that status code. + * We still return -1 if there was some other error. + */ +int +commandr (char **stdoutput, char **stderror, const char *name, ...) +{ + va_list args; + char **argv, **p; + char *s; + int i, r; + + /* Collect the command line arguments into an array. */ i = 2; argv = malloc (sizeof (char *) * i); + if (argv == NULL) { + perror ("malloc"); + return -1; + } argv[0] = (char *) name; argv[1] = NULL; + va_start (args, name); + while ((s = va_arg (args, char *)) != NULL) { - argv = realloc (argv, sizeof (char *) * (++i)); + p = realloc (argv, sizeof (char *) * (++i)); + if (p == NULL) { + perror ("realloc"); + free (argv); + va_end (args); + return -1; + } + argv = p; argv[i-2] = s; argv[i-1] = NULL; } va_end (args); - r = commandv (stdoutput, stderror, argv); + r = commandrv (stdoutput, stderror, argv); /* NB: Mustn't free the strings which are on the stack. */ free (argv); @@ -357,9 +425,22 @@ command (char **stdoutput, char **stderror, const char *name, ...) return r; } +/* Same as 'command', but passing an argv. */ int commandv (char **stdoutput, char **stderror, char * const* const argv) { + int r; + + r = commandrv (stdoutput, stderror, argv); + if (r == 0) + return 0; + else + return -1; +} + +int +commandrv (char **stdoutput, char **stderror, char * const* const argv) +{ int so_size = 0, se_size = 0; int so_fd[2], se_fd[2]; int pid, r, quit, i; @@ -503,10 +584,44 @@ commandv (char **stdoutput, char **stderror, char * const* const argv) waitpid (pid, &r, 0); if (WIFEXITED (r)) { - if (WEXITSTATUS (r) == 0) - return 0; - else - return -1; + return WEXITSTATUS (r); } else return -1; } + +/* Quote 'in' for the shell, and write max len-1 bytes to out. The + * result will be NUL-terminated, even if it is truncated. + * + * Returns number of bytes needed, so if result >= len then the buffer + * should have been longer. + * + * XXX This doesn't quote \n correctly (but is still safe). + */ +int +shell_quote (char *out, int len, const char *in) +{ +#define SAFE(c) (isalnum((c)) || \ + (c) == '/' || (c) == '-' || (c) == '_' || (c) == '.') + int i, j; + int outlen = strlen (in); + + /* Calculate how much output space this really needs. */ + for (i = 0; in[i]; ++i) + if (!SAFE (in[i])) outlen++; + + /* Now copy the string, but only up to len-1 bytes. */ + for (i = 0, j = 0; in[i]; ++i) { + int is_safe = SAFE (in[i]); + + /* Enough space left to write this character? */ + if (j >= len-1 || (!is_safe && j >= len-2)) + break; + + if (!is_safe) out[j++] = '\\'; + out[j++] = in[i]; + } + + out[j] = '\0'; + + return outlen; +}