X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=daemon%2Fguestfsd.c;h=ba4035ea48de324194374178b6e456c102956fcf;hb=f7e6ffa8a82f8a7a214a47ff32f46d9e893902d8;hp=c701f194a558546defa2d4cafc67c6cfb010ab25;hpb=b4d2a01828e5de85e5eee3631f7fe3925a0312ca;p=libguestfs.git diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index c701f19..ba4035e 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "daemon.h" @@ -41,6 +43,8 @@ static void usage (void); #define VMCHANNEL_PORT "6666" #define VMCHANNEL_ADDR "10.0.2.4" +int verbose = 0; + int main (int argc, char *argv[]) { @@ -63,7 +67,8 @@ main (int argc, char *argv[]) struct addrinfo *res, *rr; struct addrinfo hints; XDR xdr; - unsigned len; + uint32_t len; + struct sigaction sa; for (;;) { c = getopt_long (argc, argv, options, long_options, NULL); @@ -108,6 +113,14 @@ main (int argc, char *argv[]) fclose (fp); buf[n] = '\0'; + /* Set the verbose flag. Not quite right because this will only + * set the flag if host and port aren't set on the command line. + * Don't worry about this for now. (XXX) + */ + verbose = strstr (buf, "guestfs_verbose=1") != NULL; + if (verbose) + printf ("verbose daemon enabled\n"); + p = strstr (buf, "guestfs="); if (p) { @@ -130,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; @@ -163,7 +183,7 @@ main (int argc, char *argv[]) /* Send the magic length message which indicates that * userspace is up inside the guest. */ - len = 0xf5f55ff5; + len = GUESTFS_LAUNCH_FLAG; xdrmem_create (&xdr, buf, sizeof buf, XDR_ENCODE); if (!xdr_uint32_t (&xdr, &len)) { fprintf (stderr, "xdr_uint32_t failed\n"); @@ -319,20 +339,31 @@ 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. */ - va_start (args, name); - 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; } @@ -359,10 +390,12 @@ commandv (char **stdoutput, char **stderror, char * const* const argv) if (stdoutput) *stdoutput = NULL; if (stderror) *stderror = NULL; - printf ("%s", argv[0]); - for (i = 1; argv[i] != NULL; ++i) - printf (" %s", argv[i]); - printf ("\n"); + if (verbose) { + printf ("%s", argv[0]); + for (i = 1; argv[i] != NULL; ++i) + printf (" %s", argv[i]); + printf ("\n"); + } if (pipe (so_fd) == -1 || pipe (se_fd) == -1) { perror ("pipe"); @@ -372,6 +405,10 @@ commandv (char **stdoutput, char **stderror, char * const* const argv) pid = fork (); if (pid == -1) { perror ("fork"); + close (so_fd[0]); + close (so_fd[1]); + close (se_fd[0]); + close (se_fd[1]); return -1; } @@ -403,6 +440,8 @@ commandv (char **stdoutput, char **stderror, char * const* const argv) r = select (MAX (so_fd[0], se_fd[0]) + 1, &rset2, NULL, NULL, NULL); if (r == -1) { perror ("select"); + close (so_fd[0]); + close (se_fd[0]); waitpid (pid, NULL, 0); return -1; } @@ -411,6 +450,8 @@ commandv (char **stdoutput, char **stderror, char * const* const argv) r = read (so_fd[0], buf, sizeof buf); if (r == -1) { perror ("read"); + close (so_fd[0]); + close (se_fd[0]); waitpid (pid, NULL, 0); return -1; } @@ -432,6 +473,8 @@ commandv (char **stdoutput, char **stderror, char * const* const argv) r = read (se_fd[0], buf, sizeof buf); if (r == -1) { perror ("read"); + close (so_fd[0]); + close (se_fd[0]); waitpid (pid, NULL, 0); return -1; } @@ -450,6 +493,9 @@ commandv (char **stdoutput, char **stderror, char * const* const argv) } } + close (so_fd[0]); + close (se_fd[0]); + /* Make sure the output buffers are \0-terminated. Also remove any * trailing \n characters from the error buffer (not from stdout). */ @@ -485,3 +531,40 @@ commandv (char **stdoutput, char **stderror, char * const* const argv) } 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; +}