[libvirt] [PATCHv2 6/8] qemu: convert to virCommand

Eric Blake eblake at redhat.com
Tue Nov 23 23:49:59 UTC 2010


* src/qemu/qemu_conf.c (qemudExtractVersionInfo): Check for file
before executing it here, rather than in callers.
(qemudBuildCommandLine): Rewrite with virCommand.
* src/qemu/qemu_conf.h (qemudBuildCommandLine): Update signature.
* src/qemu/qemu_driver.c (qemuAssignPCIAddresses)
(qemudStartVMDaemon, qemuDomainXMLToNative): Adjust callers.
---

v2: new patch, taking most of the ideas from
https://www.redhat.com/archives/libvir-list/2010-November/msg00979.html
but making it better by using virCommand improvements

 src/qemu/qemu_conf.c     |  710 ++++++++++++++++++----------------------------
 src/qemu/qemu_conf.h     |   10 +-
 src/qemu/qemu_driver.c   |  190 +++----------
 tests/qemuxml2argvtest.c |   68 +----
 4 files changed, 338 insertions(+), 640 deletions(-)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 35caccc..7c0db15 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1530,6 +1530,15 @@ int qemudExtractVersionInfo(const char *qemu,
     if (retversion)
         *retversion = 0;

+    /* Make sure the binary we are about to try exec'ing exists.
+     * Technically we could catch the exec() failure, but that's
+     * in a sub-process so it's hard to feed back a useful error.
+     */
+    if (access(qemu, X_OK) < 0) {
+        virReportSystemError(errno, _("Cannot find QEMU binary %s"), qemu);
+        return -1;
+    }
+
     if (virExec(qemuarg, qemuenv, NULL,
                 &child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
         return -1;
@@ -3942,43 +3951,35 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
  * XXX 'conn' is only required to resolve network -> bridge name
  * figure out how to remove this requirement some day
  */
-int qemudBuildCommandLine(virConnectPtr conn,
-                          struct qemud_driver *driver,
-                          virDomainDefPtr def,
-                          virDomainChrDefPtr monitor_chr,
-                          int monitor_json,
-                          unsigned long long qemuCmdFlags,
-                          const char ***retargv,
-                          const char ***retenv,
-                          int **vmfds,
-                          int *nvmfds,
-                          const char *migrateFrom,
-                          virDomainSnapshotObjPtr current_snapshot)
+virCommandPtr
+qemudBuildCommandLine(virConnectPtr conn,
+                      struct qemud_driver *driver,
+                      virDomainDefPtr def,
+                      virDomainChrDefPtr monitor_chr,
+                      bool monitor_json,
+                      unsigned long long qemuCmdFlags,
+                      const char *migrateFrom,
+                      virDomainSnapshotObjPtr current_snapshot)
 {
     int i;
-    char memory[50];
     char boot[VIR_DOMAIN_BOOT_LAST+1];
     struct utsname ut;
     int disableKQEMU = 0;
     int enableKQEMU = 0;
     int disableKVM = 0;
     int enableKVM = 0;
-    int qargc = 0, qarga = 0;
-    const char **qargv = NULL;
-    int qenvc = 0, qenva = 0;
-    const char **qenv = NULL;
     const char *emulator;
     char uuid[VIR_UUID_STRING_BUFLEN];
-    char domid[50];
     char *cpu;
     char *smp;
     int last_good_net = -1;
     bool hasHwVirt = false;
+    virCommandPtr cmd;

     uname_normalize(&ut);

     if (qemuAssignDeviceAliases(def, qemuCmdFlags) < 0)
-        return -1;
+        return NULL;

     virUUIDFormat(def->uuid, uuid);

@@ -3990,7 +3991,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
             if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP)) {
                 qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                 "%s", _("TCP migration is not supported with this QEMU binary"));
-                return -1;
+                return NULL;
             }
         } else if (STREQ(migrateFrom, "stdio")) {
             if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC) {
@@ -3998,13 +3999,13 @@ int qemudBuildCommandLine(virConnectPtr conn,
             } else if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO)) {
                 qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                 "%s", _("STDIO migration is not supported with this QEMU binary"));
-                return -1;
+                return NULL;
             }
         } else if (STRPREFIX(migrateFrom, "exec")) {
             if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC)) {
                 qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                 "%s", _("STDIO migration is not supported with this QEMU binary"));
-                return -1;
+                return NULL;
             }
         }
     }
@@ -4065,134 +4066,45 @@ int qemudBuildCommandLine(virConnectPtr conn,
         break;
     }

-#define ADD_ARG_SPACE                                                   \
-    do { \
-        if (qargc == qarga) {                                           \
-            qarga += 10;                                                \
-            if (VIR_REALLOC_N(qargv, qarga) < 0)                        \
-                goto no_memory;                                         \
-        }                                                               \
-    } while (0)
-
-#define ADD_ARG(thisarg)                                                \
-    do {                                                                \
-        ADD_ARG_SPACE;                                                  \
-        qargv[qargc++] = thisarg;                                       \
-    } while (0)
-
-#define ADD_ARG_LIT(thisarg)                                            \
-    do {                                                                \
-        ADD_ARG_SPACE;                                                  \
-        if ((qargv[qargc++] = strdup(thisarg)) == NULL)                 \
-            goto no_memory;                                             \
-    } while (0)
-
-#define ADD_USBDISK(thisarg)                                            \
-    do {                                                                \
-        ADD_ARG_LIT("-usbdevice");                                      \
-        ADD_ARG_SPACE;                                                  \
-        if ((virAsprintf((char **)&(qargv[qargc++]),                    \
-                         "disk:%s", thisarg)) == -1) {                  \
-            goto no_memory;                                             \
-        }                                                               \
-    } while (0)
-
-#define ADD_ENV_SPACE                                                   \
-    do {                                                                \
-        if (qenvc == qenva) {                                           \
-            qenva += 10;                                                \
-            if (VIR_REALLOC_N(qenv, qenva) < 0)                         \
-                goto no_memory;                                         \
-        }                                                               \
-    } while (0)
-
-#define ADD_ENV(thisarg)                                                \
-    do {                                                                \
-        ADD_ENV_SPACE;                                                  \
-        qenv[qenvc++] = thisarg;                                        \
-    } while (0)
-
-#define ADD_ENV_LIT(thisarg)                                            \
-    do {                                                                \
-        ADD_ENV_SPACE;                                                  \
-        if ((qenv[qenvc++] = strdup(thisarg)) == NULL)                  \
-            goto no_memory;                                             \
-    } while (0)
-
-#define ADD_ENV_PAIR(envname, val)                                      \
-    do {                                                                \
-        char *envval;                                                   \
-        ADD_ENV_SPACE;                                                  \
-        if (virAsprintf(&envval, "%s=%s", envname, val) < 0)            \
-            goto no_memory;                                             \
-        qenv[qenvc++] = envval;                                         \
-    } while (0)
-
-    /* Make sure to unset or set all envvars in qemuxml2argvtest.c that
-     * are copied here using this macro, otherwise the test may fail */
-#define ADD_ENV_COPY(envname)                                           \
-    do {                                                                \
-        char *val = getenv(envname);                                    \
-        if (val != NULL) {                                              \
-            ADD_ENV_PAIR(envname, val);                                 \
-        }                                                               \
-    } while (0)
+    cmd = virCommandNewArgList(emulator, "-S", NULL);

-    /* Set '-m MB' based on maxmem, because the lower 'memory' limit
-     * is set post-startup using the balloon driver. If balloon driver
-     * is not supported, then they're out of luck anyway
-     */
-    snprintf(memory, sizeof(memory), "%lu", def->mem.max_balloon/1024);
-    snprintf(domid, sizeof(domid), "%d", def->id);
-
-    ADD_ENV_LIT("LC_ALL=C");
-
-    ADD_ENV_COPY("LD_PRELOAD");
-    ADD_ENV_COPY("LD_LIBRARY_PATH");
-    ADD_ENV_COPY("PATH");
-    ADD_ENV_COPY("HOME");
-    ADD_ENV_COPY("USER");
-    ADD_ENV_COPY("LOGNAME");
-    ADD_ENV_COPY("TMPDIR");
-
-    ADD_ARG_LIT(emulator);
-    ADD_ARG_LIT("-S");
+    virCommandAddEnvPassCommon(cmd);

     /* This should *never* be NULL, since we always provide
      * a machine in the capabilities data for QEMU. So this
      * check is just here as a safety in case the unexpected
      * happens */
-    if (def->os.machine) {
-        ADD_ARG_LIT("-M");
-        ADD_ARG_LIT(def->os.machine);
-    }
+    if (def->os.machine)
+        virCommandAddArgList(cmd, "-M", def->os.machine, NULL);

     if (qemuBuildCpuArgStr(driver, def, emulator, qemuCmdFlags,
                            &ut, &cpu, &hasHwVirt) < 0)
         goto error;

     if (cpu) {
-        ADD_ARG_LIT("-cpu");
-        ADD_ARG_LIT(cpu);
+        virCommandAddArgList(cmd, "-cpu", cpu, NULL);
         VIR_FREE(cpu);

         if ((qemuCmdFlags & QEMUD_CMD_FLAG_NESTING) &&
             hasHwVirt)
-            ADD_ARG_LIT("-enable-nesting");
+            virCommandAddArg(cmd, "-enable-nesting");
     }

     if (disableKQEMU)
-        ADD_ARG_LIT("-no-kqemu");
-    else if (enableKQEMU) {
-        ADD_ARG_LIT("-enable-kqemu");
-        ADD_ARG_LIT("-kernel-kqemu");
-    }
+        virCommandAddArg(cmd, "-no-kqemu");
+    else if (enableKQEMU)
+        virCommandAddArgList(cmd, "-enable-kqemu", "-kernel-kqemu", NULL);
     if (disableKVM)
-        ADD_ARG_LIT("-no-kvm");
+        virCommandAddArg(cmd, "-no-kvm");
     if (enableKVM)
-        ADD_ARG_LIT("-enable-kvm");
-    ADD_ARG_LIT("-m");
-    ADD_ARG_LIT(memory);
+        virCommandAddArg(cmd, "-enable-kvm");
+
+    /* Set '-m MB' based on maxmem, because the lower 'memory' limit
+     * is set post-startup using the balloon driver. If balloon driver
+     * is not supported, then they're out of luck anyway
+     */
+    virCommandAddArg(cmd, "-m");
+    virCommandAddArgFormat(cmd, "%lu", def->mem.max_balloon / 1024);
     if (def->mem.hugepage_backed) {
         if (!driver->hugetlbfs_mount) {
             qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -4210,43 +4122,38 @@ int qemudBuildCommandLine(virConnectPtr conn,
                             def->emulator);
             goto error;
         }
-        ADD_ARG_LIT("-mem-prealloc");
-        ADD_ARG_LIT("-mem-path");
-        ADD_ARG_LIT(driver->hugepage_path);
+        virCommandAddArgList(cmd, "-mem-prealloc", "-mem-path",
+                             driver->hugepage_path, NULL);
     }

-    ADD_ARG_LIT("-smp");
+    virCommandAddArg(cmd, "-smp");
     if (!(smp = qemuBuildSmpArgStr(def, qemuCmdFlags)))
         goto error;
-    ADD_ARG(smp);
+    virCommandAddArg(cmd, smp);
+    VIR_FREE(smp);

     if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
-        ADD_ARG_LIT("-name");
+        virCommandAddArg(cmd, "-name");
         if (driver->setProcessName &&
             (qemuCmdFlags & QEMUD_CMD_FLAG_NAME_PROCESS)) {
-            char *name;
-            if (virAsprintf(&name, "%s,process=qemu:%s",
-                            def->name, def->name) < 0)
-                goto no_memory;
-            ADD_ARG_LIT(name);
+            virCommandAddArgFormat(cmd, "%s,process=qemu:%s",
+                                   def->name, def->name);
         } else {
-            ADD_ARG_LIT(def->name);
+            virCommandAddArg(cmd, def->name);
         }
     }
-    if (qemuCmdFlags & QEMUD_CMD_FLAG_UUID) {
-        ADD_ARG_LIT("-uuid");
-        ADD_ARG_LIT(uuid);
-    }
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_UUID)
+        virCommandAddArgList(cmd, "-uuid", uuid, NULL);
     if (def->virtType == VIR_DOMAIN_VIRT_XEN ||
         STREQ(def->os.type, "xen") ||
         STREQ(def->os.type, "linux")) {
         if (qemuCmdFlags & QEMUD_CMD_FLAG_DOMID) {
-            ADD_ARG_LIT("-domid");
-            ADD_ARG_LIT(domid);
+            virCommandAddArg(cmd, "-domid");
+            virCommandAddArgFormat(cmd, "%d", def->id);
         } else if (qemuCmdFlags & QEMUD_CMD_FLAG_XEN_DOMID) {
-            ADD_ARG_LIT("-xen-attach");
-            ADD_ARG_LIT("-xen-domid");
-            ADD_ARG_LIT(domid);
+            virCommandAddArg(cmd, "-xen-attach");
+            virCommandAddArg(cmd, "-xen-domid");
+            virCommandAddArgFormat(cmd, "%d", def->id);
         } else {
             qemuReportError(VIR_ERR_INTERNAL_ERROR,
                             _("qemu emulator '%s' does not support xen"),
@@ -4288,13 +4195,13 @@ int qemudBuildCommandLine(virConnectPtr conn,

             smbioscmd = qemuBuildSmbiosBiosStr(source);
             if (smbioscmd != NULL) {
-                ADD_ARG_LIT("-smbios");
-                ADD_ARG(smbioscmd);
+                virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
+                VIR_FREE(smbioscmd);
             }
             smbioscmd = qemuBuildSmbiosSystemStr(source);
             if (smbioscmd != NULL) {
-                ADD_ARG_LIT("-smbios");
-                ADD_ARG(smbioscmd);
+                virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
+                VIR_FREE(smbioscmd);
             }
         }
     }
@@ -4307,12 +4214,14 @@ int qemudBuildCommandLine(virConnectPtr conn,
      * these defaults ourselves...
      */
     if (!def->graphics)
-        ADD_ARG_LIT("-nographic");
+        virCommandAddArg(cmd, "-nographic");

     if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
         if (qemuCmdFlags & QEMUD_CMD_FLAG_NODEFCONFIG)
-            ADD_ARG_LIT("-nodefconfig"); /* Disabling global config files */
-        ADD_ARG_LIT("-nodefaults");  /* Disabling default guest devices */
+            virCommandAddArg(cmd,
+                             "-nodefconfig"); /* Disable global config files */
+        virCommandAddArg(cmd,
+                         "-nodefaults");  /* Disable default guest devices */
     }

     if (monitor_chr) {
@@ -4320,39 +4229,40 @@ int qemudBuildCommandLine(virConnectPtr conn,
         /* Use -chardev if it's available */
         if (qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) {

-            ADD_ARG_LIT("-chardev");
+            virCommandAddArg(cmd, "-chardev");
             if (!(chrdev = qemuBuildChrChardevStr(monitor_chr)))
                 goto error;
-            ADD_ARG(chrdev);
+            virCommandAddArg(cmd, chrdev);
+            VIR_FREE(chrdev);

-            ADD_ARG_LIT("-mon");
-            if (monitor_json)
-                ADD_ARG_LIT("chardev=monitor,mode=control");
-            else
-                ADD_ARG_LIT("chardev=monitor,mode=readline");
+            virCommandAddArg(cmd, "-mon");
+            virCommandAddArgFormat(cmd, "chardev=monitor,mode=%s",
+                                   monitor_json ? "control" : "readline");
         } else {
             const char *prefix = NULL;
             if (monitor_json)
                 prefix = "control,";

-            ADD_ARG_LIT("-monitor");
+            virCommandAddArg(cmd, "-monitor");
             if (!(chrdev = qemuBuildChrArgStr(monitor_chr, prefix)))
                 goto error;
-            ADD_ARG(chrdev);
+            virCommandAddArg(cmd, chrdev);
+            VIR_FREE(chrdev);
         }
     }

     if (qemuCmdFlags & QEMUD_CMD_FLAG_RTC) {
         const char *rtcopt;
-        ADD_ARG_LIT("-rtc");
+        virCommandAddArg(cmd, "-rtc");
         if (!(rtcopt = qemuBuildClockArgStr(&def->clock)))
             goto error;
-        ADD_ARG(rtcopt);
+        virCommandAddArg(cmd, rtcopt);
+        VIR_FREE(rtcopt);
     } else {
         switch (def->clock.offset) {
         case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
         case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
-            ADD_ARG_LIT("-localtime");
+            virCommandAddArg(cmd, "-localtime");
             break;

         case VIR_DOMAIN_CLOCK_OFFSET_UTC:
@@ -4368,7 +4278,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
     }
     if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE &&
         def->clock.data.timezone) {
-        ADD_ENV_PAIR("TZ", def->clock.data.timezone);
+        virCommandAddEnvPair(cmd, "TZ", def->clock.data.timezone);
     }

     for (i = 0; i < def->clock.ntimers; i++) {
@@ -4392,7 +4302,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
                     /* the default - do nothing */
                     break;
                 case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
-                    ADD_ARG_LIT("-rtc-td-hack");
+                    virCommandAddArg(cmd, "-rtc-td-hack");
                     break;
                 case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
                 case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
@@ -4421,14 +4331,14 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 /* delay is the default if we don't have kernel
                    (-no-kvm-pit), otherwise, the default is catchup. */
                 if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_KVM_PIT)
-                    ADD_ARG_LIT("-no-kvm-pit-reinjection");
+                    virCommandAddArg(cmd, "-no-kvm-pit-reinjection");
                 break;
             case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
                 if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_KVM_PIT) {
                     /* do nothing - this is default for kvm-pit */
                 } else if (qemuCmdFlags & QEMUD_CMD_FLAG_TDF) {
                     /* -tdf switches to 'catchup' with userspace pit. */
-                    ADD_ARG_LIT("-tdf");
+                    virCommandAddArg(cmd, "-tdf");
                 } else {
                     /* can't catchup if we have neither pit mode */
                     qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -4457,7 +4367,7 @@ int qemudBuildCommandLine(virConnectPtr conn,

             if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_HPET) {
                 if (def->clock.timers[i]->present == 0)
-                    ADD_ARG_LIT("-no-hpet");
+                    virCommandAddArg(cmd, "-no-hpet");
             } else {
                 /* no hpet timer available. The only possible action
                    is to raise an error if present="yes" */
@@ -4472,10 +4382,10 @@ int qemudBuildCommandLine(virConnectPtr conn,

     if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
         def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
-        ADD_ARG_LIT("-no-reboot");
+        virCommandAddArg(cmd, "-no-reboot");

     if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
-        ADD_ARG_LIT("-no-acpi");
+        virCommandAddArg(cmd, "-no-acpi");

     if (!def->os.bootloader) {
         for (i = 0 ; i < def->os.nBootDevs ; i++) {
@@ -4499,7 +4409,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
         }
         if (def->os.nBootDevs) {
             virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
-            ADD_ARG_LIT("-boot");
+            char *bootstr;
+            virCommandAddArg(cmd, "-boot");

             boot[def->os.nBootDevs] = '\0';

@@ -4518,24 +4429,19 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 goto error;
             }

-            ADD_ARG(virBufferContentAndReset(&boot_buf));
+            bootstr = virBufferContentAndReset(&boot_buf);
+            virCommandAddArg(cmd, bootstr);
+            VIR_FREE(bootstr);
         }

-        if (def->os.kernel) {
-            ADD_ARG_LIT("-kernel");
-            ADD_ARG_LIT(def->os.kernel);
-        }
-        if (def->os.initrd) {
-            ADD_ARG_LIT("-initrd");
-            ADD_ARG_LIT(def->os.initrd);
-        }
-        if (def->os.cmdline) {
-            ADD_ARG_LIT("-append");
-            ADD_ARG_LIT(def->os.cmdline);
-        }
+        if (def->os.kernel)
+            virCommandAddArgList(cmd, "-kernel", def->os.kernel, NULL);
+        if (def->os.initrd)
+            virCommandAddArgList(cmd, "-initrd", def->os.initrd, NULL);
+        if (def->os.cmdline)
+            virCommandAddArgList(cmd, "-append", def->os.cmdline, NULL);
     } else {
-        ADD_ARG_LIT("-bootloader");
-        ADD_ARG_LIT(def->os.bootloader);
+        virCommandAddArgList(cmd, "-bootloader", def->os.bootloader, NULL);
     }

     for (i = 0 ; i < def->ndisks ; i++) {
@@ -4568,13 +4474,14 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 goto error;
             }

-            ADD_ARG_LIT("-device");
+            virCommandAddArg(cmd, "-device");

             char *devstr;
             if (!(devstr = qemuBuildControllerDevStr(def->controllers[i])))
                 goto no_memory;

-            ADD_ARG(devstr);
+            virCommandAddArg(cmd, devstr);
+            VIR_FREE(devstr);
         }
     }

@@ -4610,10 +4517,12 @@ int qemudBuildCommandLine(virConnectPtr conn,
             if ((disk->bus == VIR_DOMAIN_DISK_BUS_USB) &&
                 !(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
                 if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
-                    ADD_USBDISK(disk->src);
+                    virCommandAddArg(cmd, "-usbdevice");
+                    virCommandAddArgFormat(cmd, "disk:%s", disk->src);
                 } else {
                     qemuReportError(VIR_ERR_INTERNAL_ERROR,
-                                    _("unsupported usb disk type for '%s'"), disk->src);
+                                    _("unsupported usb disk type for '%s'"),
+                                    disk->src);
                     goto error;
                 }
                 continue;
@@ -4634,10 +4543,10 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 break;
             }

-            ADD_ARG_LIT("-drive");
+            virCommandAddArg(cmd, "-drive");

-            /* Unfortunately it is nt possible to use
-               -device for floppys, or Xen paravirt
+            /* Unfortunately it is not possible to use
+               -device for floppies, or Xen paravirt
                devices. Fortunately, those don't need
                static PCI addresses, so we don't really
                care that we can't use -device */
@@ -4648,24 +4557,23 @@ int qemudBuildCommandLine(virConnectPtr conn,
                                              (withDeviceArg ? qemuCmdFlags :
                                               (qemuCmdFlags & ~QEMUD_CMD_FLAG_DEVICE)))))
                 goto error;
-            ADD_ARG(optstr);
+            virCommandAddArg(cmd, optstr);
+            VIR_FREE(optstr);

             if (withDeviceArg) {
                 if (disk->bus == VIR_DOMAIN_DISK_BUS_FDC) {
-                    char *fdc;
-                    ADD_ARG_LIT("-global");
-
-                    if (virAsprintf(&fdc, "isa-fdc.drive%c=drive-%s",
-                                    disk->info.addr.drive.unit ? 'B' : 'A',
-                                    disk->info.alias) < 0)
-                        goto no_memory;
-                    ADD_ARG(fdc);
+                    virCommandAddArg(cmd, "-global");
+                    virCommandAddArgFormat(cmd, "isa-fdc.drive%c=drive-%s",
+                                           disk->info.addr.drive.unit
+                                           ? 'B' : 'A',
+                                           disk->info.alias);
                 } else {
-                    ADD_ARG_LIT("-device");
+                    virCommandAddArg(cmd, "-device");

                     if (!(optstr = qemuBuildDriveDevStr(disk)))
                         goto error;
-                    ADD_ARG(optstr);
+                    virCommandAddArg(cmd, optstr);
+                    VIR_FREE(optstr);
                 }
             }
         }
@@ -4677,10 +4585,12 @@ int qemudBuildCommandLine(virConnectPtr conn,

             if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
                 if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
-                    ADD_USBDISK(disk->src);
+                    virCommandAddArg(cmd, "-usbdevice");
+                    virCommandAddArgFormat(cmd, "disk:%s", disk->src);
                 } else {
                     qemuReportError(VIR_ERR_INTERNAL_ERROR,
-                                    _("unsupported usb disk type for '%s'"), disk->src);
+                                    _("unsupported usb disk type for '%s'"),
+                                    disk->src);
                     goto error;
                 }
                 continue;
@@ -4726,8 +4636,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 snprintf(file, PATH_MAX, "%s", disk->src);
             }

-            ADD_ARG_LIT(dev);
-            ADD_ARG_LIT(file);
+            virCommandAddArgList(cmd, dev, file, NULL);
         }
     }

@@ -4736,15 +4645,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
             char *optstr;
             virDomainFSDefPtr fs = def->fss[i];

-            ADD_ARG_LIT("-fsdev");
+            virCommandAddArg(cmd, "-fsdev");
             if (!(optstr = qemuBuildFSStr(fs, qemuCmdFlags)))
                 goto error;
-            ADD_ARG(optstr);
+            virCommandAddArg(cmd, optstr);
+            VIR_FREE(optstr);

-            ADD_ARG_LIT("-device");
+            virCommandAddArg(cmd, "-device");
             if (!(optstr = qemuBuildFSDevStr(fs)))
                 goto error;
-            ADD_ARG(optstr);
+            virCommandAddArg(cmd, optstr);
+            VIR_FREE(optstr);
         }
     } else {
         if (def->nfss) {
@@ -4756,10 +4667,8 @@ int qemudBuildCommandLine(virConnectPtr conn,

     if (!def->nnets) {
         /* If we have -device, then we set -nodefault already */
-        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
-            ADD_ARG_LIT("-net");
-            ADD_ARG_LIT("none");
-        }
+        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
+            virCommandAddArgList(cmd, "-net", "none", NULL);
     } else {
         for (i = 0 ; i < def->nnets ; i++) {
             virDomainNetDefPtr net = def->nets[i];
@@ -4777,21 +4686,16 @@ int qemudBuildCommandLine(virConnectPtr conn,

             if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
                 net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
-                int tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags);
+                int tapfd = qemudNetworkIfaceConnect(conn, driver, net,
+                                                     qemuCmdFlags);
                 if (tapfd < 0)
                     goto error;

-                if (VIR_REALLOC_N(*vmfds, (*nvmfds)+1) < 0) {
-                    virDomainConfNWFilterTeardown(net);
-                    VIR_FORCE_CLOSE(tapfd);
-                    goto no_memory;
-                }
-
                 last_good_net = i;
+                virCommandTransferFD(cmd, tapfd);

-                (*vmfds)[(*nvmfds)++] = tapfd;
-
-                if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name))
+                if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
+                             tapfd) >= sizeof(tapfd_name))
                     goto no_memory;
             } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
                 int tapfd = qemudPhysIfaceConnect(conn, driver, net,
@@ -4800,17 +4704,11 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 if (tapfd < 0)
                     goto error;

-                if (VIR_REALLOC_N(*vmfds, (*nvmfds)+1) < 0) {
-                    virDomainConfNWFilterTeardown(net);
-                    VIR_FORCE_CLOSE(tapfd);
-                    goto no_memory;
-                }
-
                 last_good_net = i;
+                virCommandTransferFD(cmd, tapfd);

-                (*vmfds)[(*nvmfds)++] = tapfd;
-
-                if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name))
+                if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
+                             tapfd) >= sizeof(tapfd_name))
                     goto no_memory;
             }

@@ -4821,14 +4719,10 @@ int qemudBuildCommandLine(virConnectPtr conn,
                    network device */
                 int vhostfd = qemudOpenVhostNet(net, qemuCmdFlags);
                 if (vhostfd >= 0) {
-                    if (VIR_REALLOC_N(*vmfds, (*nvmfds)+1) < 0) {
-                        VIR_FORCE_CLOSE(vhostfd);
-                        goto no_memory;
-                    }
+                    virCommandTransferFD(cmd, vhostfd);

-                    (*vmfds)[(*nvmfds)++] = vhostfd;
-                    if (snprintf(vhostfd_name, sizeof(vhostfd_name), "%d", vhostfd)
-                        >= sizeof(vhostfd_name))
+                    if (snprintf(vhostfd_name, sizeof(vhostfd_name), "%d",
+                                 vhostfd) >= sizeof(vhostfd_name))
                         goto no_memory;
                 }
             }
@@ -4842,40 +4736,42 @@ int qemudBuildCommandLine(virConnectPtr conn,
              */
             if ((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
                 (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
-                ADD_ARG_LIT("-netdev");
+                virCommandAddArg(cmd, "-netdev");
                 if (!(host = qemuBuildHostNetStr(net, ',', vlan,
                                                  tapfd_name, vhostfd_name)))
                     goto error;
-                ADD_ARG(host);
+                virCommandAddArg(cmd, host);
+                VIR_FREE(host);
             }
             if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
-                ADD_ARG_LIT("-device");
+                virCommandAddArg(cmd, "-device");
                 if (!(nic = qemuBuildNicDevStr(net, vlan)))
                     goto error;
-                ADD_ARG(nic);
+                virCommandAddArg(cmd, nic);
+                VIR_FREE(nic);
             } else {
-                ADD_ARG_LIT("-net");
+                virCommandAddArg(cmd, "-net");
                 if (!(nic = qemuBuildNicStr(net, "nic,", vlan)))
                     goto error;
-                ADD_ARG(nic);
+                virCommandAddArg(cmd, nic);
+                VIR_FREE(nic);
             }
             if (!((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
                   (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))) {
-                ADD_ARG_LIT("-net");
+                virCommandAddArg(cmd, "-net");
                 if (!(host = qemuBuildHostNetStr(net, ',', vlan,
                                                  tapfd_name, vhostfd_name)))
                     goto error;
-                ADD_ARG(host);
+                virCommandAddArg(cmd, host);
+                VIR_FREE(host);
             }
         }
     }

     if (!def->nserials) {
         /* If we have -device, then we set -nodefault already */
-        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
-            ADD_ARG_LIT("-serial");
-            ADD_ARG_LIT("none");
-        }
+        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
+            virCommandAddArgList(cmd, "-serial", "none", NULL);
     } else {
         for (i = 0 ; i < def->nserials ; i++) {
             virDomainChrDefPtr serial = def->serials[i];
@@ -4884,30 +4780,29 @@ int qemudBuildCommandLine(virConnectPtr conn,
             /* Use -chardev with -device if they are available */
             if ((qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) &&
                 (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
-                ADD_ARG_LIT("-chardev");
+                virCommandAddArg(cmd, "-chardev");
                 if (!(devstr = qemuBuildChrChardevStr(serial)))
                     goto error;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, devstr);
+                VIR_FREE(devstr);

-                ADD_ARG_LIT("-device");
-                if (virAsprintf(&devstr, "isa-serial,chardev=%s", serial->info.alias) < 0)
-                    goto no_memory;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, "-device");
+                virCommandAddArgFormat(cmd, "isa-serial,chardev=%s",
+                                       serial->info.alias);
             } else {
-                ADD_ARG_LIT("-serial");
+                virCommandAddArg(cmd, "-serial");
                 if (!(devstr = qemuBuildChrArgStr(serial, NULL)))
                     goto error;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, devstr);
+                VIR_FREE(devstr);
             }
         }
     }

     if (!def->nparallels) {
         /* If we have -device, then we set -nodefault already */
-        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
-            ADD_ARG_LIT("-parallel");
-            ADD_ARG_LIT("none");
-        }
+        if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
+            virCommandAddArgList(cmd, "-parallel", "none", NULL);
     } else {
         for (i = 0 ; i < def->nparallels ; i++) {
             virDomainChrDefPtr parallel = def->parallels[i];
@@ -4916,20 +4811,21 @@ int qemudBuildCommandLine(virConnectPtr conn,
             /* Use -chardev with -device if they are available */
             if ((qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) &&
                 (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
-                ADD_ARG_LIT("-chardev");
+                virCommandAddArg(cmd, "-chardev");
                 if (!(devstr = qemuBuildChrChardevStr(parallel)))
                     goto error;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, devstr);
+                VIR_FREE(devstr);

-                ADD_ARG_LIT("-device");
-                if (virAsprintf(&devstr, "isa-parallel,chardev=%s", parallel->info.alias) < 0)
-                    goto no_memory;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, "-device");
+                virCommandAddArgFormat(cmd, "isa-parallel,chardev=%s",
+                                       parallel->info.alias);
             } else {
-                ADD_ARG_LIT("-parallel");
+                virCommandAddArg(cmd, "-parallel");
                 if (!(devstr = qemuBuildChrArgStr(parallel, NULL)))
                       goto error;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, devstr);
+                VIR_FREE(devstr);
             }
         }
     }
@@ -4947,24 +4843,23 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 goto error;
             }

-            ADD_ARG_LIT("-chardev");
+            virCommandAddArg(cmd, "-chardev");
             if (!(devstr = qemuBuildChrChardevStr(channel)))
                 goto error;
-            ADD_ARG(devstr);
+            virCommandAddArg(cmd, devstr);
+            VIR_FREE(devstr);

             char *addr = virSocketFormatAddr(channel->target.addr);
             if (!addr)
                 goto error;
             int port = virSocketGetPort(channel->target.addr);

-            ADD_ARG_LIT("-netdev");
-            if (virAsprintf(&devstr, "user,guestfwd=tcp:%s:%i,chardev=%s,id=user-%s",
-                            addr, port, channel->info.alias, channel->info.alias) < 0) {
-                VIR_FREE(addr);
-                goto no_memory;
-            }
+            virCommandAddArg(cmd, "-netdev");
+            virCommandAddArgFormat(cmd,
+                                   "user,guestfwd=tcp:%s:%i,chardev=%s,id=user-%s",
+                                   addr, port, channel->info.alias,
+                                   channel->info.alias);
             VIR_FREE(addr);
-            ADD_ARG(devstr);
             break;

         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
@@ -4974,15 +4869,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 goto error;
             }

-            ADD_ARG_LIT("-chardev");
+            virCommandAddArg(cmd, "-chardev");
             if (!(devstr = qemuBuildChrChardevStr(channel)))
                 goto error;
-            ADD_ARG(devstr);
+            virCommandAddArg(cmd, devstr);
+            VIR_FREE(devstr);

-            ADD_ARG_LIT("-device");
+            virCommandAddArg(cmd, "-device");
             if (!(devstr = qemuBuildVirtioSerialPortDevStr(channel)))
                 goto error;
-            ADD_ARG(devstr);
+            virCommandAddArg(cmd, devstr);
+            VIR_FREE(devstr);
             break;
         }
     }
@@ -5000,15 +4897,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 goto error;
             }

-            ADD_ARG_LIT("-chardev");
+            virCommandAddArg(cmd, "-chardev");
             if (!(devstr = qemuBuildChrChardevStr(console)))
                 goto error;
-            ADD_ARG(devstr);
+            virCommandAddArg(cmd, devstr);
+            VIR_FREE(devstr);

-            ADD_ARG_LIT("-device");
+            virCommandAddArg(cmd, "-device");
             if (!(devstr = qemuBuildVirtioSerialPortDevStr(console)))
                 goto error;
-            ADD_ARG(devstr);
+            virCommandAddArg(cmd, devstr);
+            VIR_FREE(devstr);
             break;

         case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
@@ -5022,20 +4921,22 @@ int qemudBuildCommandLine(virConnectPtr conn,
         }
     }

-    ADD_ARG_LIT("-usb");
+    virCommandAddArg(cmd, "-usb");
     for (i = 0 ; i < def->ninputs ; i++) {
         virDomainInputDefPtr input = def->inputs[i];

         if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
             if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
                 char *optstr;
-                ADD_ARG_LIT("-device");
+                virCommandAddArg(cmd, "-device");
                 if (!(optstr = qemuBuildUSBInputDevStr(input)))
                     goto error;
-                ADD_ARG(optstr);
+                virCommandAddArg(cmd, optstr);
+                VIR_FREE(optstr);
             } else {
-                ADD_ARG_LIT("-usbdevice");
-                ADD_ARG_LIT(input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
+                virCommandAddArgList(cmd, "-usbdevice",
+                                     input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE
+                                     ? "mouse" : "tablet", NULL);
             }
         }
     }
@@ -5079,7 +4980,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 virBufferAddLit(&opt, ",sasl");

                 if (driver->vncSASLdir)
-                    ADD_ENV_PAIR("SASL_CONF_DIR", driver->vncSASLdir);
+                    virCommandAddEnvPair(cmd, "SASL_CONF_DIR",
+                                         driver->vncSASLdir);

                 /* TODO: Support ACLs later */
             }
@@ -5094,11 +4996,11 @@ int qemudBuildCommandLine(virConnectPtr conn,

         optstr = virBufferContentAndReset(&opt);

-        ADD_ARG_LIT("-vnc");
-        ADD_ARG(optstr);
+        virCommandAddArgList(cmd, "-vnc", optstr, NULL);
+        VIR_FREE(optstr);
         if (def->graphics[0]->data.vnc.keymap) {
-            ADD_ARG_LIT("-k");
-            ADD_ARG_LIT(def->graphics[0]->data.vnc.keymap);
+            virCommandAddArgList(cmd, "-k", def->graphics[0]->data.vnc.keymap,
+                                 NULL);
         }

         /* Unless user requested it, set the audio backend to none, to
@@ -5106,45 +5008,33 @@ int qemudBuildCommandLine(virConnectPtr conn,
          * security issues and might not work when using VNC.
          */
         if (driver->vncAllowHostAudio) {
-            ADD_ENV_COPY("QEMU_AUDIO_DRV");
+            virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
         } else {
-            ADD_ENV_LIT("QEMU_AUDIO_DRV=none");
+            virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
         }
     } else if ((def->ngraphics == 1) &&
                def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-        char *xauth = NULL;
-        char *display = NULL;
-
-        if (def->graphics[0]->data.sdl.xauth &&
-            virAsprintf(&xauth, "XAUTHORITY=%s",
-                        def->graphics[0]->data.sdl.xauth) < 0)
-            goto no_memory;
-        if (def->graphics[0]->data.sdl.display &&
-            virAsprintf(&display, "DISPLAY=%s",
-                        def->graphics[0]->data.sdl.display) < 0) {
-            VIR_FREE(xauth);
-            goto no_memory;
-        }
-
-        if (xauth)
-            ADD_ENV(xauth);
-        if (display)
-            ADD_ENV(display);
+        if (def->graphics[0]->data.sdl.xauth)
+            virCommandAddEnvPair(cmd, "XAUTHORITY",
+                                 def->graphics[0]->data.sdl.xauth);
+        if (def->graphics[0]->data.sdl.display)
+            virCommandAddEnvPair(cmd, "DISPLAY",
+                                 def->graphics[0]->data.sdl.display);
         if (def->graphics[0]->data.sdl.fullscreen)
-            ADD_ARG_LIT("-full-screen");
+            virCommandAddArg(cmd, "-full-screen");

         /* If using SDL for video, then we should just let it
          * use QEMU's host audio drivers, possibly SDL too
          * User can set these two before starting libvirtd
          */
-        ADD_ENV_COPY("QEMU_AUDIO_DRV");
-        ADD_ENV_COPY("SDL_AUDIODRIVER");
+        virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
+        virCommandAddEnvPass(cmd, "SDL_AUDIODRIVER");

         /* New QEMU has this flag to let us explicitly ask for
          * SDL graphics. This is better than relying on the
          * default, since the default changes :-( */
         if (qemuCmdFlags & QEMUD_CMD_FLAG_SDL)
-            ADD_ARG_LIT("-sdl");
+            virCommandAddArg(cmd, "-sdl");

     } else if ((def->ngraphics == 1) &&
                def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
@@ -5197,16 +5087,15 @@ int qemudBuildCommandLine(virConnectPtr conn,

         optstr = virBufferContentAndReset(&opt);

-        ADD_ARG_LIT("-spice");
-        ADD_ARG(optstr);
-        if (def->graphics[0]->data.spice.keymap) {
-            ADD_ARG_LIT("-k");
-            ADD_ARG_LIT(def->graphics[0]->data.spice.keymap);
-        }
+        virCommandAddArgList(cmd, "-spice", optstr, NULL);
+        VIR_FREE(optstr);
+        if (def->graphics[0]->data.spice.keymap)
+            virCommandAddArgList(cmd, "-k",
+                                 def->graphics[0]->data.spice.keymap, NULL);
         /* SPICE includes native support for tunnelling audio, so we
          * set the audio backend to point at SPICE's own driver
          */
-        ADD_ENV_LIT("QEMU_AUDIO_DRV=spice");
+        virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=spice");

     } else if ((def->ngraphics == 1)) {
         qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -5235,18 +5124,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
                     goto error;
                 }

-                ADD_ARG_LIT("-vga");
-                ADD_ARG_LIT(vgastr);
+                virCommandAddArgList(cmd, "-vga", vgastr, NULL);
             }
         } else {

             switch (def->videos[0]->type) {
             case VIR_DOMAIN_VIDEO_TYPE_VGA:
-                ADD_ARG_LIT("-std-vga");
+                virCommandAddArg(cmd, "-std-vga");
                 break;

             case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
-                ADD_ARG_LIT("-vmwarevga");
+                virCommandAddArg(cmd, "-vmwarevga");
                 break;

             case VIR_DOMAIN_VIDEO_TYPE_XEN:
@@ -5273,12 +5161,13 @@ int qemudBuildCommandLine(virConnectPtr conn,
                         goto error;
                     }

-                    ADD_ARG_LIT("-device");
+                    virCommandAddArg(cmd, "-device");

                     if (!(str = qemuBuildVideoDevStr(def->videos[i])))
                         goto error;

-                    ADD_ARG(str);
+                    virCommandAddArg(cmd, str);
+                    VIR_FREE(str);
                 }
             } else {
                 qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -5290,10 +5179,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
     } else {
         /* If we have -device, then we set -nodefault already */
         if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
-            (qemuCmdFlags & QEMUD_CMD_FLAG_VGA)) {
-            ADD_ARG_LIT("-vga");
-            ADD_ARG_LIT("none");
-        }
+            (qemuCmdFlags & QEMUD_CMD_FLAG_VGA))
+            virCommandAddArgList(cmd, "-vga", "none", NULL);
     }

     /* Add sound hardware */
@@ -5307,15 +5194,15 @@ int qemudBuildCommandLine(virConnectPtr conn,
                  * we don't need to set any PCI address on it, so we don't
                  * mind too much */
                 if (sound->model == VIR_DOMAIN_SOUND_MODEL_PCSPK) {
-                    ADD_ARG_LIT("-soundhw");
-                    ADD_ARG_LIT("pcspk");
+                    virCommandAddArgList(cmd, "-soundhw", "pcspk", NULL);
                 } else {
-                    ADD_ARG_LIT("-device");
+                    virCommandAddArg(cmd, "-device");

                     if (!(str = qemuBuildSoundDevStr(sound)))
                         goto error;

-                    ADD_ARG(str);
+                    virCommandAddArg(cmd, str);
+                    VIR_FREE(str);
                 }
             }
         } else {
@@ -5338,8 +5225,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
                 if (i < (def->nsounds - 1))
                     strncat(modstr, ",", size--);
             }
-            ADD_ARG_LIT("-soundhw");
-            ADD_ARG(modstr);
+            virCommandAddArgList(cmd, "-soundhw", modstr, NULL);
+            VIR_FREE(modstr);
         }
     }

@@ -5349,13 +5236,13 @@ int qemudBuildCommandLine(virConnectPtr conn,
         char *optstr;

         if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
-            ADD_ARG_LIT("-device");
+            virCommandAddArg(cmd, "-device");

             optstr = qemuBuildWatchdogDevStr(watchdog);
             if (!optstr)
                 goto error;
         } else {
-            ADD_ARG_LIT("-watchdog");
+            virCommandAddArg(cmd, "-watchdog");

             const char *model = virDomainWatchdogModelTypeToString(watchdog->model);
             if (!model) {
@@ -5367,7 +5254,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
             if (!(optstr = strdup(model)))
                 goto no_memory;
         }
-        ADD_ARG(optstr);
+        virCommandAddArg(cmd, optstr);
+        VIR_FREE(optstr);

         const char *action = virDomainWatchdogActionTypeToString(watchdog->action);
         if (!action) {
@@ -5375,8 +5263,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
                             "%s", _("invalid watchdog action"));
             goto error;
         }
-        ADD_ARG_LIT("-watchdog-action");
-        ADD_ARG_LIT(action);
+        virCommandAddArgList(cmd, "-watchdog-action", action, NULL);
     }

     /* Add host passthrough hardware */
@@ -5389,15 +5276,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
             hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {

             if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
-                ADD_ARG_LIT("-device");
+                virCommandAddArg(cmd, "-device");
                 if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev)))
                     goto error;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, devstr);
+                VIR_FREE(devstr);
             } else {
-                ADD_ARG_LIT("-usbdevice");
+                virCommandAddArg(cmd, "-usbdevice");
                 if (!(devstr = qemuBuildUSBHostdevUsbDevStr(hostdev)))
                     goto error;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, devstr);
+                VIR_FREE(devstr);
             }
         }

@@ -5416,26 +5305,22 @@ int qemudBuildCommandLine(virConnectPtr conn,
                             goto no_memory;
                         }

-                        if (VIR_REALLOC_N(*vmfds, (*nvmfds)+1) < 0) {
-                            VIR_FREE(configfd_name);
-                            VIR_FORCE_CLOSE(configfd);
-                            goto no_memory;
-                        }
-
-                        (*vmfds)[(*nvmfds)++] = configfd;
+                        virCommandTransferFD(cmd, configfd);
                     }
                 }
-                ADD_ARG_LIT("-device");
+                virCommandAddArg(cmd, "-device");
                 devstr = qemuBuildPCIHostdevDevStr(hostdev, configfd_name);
                 VIR_FREE(configfd_name);
                 if (!devstr)
                     goto error;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, devstr);
+                VIR_FREE(devstr);
             } else if (qemuCmdFlags & QEMUD_CMD_FLAG_PCIDEVICE) {
-                ADD_ARG_LIT("-pcidevice");
+                virCommandAddArg(cmd, "-pcidevice");
                 if (!(devstr = qemuBuildPCIHostdevPCIDevStr(hostdev)))
                     goto error;
-                ADD_ARG(devstr);
+                virCommandAddArg(cmd, devstr);
+                VIR_FREE(devstr);
             } else {
                 qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                 _("PCI device assignment is not supported by this version of qemu"));
@@ -5444,10 +5329,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
         }
     }

-    if (migrateFrom) {
-        ADD_ARG_LIT("-incoming");
-        ADD_ARG_LIT(migrateFrom);
-    }
+    if (migrateFrom)
+        virCommandAddArgList(cmd, "-incoming", migrateFrom, NULL);

     /* QEMU changed its default behavior to not include the virtio balloon
      * device.  Explicitly request it to ensure it will be present.
@@ -5465,76 +5348,43 @@ int qemudBuildCommandLine(virConnectPtr conn,
         }
         if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
             char *optstr;
-            ADD_ARG_LIT("-device");
+            virCommandAddArg(cmd, "-device");

             optstr = qemuBuildMemballoonDevStr(def->memballoon);
             if (!optstr)
                 goto error;
-            ADD_ARG(optstr);
+            virCommandAddArg(cmd, optstr);
+            VIR_FREE(optstr);
         } else if (qemuCmdFlags & QEMUD_CMD_FLAG_BALLOON) {
-            ADD_ARG_LIT("-balloon");
-            ADD_ARG_LIT("virtio");
+            virCommandAddArgList(cmd, "-balloon", "virtio", NULL);
         }
     }

-    if (current_snapshot && current_snapshot->def->active) {
-        ADD_ARG_LIT("-loadvm");
-        ADD_ARG_LIT(current_snapshot->def->name);
-    }
+    if (current_snapshot && current_snapshot->def->active)
+        virCommandAddArgList(cmd, "-loadvm", current_snapshot->def->name,
+                             NULL);

     if (def->namespaceData) {
-        qemuDomainCmdlineDefPtr cmd;
-
-        cmd = def->namespaceData;
-        for (i = 0; i < cmd->num_args; i++)
-            ADD_ARG_LIT(cmd->args[i]);
-        for (i = 0; i < cmd->num_env; i++) {
-            if (cmd->env_value[i])
-                ADD_ENV_PAIR(cmd->env_name[i], cmd->env_value[i]);
-            else
-                ADD_ENV_PAIR(cmd->env_name[i], "");
-        }
-    }
+        qemuDomainCmdlineDefPtr qemucmd;

-    ADD_ARG(NULL);
-    ADD_ENV(NULL);
+        qemucmd = def->namespaceData;
+        for (i = 0; i < qemucmd->num_args; i++)
+            virCommandAddArg(cmd, qemucmd->args[i]);
+        for (i = 0; i < qemucmd->num_env; i++)
+            virCommandAddEnvPair(cmd, qemucmd->env_name[i],
+                                 qemucmd->env_value[i]
+                                 ? qemucmd->env_value[i] : "");
+    }

-    *retargv = qargv;
-    *retenv = qenv;
-    return 0;
+    return cmd;

  no_memory:
     virReportOOMError();
  error:
     for (i = 0; i <= last_good_net; i++)
         virDomainConfNWFilterTeardown(def->nets[i]);
-    if (vmfds &&
-        *vmfds) {
-        for (i = 0; i < *nvmfds; i++)
-            VIR_FORCE_CLOSE((*vmfds)[i]);
-        VIR_FREE(*vmfds);
-        *nvmfds = 0;
-    }
-    if (qargv) {
-        for (i = 0 ; i < qargc ; i++)
-            VIR_FREE((qargv)[i]);
-        VIR_FREE(qargv);
-    }
-    if (qenv) {
-        for (i = 0 ; i < qenvc ; i++)
-            VIR_FREE((qenv)[i]);
-        VIR_FREE(qenv);
-    }
-    return -1;
-
-#undef ADD_ARG
-#undef ADD_ARG_LIT
-#undef ADD_ARG_SPACE
-#undef ADD_USBDISK
-#undef ADD_ENV
-#undef ADD_ENV_COPY
-#undef ADD_ENV_LIT
-#undef ADD_ENV_SPACE
+    virCommandFree(cmd);
+    return NULL;
 }


diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 790ce98..24df871 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -25,6 +25,7 @@
 # define __QEMUD_CONF_H

 # include <config.h>
+# include <stdbool.h>

 # include "ebtables.h"
 # include "internal.h"
@@ -40,6 +41,7 @@
 # include "cpu_conf.h"
 # include "driver.h"
 # include "bitmap.h"
+# include "command.h"

 # define qemudDebug(fmt, ...) do {} while(0)

@@ -227,16 +229,12 @@ int         qemudParseHelpStr           (const char *qemu,
                                          unsigned int *is_kvm,
                                          unsigned int *kvm_version);

-int         qemudBuildCommandLine       (virConnectPtr conn,
+virCommandPtr qemudBuildCommandLine     (virConnectPtr conn,
                                          struct qemud_driver *driver,
                                          virDomainDefPtr def,
                                          virDomainChrDefPtr monitor_chr,
-                                         int monitor_json,
+                                         bool monitor_json,
                                          unsigned long long qemuCmdFlags,
-                                         const char ***retargv,
-                                         const char ***retenv,
-                                         int **vmfds,
-                                         int *nvmfds,
                                          const char *migrateFrom,
                                          virDomainSnapshotObjPtr current_snapshot)
     ATTRIBUTE_NONNULL(1);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f00d8a3..38d7bd2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3018,14 +3018,6 @@ qemuAssignPCIAddresses(virDomainDefPtr def)
     int ret = -1;
     unsigned long long qemuCmdFlags = 0;
     qemuDomainPCIAddressSetPtr addrs = NULL;
-    struct stat sb;
-
-    if (stat(def->emulator, &sb) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot find QEMU binary %s"),
-                             def->emulator);
-        goto cleanup;
-    }

     if (qemudExtractVersionInfo(def->emulator,
                                 NULL,
@@ -3865,30 +3857,21 @@ static int qemudStartVMDaemon(virConnectPtr conn,
                               bool start_paused,
                               int stdin_fd,
                               const char *stdin_path) {
-    const char **argv = NULL, **tmp;
-    const char **progenv = NULL;
-    int i, ret, runflags;
-    struct stat sb;
-    int *vmfds = NULL;
-    int nvmfds = 0;
+    int ret;
     unsigned long long qemuCmdFlags;
-    fd_set keepfd;
-    const char *emulator;
-    pid_t child;
     int pos = -1;
     char ebuf[1024];
     char *pidfile = NULL;
     int logfile = -1;
     char *timestamp;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    virCommandPtr cmd = NULL;

     struct qemudHookData hookData;
     hookData.conn = conn;
     hookData.vm = vm;
     hookData.driver = driver;

-    FD_ZERO(&keepfd);
-
     DEBUG0("Beginning VM startup process");

     if (virDomainObjIsActive(vm)) {
@@ -3979,21 +3962,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
     if ((logfile = qemudLogFD(driver, vm->def->name, false)) < 0)
         goto cleanup;

-    emulator = vm->def->emulator;
-
-    /* Make sure the binary we are about to try exec'ing exists.
-     * Technically we could catch the exec() failure, but that's
-     * in a sub-process so its hard to feed back a useful error
-     */
-    if (stat(emulator, &sb) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot find QEMU binary %s"),
-                             emulator);
-        goto cleanup;
-    }
-
-    DEBUG0("Determing emulator version");
-    if (qemudExtractVersionInfo(emulator,
+    DEBUG0("Determining emulator version");
+    if (qemudExtractVersionInfo(vm->def->emulator,
                                 NULL,
                                 &qemuCmdFlags) < 0)
         goto cleanup;
@@ -4062,10 +4032,10 @@ static int qemudStartVMDaemon(virConnectPtr conn,

     DEBUG0("Building emulator command line");
     vm->def->id = driver->nextvmid++;
-    if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
-                              priv->monJSON, qemuCmdFlags, &argv, &progenv,
-                              &vmfds, &nvmfds, migrateFrom,
-                              vm->current_snapshot) < 0)
+    if (!(cmd = qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
+                                      priv->monJSON != 0, qemuCmdFlags,
+                                      migrateFrom,
+                                      vm->current_snapshot)))
         goto cleanup;

     if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0)
@@ -4100,50 +4070,28 @@ static int qemudStartVMDaemon(virConnectPtr conn,
         VIR_FREE(timestamp);
     }

-    tmp = progenv;
-
-    while (*tmp) {
-        if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
-            VIR_WARN("Unable to write envv to logfile: %s",
-                     virStrerror(errno, ebuf, sizeof ebuf));
-        if (safewrite(logfile, " ", 1) < 0)
-            VIR_WARN("Unable to write envv to logfile: %s",
-                     virStrerror(errno, ebuf, sizeof ebuf));
-        tmp++;
-    }
-    tmp = argv;
-    while (*tmp) {
-        if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
-            VIR_WARN("Unable to write argv to logfile: %s",
-                     virStrerror(errno, ebuf, sizeof ebuf));
-        if (safewrite(logfile, " ", 1) < 0)
-            VIR_WARN("Unable to write argv to logfile: %s",
-                     virStrerror(errno, ebuf, sizeof ebuf));
-        tmp++;
-    }
-    if (safewrite(logfile, "\n", 1) < 0)
-        VIR_WARN("Unable to write argv to logfile: %s",
-                 virStrerror(errno, ebuf, sizeof ebuf));
+    virCommandWriteArgLog(cmd, logfile);

     if ((pos = lseek(logfile, 0, SEEK_END)) < 0)
         VIR_WARN("Unable to seek to end of logfile: %s",
                  virStrerror(errno, ebuf, sizeof ebuf));

-    for (i = 0 ; i < nvmfds ; i++)
-        FD_SET(vmfds[i], &keepfd);
-
     VIR_DEBUG("Clear emulator capabilities: %d",
               driver->clearEmulatorCapabilities);
-    runflags = VIR_EXEC_NONBLOCK;
-    if (driver->clearEmulatorCapabilities) {
-        runflags |= VIR_EXEC_CLEAR_CAPS;
-    }
-
-    ret = virExecDaemonize(argv, progenv, &keepfd, &child,
-                           stdin_fd, &logfile, &logfile,
-                           runflags,
-                           qemudSecurityHook, &hookData,
-                           pidfile);
+    if (driver->clearEmulatorCapabilities)
+        virCommandClearCaps(cmd);
+
+    VIR_WARN("Executing %s", vm->def->emulator);
+    virCommandSetPreExecHook(cmd, qemudSecurityHook, &hookData);
+    virCommandSetInputFD(cmd, stdin_fd);
+    virCommandSetOutputFD(cmd, &logfile);
+    virCommandSetErrorFD(cmd, &logfile);
+    virCommandNonblockingFDs(cmd);
+    virCommandSetPidFile(cmd, pidfile);
+    virCommandDaemonize(cmd);
+
+    ret = virCommandRun(cmd, NULL);
+    VIR_WARN("Executing done %s", vm->def->emulator);
     VIR_FREE(pidfile);

     /* wait for qemu process to to show up */
@@ -4153,7 +4101,13 @@ static int qemudStartVMDaemon(virConnectPtr conn,
                             _("Domain %s didn't show up\n"), vm->def->name);
             ret = -1;
         }
+#if 0
     } else if (ret == -2) {
+        /*
+         * XXX this is bogus. It isn't safe to set vm->pid = child
+         * because the child no longer exists.
+         */
+
         /* The virExec process that launches the daemon failed. Pending on
          * when it failed (we can't determine for sure), there may be
          * extra info in the domain log (if the hook failed for example).
@@ -4163,30 +4117,16 @@ static int qemudStartVMDaemon(virConnectPtr conn,
          */
         vm->pid = child;
         ret = 0;
+#endif
     }

     if (migrateFrom)
         start_paused = true;
     vm->state = start_paused ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;

-    for (i = 0 ; argv[i] ; i++)
-        VIR_FREE(argv[i]);
-    VIR_FREE(argv);
-
-    for (i = 0 ; progenv[i] ; i++)
-        VIR_FREE(progenv[i]);
-    VIR_FREE(progenv);
-
     if (ret == -1) /* The VM failed to start; tear filters before taps */
         virDomainConfVMNWFilterTeardown(vm);

-    if (vmfds) {
-        for (i = 0 ; i < nvmfds ; i++) {
-            VIR_FORCE_CLOSE(vmfds[i]);
-        }
-        VIR_FREE(vmfds);
-    }
-
     if (ret == -1) /* The VM failed to start */
         goto cleanup;

@@ -4240,6 +4180,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
     if (virDomainObjSetDefTransient(driver->caps, vm) < 0)
         goto cleanup;

+    virCommandFree(cmd);
     VIR_FORCE_CLOSE(logfile);

     return 0;
@@ -4248,9 +4189,9 @@ cleanup:
     /* We jump here if we failed to start the VM for any reason, or
      * if we failed to initialize the now running VM. kill it off and
      * pretend we never started it */
-    qemudShutdownVMDaemon(driver, vm, 0);
-
+    virCommandFree(cmd);
     VIR_FORCE_CLOSE(logfile);
+    qemudShutdownVMDaemon(driver, vm, 0);

     return -1;
 }
@@ -7312,13 +7253,8 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
     struct qemud_driver *driver = conn->privateData;
     virDomainDefPtr def = NULL;
     virDomainChrDef monConfig;
-    const char *emulator;
     unsigned long long qemuCmdFlags;
-    struct stat sb;
-    const char **retargv = NULL;
-    const char **retenv = NULL;
-    const char **tmp;
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virCommandPtr cmd = NULL;
     char *ret = NULL;
     int i;

@@ -7368,70 +7304,26 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
             def->graphics[i]->data.vnc.autoport)
             def->graphics[i]->data.vnc.port = 5900;
     }
-    emulator = def->emulator;
-
-    /* Make sure the binary we are about to try exec'ing exists.
-     * Technically we could catch the exec() failure, but that's
-     * in a sub-process so its hard to feed back a useful error
-     */
-    if (stat(emulator, &sb) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot find QEMU binary %s"),
-                             emulator);
-        goto cleanup;
-    }

-    if (qemudExtractVersionInfo(emulator,
+    if (qemudExtractVersionInfo(def->emulator,
                                 NULL,
-                                &qemuCmdFlags) < 0) {
-        qemuReportError(VIR_ERR_INTERNAL_ERROR,
-                        _("Cannot determine QEMU argv syntax %s"),
-                        emulator);
+                                &qemuCmdFlags) < 0)
         goto cleanup;
-    }

     if (qemuPrepareMonitorChr(driver, &monConfig, def->name) < 0)
         goto cleanup;

-    if (qemudBuildCommandLine(conn, driver, def,
-                              &monConfig, 0, qemuCmdFlags,
-                              &retargv, &retenv,
-                              NULL, NULL, /* Don't want it to create TAP devices */
-                              NULL, NULL) < 0) {
-        goto cleanup;
-    }
-
-    tmp = retenv;
-    while (*tmp) {
-        virBufferAdd(&buf, *tmp, strlen(*tmp));
-        virBufferAddLit(&buf, " ");
-        tmp++;
-    }
-    tmp = retargv;
-    while (*tmp) {
-        virBufferAdd(&buf, *tmp, strlen(*tmp));
-        virBufferAddLit(&buf, " ");
-        tmp++;
-    }
-
-    if (virBufferError(&buf)) {
-        virBufferFreeAndReset(&buf);
-        virReportOOMError();
+    if (!(cmd = qemudBuildCommandLine(conn, driver, def,
+                                      &monConfig, false, qemuCmdFlags,
+                                      NULL, NULL)))
         goto cleanup;
-    }

-    ret = virBufferContentAndReset(&buf);
+    ret = virCommandToString(cmd);

 cleanup:
     qemuDriverUnlock(driver);
-    for (tmp = retargv ; tmp && *tmp ; tmp++)
-        VIR_FREE(*tmp);
-    VIR_FREE(retargv);
-
-    for (tmp = retenv ; tmp && *tmp ; tmp++)
-        VIR_FREE(*tmp);
-    VIR_FREE(retenv);

+    virCommandFree(cmd);
     virDomainDefFree(def);
     return ret;
 }
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index b149ef4..07dde54 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -25,28 +25,30 @@ static struct qemud_driver driver;
 # define MAX_FILE 4096

 static int testCompareXMLToArgvFiles(const char *xml,
-                                     const char *cmd,
+                                     const char *cmdline,
                                      unsigned long long extraFlags,
                                      const char *migrateFrom,
                                      bool expectError) {
     char argvData[MAX_FILE];
     char *expectargv = &(argvData[0]);
+    int len;
     char *actualargv = NULL;
-    const char **argv = NULL;
-    const char **qenv = NULL;
-    const char **tmp = NULL;
-    int ret = -1, len;
+    int ret = -1;
     unsigned long long flags;
     virDomainDefPtr vmdef = NULL;
     virDomainChrDef monitor_chr;
     virConnectPtr conn;
     char *log = NULL;
+    virCommandPtr cmd = NULL;

     if (!(conn = virGetConnect()))
         goto fail;

-    if (virtTestLoadFile(cmd, &expectargv, MAX_FILE) < 0)
+    len = virtTestLoadFile(cmdline, &expectargv, MAX_FILE);
+    if (len < 0)
         goto fail;
+    if (len && expectargv[len - 1] == '\n')
+        expectargv[len - 1] = '\0';

     if (!(vmdef = virDomainDefParseFile(driver.caps, xml,
                                         VIR_DOMAIN_XML_INACTIVE)))
@@ -85,10 +87,9 @@ static int testCompareXMLToArgvFiles(const char *xml,

     free(virtTestLogContentAndReset());

-    if (qemudBuildCommandLine(conn, &driver,
-                              vmdef, &monitor_chr, 0, flags,
-                              &argv, &qenv,
-                              NULL, NULL, migrateFrom, NULL) < 0)
+    if (!(cmd = qemudBuildCommandLine(conn, &driver,
+                                      vmdef, &monitor_chr, false, flags,
+                                      migrateFrom, NULL)))
         goto fail;

     if ((log = virtTestLogContentAndReset()) == NULL)
@@ -105,36 +106,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
         virResetLastError();
     }

-    len = 1; /* for trailing newline */
-    tmp = qenv;
-    while (*tmp) {
-        len += strlen(*tmp) + 1;
-        tmp++;
-    }
-
-    tmp = argv;
-    while (*tmp) {
-        len += strlen(*tmp) + 1;
-        tmp++;
-    }
-    if ((actualargv = malloc(sizeof(*actualargv)*len)) == NULL)
+    if (!(actualargv = virCommandToString(cmd)))
         goto fail;
-    actualargv[0] = '\0';
-    tmp = qenv;
-    while (*tmp) {
-        if (actualargv[0])
-            strcat(actualargv, " ");
-        strcat(actualargv, *tmp);
-        tmp++;
-    }
-    tmp = argv;
-    while (*tmp) {
-        if (actualargv[0])
-            strcat(actualargv, " ");
-        strcat(actualargv, *tmp);
-        tmp++;
-    }
-    strcat(actualargv, "\n");

     if (STRNEQ(expectargv, actualargv)) {
         virtTestDifference(stderr, expectargv, actualargv);
@@ -146,22 +119,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
  fail:
     free(log);
     free(actualargv);
-    if (argv) {
-        tmp = argv;
-        while (*tmp) {
-            free(*(char**)tmp);
-            tmp++;
-        }
-        free(argv);
-    }
-    if (qenv) {
-        tmp = qenv;
-        while (*tmp) {
-            free(*(char**)tmp);
-            tmp++;
-        }
-        free(qenv);
-    }
+    virCommandFree(cmd);
     virDomainDefFree(vmdef);
     virUnrefConnect(conn);
     return ret;
-- 
1.7.3.2




More information about the libvir-list mailing list