Rearrange and tidy up code in guestfsd.c
[libguestfs.git] / daemon / guestfsd.c
index b013661..b4fb15e 100644 (file)
 #include "daemon.h"
 
 static void usage (void);
+static char *read_cmdline (void);
 
 /* Also in guestfs.c */
-#define VMCHANNEL_PORT "6666"
-#define VMCHANNEL_ADDR "10.0.2.4"
+#define GUESTFWD_ADDR "10.0.2.4"
+#define GUESTFWD_PORT "6666"
 
 int verbose = 0;
 
@@ -67,27 +68,15 @@ int sysroot_len = 8;
 int
 main (int argc, char *argv[])
 {
-  static const char *options = "fh:p:?";
+  static const char *options = "f?";
   static const struct option long_options[] = {
     { "foreground", 0, 0, 'f' },
     { "help", 0, 0, '?' },
-    { "host", 1, 0, 'h' },
-    { "port", 1, 0, 'p' },
     { 0, 0, 0, 0 }
   };
-  int c, n, r;
+  int c;
   int dont_fork = 0;
-  const char *host = NULL;
-  const char *port = NULL;
-  FILE *fp;
-  char buf[4096];
-  char *p, *p2;
-  int sock;
-  struct addrinfo *res, *rr;
-  struct addrinfo hints;
-  XDR xdr;
-  uint32_t len;
-  struct sigaction sa;
+  char *cmdline;
 
 #ifdef HAVE_REGISTER_PRINTF_SPECIFIER
   /* http://udrepper.livejournal.com/20948.html */
@@ -111,14 +100,6 @@ main (int argc, char *argv[])
       dont_fork = 1;
       break;
 
-    case 'h':
-      host = optarg;
-      break;
-
-    case 'p':
-      port = optarg;
-      break;
-
     case '?':
       usage ();
       exit (0);
@@ -134,48 +115,22 @@ main (int argc, char *argv[])
     exit (1);
   }
 
-  /* If host and port aren't set yet, try /proc/cmdline. */
-  if (!host || !port) {
-    fp = fopen ("/proc/cmdline", "r");
-    if (fp == NULL) {
-      perror ("/proc/cmdline");
-      goto next;
-    }
-    n = fread (buf, 1, sizeof buf - 1, fp);
-    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) {
-      p += 8;
-      p2 = strchr (p, ':');
-      if (p2) {
-        *p2++ = '\0';
-        host = p;
-        r = strcspn (p2, " \n");
-        p2[r] = '\0';
-        port = p2;
-      }
-    }
-  }
+  cmdline = read_cmdline ();
 
- next:
-  /* Can't parse /proc/cmdline, so use built-in defaults. */
-  if (!host || !port) {
-    host = VMCHANNEL_ADDR;
-    port = VMCHANNEL_PORT;
+  /* Set the verbose flag. */
+  verbose = cmdline && strstr (cmdline, "guestfs_verbose=1") != NULL;
+  if (verbose)
+    printf ("verbose daemon enabled\n");
+
+  if (verbose) {
+    if (cmdline)
+      printf ("linux commmand line: %s\n", cmdline);
+    else
+      printf ("could not read linux command line\n");
   }
 
   /* Make sure SIGPIPE doesn't kill us. */
+  struct sigaction sa;
   memset (&sa, 0, sizeof sa);
   sa.sa_handler = SIG_IGN;
   sa.sa_flags = 0;
@@ -194,17 +149,21 @@ main (int argc, char *argv[])
   umask (022);
 
   /* Resolve the hostname. */
+  struct addrinfo *res, *rr;
+  struct addrinfo hints;
+  int r;
   memset (&hints, 0, sizeof hints);
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_flags = AI_ADDRCONFIG;
-  r = getaddrinfo (host, port, &hints, &res);
+  r = getaddrinfo (GUESTFWD_ADDR, GUESTFWD_PORT, &hints, &res);
   if (r != 0) {
-    fprintf (stderr, "%s:%s: %s\n", host, port, gai_strerror (r));
+    fprintf (stderr, "%s:%s: %s\n",
+             GUESTFWD_ADDR, GUESTFWD_PORT, gai_strerror (r));
     exit (1);
   }
 
   /* Connect to the given TCP socket. */
-  sock = -1;
+  int sock = -1;
   for (rr = res; rr != NULL; rr = rr->ai_next) {
     sock = socket (rr->ai_family, rr->ai_socktype, rr->ai_protocol);
     if (sock != -1) {
@@ -219,21 +178,22 @@ main (int argc, char *argv[])
   freeaddrinfo (res);
 
   if (sock == -1) {
-    fprintf (stderr, "connection to %s:%s failed\n", host, port);
+    fprintf (stderr, "connection to %s:%s failed\n",
+             GUESTFWD_ADDR, GUESTFWD_PORT);
     exit (1);
   }
 
   /* Send the magic length message which indicates that
    * userspace is up inside the guest.
    */
-  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);
-  }
+  char lenbuf[4];
+  XDR xdr;
+  uint32_t len = GUESTFS_LAUNCH_FLAG;
+  xdrmem_create (&xdr, lenbuf, sizeof lenbuf, XDR_ENCODE);
+  xdr_uint32_t (&xdr, &len);
 
-  (void) xwrite (sock, buf, xdr_getpos (&xdr));
+  if (xwrite (sock, lenbuf, sizeof lenbuf) == -1)
+    exit (1);
 
   xdr_destroy (&xdr);
 
@@ -251,6 +211,55 @@ main (int argc, char *argv[])
   exit (0);
 }
 
+/* Read /proc/cmdline. */
+static char *
+read_cmdline (void)
+{
+  int fd = open ("/proc/cmdline", O_RDONLY);
+  if (fd == -1) {
+    perror ("/proc/cmdline");
+    return NULL;
+  }
+
+  size_t len = 0;
+  ssize_t n;
+  char buf[256];
+  char *r = NULL;
+
+  for (;;) {
+    n = read (fd, buf, sizeof buf);
+    if (n == -1) {
+      perror ("read");
+      free (r);
+      close (fd);
+      return NULL;
+    }
+    if (n == 0)
+      break;
+    char *newr = realloc (r, len + n + 1); /* + 1 is for terminating NUL */
+    if (newr == NULL) {
+      perror ("realloc");
+      free (r);
+      close (fd);
+      return NULL;
+    }
+    r = newr;
+    memcpy (&r[len], buf, n);
+    len += n;
+  }
+
+  if (r)
+    r[len] = '\0';
+
+  if (close (fd) == -1) {
+    perror ("close");
+    free (r);
+    return NULL;
+  }
+
+  return r;
+}
+
 /* Turn "/path" into "/sysroot/path".
  *
  * Caller must check for NULL and call reply_with_perror ("malloc")
@@ -273,9 +282,10 @@ sysroot_path (const char *path)
 }
 
 int
-xwrite (int sock, const void *buf, size_t len)
+xwrite (int sock, const void *v_buf, size_t len)
 {
   int r;
+  const char *buf = v_buf;
 
   while (len > 0) {
     r = write (sock, buf, len);
@@ -291,9 +301,10 @@ xwrite (int sock, const void *buf, size_t len)
 }
 
 int
-xread (int sock, void *buf, size_t len)
+xread (int sock, void *v_buf, size_t len)
 {
   int r;
+  char *buf = v_buf;
 
   while (len > 0) {
     r = read (sock, buf, len);
@@ -315,7 +326,7 @@ xread (int sock, void *buf, size_t len)
 static void
 usage (void)
 {
-  fprintf (stderr, "guestfsd [-f] [-h host -p port]\n");
+  fprintf (stderr, "guestfsd [-f]\n");
 }
 
 int
@@ -351,7 +362,7 @@ add_string (char ***argv, int *size, int *alloc, const char *str)
 }
 
 int
-count_strings (char * const* const argv)
+count_strings (char *const *argv)
 {
   int argc;
 
@@ -403,7 +414,7 @@ int
 command (char **stdoutput, char **stderror, const char *name, ...)
 {
   va_list args;
-  char **argv, **p;
+  const char **argv;
   char *s;
   int i, r;
 
@@ -420,7 +431,7 @@ command (char **stdoutput, char **stderror, const char *name, ...)
   va_start (args, name);
 
   while ((s = va_arg (args, char *)) != NULL) {
-    p = realloc (argv, sizeof (char *) * (++i));
+    const char **p = realloc (argv, sizeof (char *) * (++i));
     if (p == NULL) {
       perror ("realloc");
       free (argv);
@@ -434,7 +445,7 @@ command (char **stdoutput, char **stderror, const char *name, ...)
 
   va_end (args);
 
-  r = commandv (stdoutput, stderror, argv);
+  r = commandv (stdoutput, stderror, (char **) argv);
 
   /* NB: Mustn't free the strings which are on the stack. */
   free (argv);
@@ -450,7 +461,7 @@ int
 commandr (char **stdoutput, char **stderror, const char *name, ...)
 {
   va_list args;
-  char **argv, **p;
+  const char **argv;
   char *s;
   int i, r;
 
@@ -467,7 +478,7 @@ commandr (char **stdoutput, char **stderror, const char *name, ...)
   va_start (args, name);
 
   while ((s = va_arg (args, char *)) != NULL) {
-    p = realloc (argv, sizeof (char *) * (++i));
+    const char **p = realloc (argv, sizeof (char *) * (++i));
     if (p == NULL) {
       perror ("realloc");
       free (argv);
@@ -491,11 +502,11 @@ commandr (char **stdoutput, char **stderror, const char *name, ...)
 
 /* Same as 'command', but passing an argv. */
 int
-commandv (char **stdoutput, char **stderror, char * const* const argv)
+commandv (char **stdoutput, char **stderror, char *const *argv)
 {
   int r;
 
-  r = commandrv (stdoutput, stderror, argv);
+  r = commandrv (stdoutput, stderror, (void *) argv);
   if (r == 0)
     return 0;
   else
@@ -503,7 +514,7 @@ commandv (char **stdoutput, char **stderror, char * const* const argv)
 }
 
 int
-commandrv (char **stdoutput, char **stderror, char * const* const argv)
+commandrv (char **stdoutput, char **stderror, char const* const *argv)
 {
   int so_size = 0, se_size = 0;
   int so_fd[2], se_fd[2];
@@ -547,7 +558,7 @@ commandrv (char **stdoutput, char **stderror, char * const* const argv)
     close (so_fd[1]);
     close (se_fd[1]);
 
-    execvp (argv[0], argv);
+    execvp (argv[0], (void *) argv);
     perror (argv[0]);
     _exit (1);
   }
@@ -743,8 +754,6 @@ print_sysroot_shell_quote (FILE *stream,
                            const struct printf_info *info,
                            const void *const *args)
 {
-#define SAFE(c) (isalnum((c)) ||                                       \
-                 (c) == '/' || (c) == '-' || (c) == '_' || (c) == '.')
   fputs (sysroot, stream);
   return sysroot_len + print_shell_quote (stream, info, args);
 }