X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=daemon%2Fguestfsd.c;h=2553ea2cd3046aae2828f886a1011aac2e7ebeb4;hp=6730c1d23b3fbeb400f4106a5cb587235ac68910;hb=aef3d2013fee188c9607f35657c45df88503cd64;hpb=1cf85b1e60e85c4940869c6291d75ac44a5bd190 diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 6730c1d..2553ea2 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -41,6 +41,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 +65,7 @@ main (int argc, char *argv[]) struct addrinfo *res, *rr; struct addrinfo hints; XDR xdr; - unsigned len; + uint32_t len; for (;;) { c = getopt_long (argc, argv, options, long_options, NULL); @@ -108,6 +110,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) { @@ -163,14 +173,14 @@ 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"); exit (1); } - xwrite (sock, buf, xdr_getpos (&xdr)); + (void) xwrite (sock, buf, xdr_getpos (&xdr)); xdr_destroy (&xdr); @@ -188,7 +198,7 @@ main (int argc, char *argv[]) exit (0); } -void +int xwrite (int sock, const void *buf, size_t len) { int r; @@ -197,14 +207,16 @@ xwrite (int sock, const void *buf, size_t len) r = write (sock, buf, len); if (r == -1) { perror ("write"); - exit (1); + return -1; } buf += r; len -= r; } + + return 0; } -void +int xread (int sock, void *buf, size_t len) { int r; @@ -213,15 +225,17 @@ xread (int sock, void *buf, size_t len) r = read (sock, buf, len); if (r == -1) { perror ("read"); - exit (1); + return -1; } if (r == 0) { - fprintf (stderr, "read: unexpected end of file on comms socket\n"); - exit (1); + fprintf (stderr, "read: unexpected end of file on fd %d\n", sock); + return -1; } buf += r; len -= r; } + + return 0; } static void @@ -263,7 +277,7 @@ add_string (char ***argv, int *size, int *alloc, const char *str) } int -count_strings (char **argv) +count_strings (char * const* const argv) { int argc; @@ -272,6 +286,20 @@ count_strings (char **argv) return argc; } +static int +compare (const void *vp1, const void *vp2) +{ + char * const *p1 = (char * const *) vp1; + char * const *p2 = (char * const *) vp2; + return strcmp (*p1, *p2); +} + +void +sort_strings (char **argv, int len) +{ + qsort (argv, len, sizeof (char *), compare); +} + void free_strings (char **argv) { @@ -282,6 +310,16 @@ free_strings (char **argv) free (argv); } +void +free_stringslen (char **argv, int len) +{ + int i; + + for (i = 0; i < len; ++i) + free (argv[i]); + 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 @@ -290,15 +328,54 @@ free_strings (char **argv) int command (char **stdoutput, char **stderror, const char *name, ...) { + va_list args; + char **argv; + char *s; + int i, r; + + /* Collect the command line arguments into an array. */ + va_start (args, name); + + i = 2; + argv = malloc (sizeof (char *) * i); + argv[0] = (char *) name; + argv[1] = NULL; + + while ((s = va_arg (args, char *)) != NULL) { + argv = realloc (argv, sizeof (char *) * (++i)); + 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; +} + +int +commandv (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; + int pid, r, quit, i; fd_set rset, rset2; char buf[256]; if (stdoutput) *stdoutput = NULL; if (stderror) *stderror = NULL; + 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"); return -1; @@ -311,25 +388,6 @@ command (char **stdoutput, char **stderror, const char *name, ...) } if (pid == 0) { /* Child process. */ - va_list args; - char **argv; - char *s; - int i; - - /* Collect the command line arguments into an array. */ - va_start (args, name); - - i = 2; - argv = malloc (sizeof (char *) * i); - argv[0] = (char *) name; - argv[1] = NULL; - - while ((s = va_arg (args, char *)) != NULL) { - argv = realloc (argv, sizeof (char *) * (++i)); - argv[i-2] = s; - argv[i-1] = NULL; - } - close (0); close (so_fd[0]); close (se_fd[0]); @@ -338,8 +396,8 @@ command (char **stdoutput, char **stderror, const char *name, ...) close (so_fd[1]); close (se_fd[1]); - execvp (name, argv); - perror (name); + execvp (argv[0], argv); + perror (argv[0]); _exit (1); } @@ -352,7 +410,7 @@ command (char **stdoutput, char **stderror, const char *name, ...) FD_SET (se_fd[0], &rset); quit = 0; - while (!quit) { + while (quit < 2) { rset2 = rset; r = select (MAX (so_fd[0], se_fd[0]) + 1, &rset2, NULL, NULL, NULL); if (r == -1) { @@ -368,7 +426,7 @@ command (char **stdoutput, char **stderror, const char *name, ...) waitpid (pid, NULL, 0); return -1; } - if (r == 0) quit = 1; + if (r == 0) { FD_CLR (so_fd[0], &rset); quit++; } if (r > 0 && stdoutput) { so_size += r; @@ -389,7 +447,7 @@ command (char **stdoutput, char **stderror, const char *name, ...) waitpid (pid, NULL, 0); return -1; } - if (r == 0) quit = 1; + if (r == 0) { FD_CLR (se_fd[0], &rset); quit++; } if (r > 0 && stderror) { se_size += r;