tools: Add basic tests for the virt-* tools.
[libguestfs.git] / src / guestfs.c
index 02d5fdb..e235fdc 100644 (file)
@@ -33,6 +33,7 @@
 #include <sys/stat.h>
 #include <sys/select.h>
 #include <dirent.h>
+#include <signal.h>
 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #define safe_strdup guestfs_safe_strdup
 //#define safe_memdup guestfs_safe_memdup
 
+#ifdef __linux__
+#define CAN_CHECK_PEER_EUID 1
+#else
+#define CAN_CHECK_PEER_EUID 0
+#endif
+
 static void default_error_cb (guestfs_h *g, void *data, const char *msg);
 static int send_to_daemon (guestfs_h *g, const void *v_buf, size_t n);
 static int recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn);
@@ -95,6 +102,14 @@ static int qemu_supports (guestfs_h *g, const char *option);
 
 #define UNIX_PATH_MAX 108
 
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#ifdef __APPLE__
+#define xdr_uint32_t xdr_u_int32_t
+#endif
+
 /* Also in guestfsd.c */
 #define GUESTFWD_ADDR "10.0.2.4"
 #define GUESTFWD_PORT "6666"
@@ -390,7 +405,7 @@ guestfs_perrorf (guestfs_h *g, const char *fs, ...)
 
   if (err < 0) return;
 
-#ifndef _GNU_SOURCE
+#if !defined(_GNU_SOURCE) || defined(__APPLE__)
   char buf[256];
   strerror_r (errnum, buf, sizeof buf);
 #else
@@ -434,7 +449,11 @@ guestfs_safe_malloc (guestfs_h *g, size_t nbytes)
 
 /* Technically we should add an autoconf test for this, testing for the desired
    functionality, like what's done in gnulib, but for now, this is fine.  */
+#if defined(__GLIBC__)
 #define HAVE_GNU_CALLOC (__GLIBC__ >= 2)
+#else
+#define HAVE_GNU_CALLOC 0
+#endif
 
 /* Allocate zeroed memory for N elements of S bytes, with error
    checking.  S must be nonzero.  */
@@ -1040,7 +1059,7 @@ guestfs__launch (guestfs_h *g)
     goto cleanup0;
 
   /* Choose which vmchannel implementation to use. */
-  if (qemu_supports (g, "-net user")) {
+  if (CAN_CHECK_PEER_EUID && qemu_supports (g, "-net user")) {
     /* The "null vmchannel" implementation.  Requires SLIRP (user mode
      * networking in qemu) but no other vmchannel support.  The daemon
      * will connect back to a random port number on localhost.
@@ -1238,10 +1257,12 @@ guestfs__launch (guestfs_h *g)
               "%s "             /* (selinux) */
               "%s "             /* (vmchannel) */
               "%s "             /* (verbose) */
+              "TERM=%s "        /* (TERM environment variable) */
               "%s",             /* (append) */
               g->selinux ? "selinux=1 enforcing=0" : "selinux=0",
               vmchannel ? vmchannel : "",
               g->verbose ? "guestfs_verbose=1" : "",
+              getenv ("TERM") ? : "linux",
               g->append ? g->append : "");
 
     add_cmdline (g, "-kernel");
@@ -1268,7 +1289,7 @@ guestfs__launch (guestfs_h *g)
       if (dup (wfd[0]) == -1) {
       dup_failed:
         perror ("dup failed");
-        _exit (1);
+        _exit (EXIT_FAILURE);
       }
       if (dup (rfd[1]) == -1)
         goto dup_failed;
@@ -1288,7 +1309,7 @@ guestfs__launch (guestfs_h *g)
 
     execv (g->qemu, g->cmdline); /* Run qemu. */
     perror (g->qemu);
-    _exit (1);
+    _exit (EXIT_FAILURE);
   }
 
   /* Parent (library). */
@@ -1320,11 +1341,11 @@ guestfs__launch (guestfs_h *g)
        */
       for (;;) {
         if (kill (qemu_pid, 0) == -1) /* qemu's gone away, we aren't needed */
-          _exit (0);
+          _exit (EXIT_SUCCESS);
         if (kill (parent_pid, 0) == -1) {
           /* Parent's gone away, qemu still around, so kill qemu. */
           kill (qemu_pid, 9);
-          _exit (0);
+          _exit (EXIT_SUCCESS);
         }
         sleep (2);
       }
@@ -1620,7 +1641,7 @@ test_qemu (guestfs_h *g)
   char cmd[1024];
   FILE *fp;
 
-  snprintf (cmd, sizeof cmd, "LC_ALL=C '%s' -help", g->qemu);
+  snprintf (cmd, sizeof cmd, "LC_ALL=C '%s' -nographic -help", g->qemu);
 
   fp = popen (cmd, "r");
   /* qemu -help should always work (qemu -version OTOH wasn't
@@ -1642,7 +1663,8 @@ test_qemu (guestfs_h *g)
   if (pclose (fp) == -1)
     goto error;
 
-  snprintf (cmd, sizeof cmd, "LC_ALL=C '%s' -version 2>/dev/null", g->qemu);
+  snprintf (cmd, sizeof cmd, "LC_ALL=C '%s' -nographic -version 2>/dev/null",
+           g->qemu);
 
   fp = popen (cmd, "r");
   if (fp) {
@@ -1723,6 +1745,7 @@ is_openable (guestfs_h *g, const char *path, int flags)
 static int
 check_peer_euid (guestfs_h *g, int sock, uid_t *rtn)
 {
+#if CAN_CHECK_PEER_EUID
   struct sockaddr_in peer;
   socklen_t addrlen = sizeof peer;
 
@@ -1791,6 +1814,12 @@ check_peer_euid (guestfs_h *g, int sock, uid_t *rtn)
   error (g, "check_peer_euid: no matching TCP connection found in /proc/net/tcp");
   fclose (fp);
   return -1;
+#else /* !CAN_CHECK_PEER_EUID */
+  /* This function exists but should never be called in this
+   * configuration.
+   */
+  abort ();
+#endif /* !CAN_CHECK_PEER_EUID */
 }
 
 /* You had to call this function after launch in versions <= 1.0.70,