WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 1/3]xl: Move xl command implementation to a seperate

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 1/3]xl: Move xl command implementation to a seperate file
From: Yang Hongyang <yanghy@xxxxxxxxxxxxxx>
Date: Thu, 29 Apr 2010 17:23:45 +0800
Delivery-date: Thu, 29 Apr 2010 02:26:14 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100415 Thunderbird/3.0.4
Move xl command implementation to a seperate file

Signed-off-by: Yang Hongyang <yanghy@xxxxxxxxxxxxxx>

diff -r 9a1d7caa2024 -r d23a0a1823ef tools/libxl/Makefile
--- a/tools/libxl/Makefile      Mon Apr 26 12:13:23 2010 +0100
+++ b/tools/libxl/Makefile      Thu Apr 29 22:07:08 2010 +0800
@@ -70,7 +70,10 @@
 xl.o: xl.c
        $(CC) $(CFLAGS) -c xl.c
 
-$(CLIENTS): xl.o libxlutil.so libxenlight.so
+xl_cmdimpl.o: xl_cmdimpl.c
+       $(CC) $(CFLAGS) -c xl_cmdimpl.c
+
+$(CLIENTS): xl.o xl_cmdimpl.o libxlutil.so libxenlight.so
        $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
 
 .PHONY: install
diff -r 9a1d7caa2024 -r d23a0a1823ef tools/libxl/xl.c
--- a/tools/libxl/xl.c  Mon Apr 26 12:13:23 2010 +0100
+++ b/tools/libxl/xl.c  Thu Apr 29 22:07:08 2010 +0800
@@ -17,74 +17,21 @@
 #include "libxl_osdeps.h"
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/time.h> /* for time */
-#include <getopt.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <arpa/inet.h>
-#include <sys/utsname.h> /* for utsname in xl info */
-#include <xenctrl.h>
 #include <ctype.h>
 #include <inttypes.h>
 
 #include "libxl.h"
-#include "libxl_utils.h"
-#include "libxlutil.h"
+#include "xl_cmdimpl.h"
 
-#define UUID_FMT 
"%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
-
-static int logfile = 2;
-
-/* every libxl action in xl uses this same libxl context */
-static struct libxl_ctx ctx;
-
-/* when we operate on a domain, it is this one: */
-static uint32_t domid;
-static const char *common_domname;
-
-
-static const char savefileheader_magic[32]=
-    "Xen saved domain, xl format\n \0 \r";
-
-static const char migrate_receiver_banner[]=
-    "xl migration receiver ready, send binary domain data.\n";
-static const char migrate_receiver_ready[]=
-    "domain received, ready to unpause";
-static const char migrate_permission_to_go[]=
-    "domain is yours, you are cleared to unpause";
-static const char migrate_report[]=
-    "my copy unpause results are as follows";
-  /* followed by one byte:
-   *     0: everything went well, domain is running
-   *            next thing is we all exit
-   * non-0: things went badly
-   *            next thing should be a migrate_permission_to_go
-   *            from target to source
-   */
-
-struct save_file_header {
-    char magic[32]; /* savefileheader_magic */
-    /* All uint32_ts are in domain's byte order. */
-    uint32_t byteorder; /* SAVEFILE_BYTEORDER_VALUE */
-    uint32_t mandatory_flags; /* unknown flags => reject restore */
-    uint32_t optional_flags; /* unknown flags => reject restore */
-    uint32_t optional_data_len; /* skip, or skip tail, if not understood */
-};
-
-/* Optional data, in order:
- *   4 bytes uint32_t  config file size
- *   n bytes           config file in Unix text file format
- */
-
-#define SAVEFILE_BYTEORDER_VALUE ((uint32_t)0x01020304UL)
+extern struct libxl_ctx ctx;
+extern int logfile;
 
 void log_callback(void *userdata, int loglevel, const char *file, int line, 
const char *func, char *s)
 {
@@ -94,2669 +41,6 @@
     write(logfile, str, strlen(str));
 }
 
-static int domain_qualifier_to_domid(const char *p, uint32_t *domid_r,
-                                     int *was_name_r)
-{
-    int i, alldigit;
-
-    alldigit = 1;
-    for (i = 0; p[i]; i++) {
-        if (!isdigit((uint8_t)p[i])) {
-            alldigit = 0;
-            break;
-        }
-    }
-
-    if (i > 0 && alldigit) {
-        *domid_r = strtoul(p, NULL, 10);
-        if (was_name_r) *was_name_r = 0;
-        return 0;
-    } else {
-        /* check here if it's a uuid and do proper conversion */
-    }
-    if (was_name_r) *was_name_r = 1;
-    return libxl_name_to_domid(&ctx, p, domid_r);
-}
-
-static void find_domain(const char *p)
-{
-    int rc, was_name;
-
-    rc = domain_qualifier_to_domid(p, &domid, &was_name);
-    if (rc) {
-        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
-        exit(2);
-    }
-    common_domname = was_name ? p : 0;
-}
-
-#define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
-
-void dolog(const char *file, int line, const char *func, char *fmt, ...)
-{
-    va_list ap;
-    char *s;
-    int rc;
-
-    va_start(ap, fmt);
-    rc = vasprintf(&s, fmt, ap);
-    va_end(ap);
-    if (rc >= 0)
-        write(logfile, s, rc);
-}
-
-static void init_create_info(libxl_domain_create_info *c_info)
-{
-    memset(c_info, '\0', sizeof(*c_info));
-    c_info->xsdata = NULL;
-    c_info->platformdata = NULL;
-    c_info->hvm = 1;
-    c_info->oos = 1;
-    c_info->ssidref = 0;
-}
-
-static void init_build_info(libxl_domain_build_info *b_info, 
libxl_domain_create_info *c_info)
-{
-    memset(b_info, '\0', sizeof(*b_info));
-    b_info->timer_mode = -1;
-    b_info->hpet = 1;
-    b_info->vpt_align = -1;
-    b_info->max_vcpus = 1;
-    b_info->max_memkb = 32 * 1024;
-    b_info->target_memkb = b_info->max_memkb;
-    if (c_info->hvm) {
-        b_info->shadow_memkb = 
libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus);
-        b_info->video_memkb = 8 * 1024;
-        b_info->kernel = "/usr/lib/xen/boot/hvmloader";
-        b_info->hvm = 1;
-        b_info->u.hvm.pae = 1;
-        b_info->u.hvm.apic = 1;
-        b_info->u.hvm.acpi = 1;
-        b_info->u.hvm.nx = 1;
-        b_info->u.hvm.viridian = 0;
-    } else {
-        b_info->u.pv.slack_memkb = 8 * 1024;
-    }
-}
-
-static void init_dm_info(libxl_device_model_info *dm_info,
-        libxl_domain_create_info *c_info, libxl_domain_build_info *b_info)
-{
-    int i;
-    memset(dm_info, '\0', sizeof(*dm_info));
-
-    for (i = 0; i < 16; i++) {
-        dm_info->uuid[i] = rand();
-    }
-
-    dm_info->dom_name = c_info->name;
-    dm_info->device_model = "/usr/lib/xen/bin/qemu-dm";
-    dm_info->videoram = b_info->video_memkb / 1024;
-    dm_info->apic = b_info->u.hvm.apic;
-
-    dm_info->stdvga = 0;
-    dm_info->vnc = 1;
-    dm_info->vnclisten = "127.0.0.1";
-    dm_info->vncdisplay = 0;
-    dm_info->vncunused = 0;
-    dm_info->keymap = NULL;
-    dm_info->sdl = 0;
-    dm_info->opengl = 0;
-    dm_info->nographic = 0;
-    dm_info->serial = NULL;
-    dm_info->boot = "cda";
-    dm_info->usb = 0;
-    dm_info->usbdevice = NULL;
-}
-
-static void init_nic_info(libxl_device_nic *nic_info, int devnum)
-{
-    memset(nic_info, '\0', sizeof(*nic_info));
-
-    nic_info->backend_domid = 0;
-    nic_info->domid = 0;
-    nic_info->devid = devnum;
-    nic_info->mtu = 1492;
-    nic_info->model = "e1000";
-    nic_info->mac[0] = 0x00;
-    nic_info->mac[1] = 0x16;
-    nic_info->mac[2] = 0x3e;
-    nic_info->mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
-    nic_info->mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
-    nic_info->mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
-    nic_info->ifname = NULL;
-    nic_info->bridge = "xenbr0";
-    nic_info->script = "/etc/xen/scripts/vif-bridge";
-    nic_info->nictype = NICTYPE_IOEMU;
-}
-
-static void init_vfb_info(libxl_device_vfb *vfb, int dev_num)
-{
-    memset(vfb, 0x00, sizeof(libxl_device_vfb));
-    vfb->devid = dev_num;
-    vfb->vnc = 1;
-    vfb->vnclisten = "127.0.0.1";
-    vfb->vncdisplay = 0;
-    vfb->vncunused = 1;
-    vfb->keymap = NULL;
-    vfb->sdl = 0;
-    vfb->opengl = 0;
-}
-
-static void init_vkb_info(libxl_device_vkb *vkb, int dev_num)
-{
-    memset(vkb, 0x00, sizeof(libxl_device_vkb));
-    vkb->devid = dev_num;
-}
-
-static void init_console_info(libxl_device_console *console, int dev_num, 
libxl_domain_build_state *state)
-{
-    memset(console, 0x00, sizeof(libxl_device_console));
-    console->devid = dev_num;
-    console->constype = CONSTYPE_XENCONSOLED;
-    if (state)
-        console->build_state = state;
-}
-
-static void printf_info(libxl_domain_create_info *c_info,
-                        libxl_domain_build_info *b_info,
-                        libxl_device_disk *disks,
-                        int num_disks,
-                        libxl_device_nic *vifs,
-                        int num_vifs,
-                        libxl_device_pci *pcidevs,
-                        int num_pcidevs,
-                        libxl_device_vfb *vfbs,
-                        int num_vfbs,
-                        libxl_device_vkb *vkb,
-                        int num_vkbs,
-                        libxl_device_model_info *dm_info)
-{
-    int i;
-    printf("*** domain_create_info ***\n");
-    printf("hvm: %d\n", c_info->hvm);
-    printf("hap: %d\n", c_info->hap);
-    printf("oos: %d\n", c_info->oos);
-    printf("ssidref: %d\n", c_info->ssidref);
-    printf("name: %s\n", c_info->name);
-    printf("uuid: " UUID_FMT "\n",
-           (c_info->uuid)[0], (c_info->uuid)[1], (c_info->uuid)[2], 
(c_info->uuid)[3],
-           (c_info->uuid)[4], (c_info->uuid)[5], (c_info->uuid)[6], 
(c_info->uuid)[7],
-           (c_info->uuid)[8], (c_info->uuid)[9], (c_info->uuid)[10], 
(c_info->uuid)[11],
-           (c_info->uuid)[12], (c_info->uuid)[13], (c_info->uuid)[14], 
(c_info->uuid)[15]);
-    if (c_info->xsdata)
-        printf("xsdata: contains data\n");
-    else
-        printf("xsdata: (null)\n");
-    if (c_info->platformdata)
-        printf("platformdata: contains data\n");
-    else
-        printf("platformdata: (null)\n");
-
-
-    printf("\n\n\n*** domain_build_info ***\n");
-    printf("timer_mode: %d\n", b_info->timer_mode);
-    printf("hpet: %d\n", b_info->hpet);
-    printf("vpt_align: %d\n", b_info->vpt_align);
-    printf("max_vcpus: %d\n", b_info->max_vcpus);
-    printf("tsc_mode: %d\n", b_info->tsc_mode);
-    printf("max_memkb: %d\n", b_info->max_memkb);
-    printf("target_memkb: %d\n", b_info->target_memkb);
-    printf("kernel: %s\n", b_info->kernel);
-    printf("hvm: %d\n", b_info->hvm);
-
-    if (c_info->hvm) {
-        printf("video_memkb: %d\n", b_info->video_memkb);
-        printf("shadow_memkb: %d\n", b_info->shadow_memkb);
-        printf("    pae: %d\n", b_info->u.hvm.pae);
-        printf("    apic: %d\n", b_info->u.hvm.apic);
-        printf("    acpi: %d\n", b_info->u.hvm.acpi);
-        printf("    nx: %d\n", b_info->u.hvm.nx);
-        printf("    viridian: %d\n", b_info->u.hvm.viridian);
-    } else {
-        printf("cmdline: %s\n", b_info->u.pv.cmdline);
-        printf("ramdisk: %s\n", b_info->u.pv.ramdisk);
-    }
-
-    for (i = 0; i < num_disks; i++) {
-        printf("\n\n\n*** disks_info: %d ***\n", i);
-        printf("backend_domid %d\n", disks[i].backend_domid);
-        printf("domid %d\n", disks[i].domid);
-        printf("physpath %s\n", disks[i].physpath);
-        printf("phystype %d\n", disks[i].phystype);
-        printf("virtpath %s\n", disks[i].virtpath);
-        printf("unpluggable %d\n", disks[i].unpluggable);
-        printf("readwrite %d\n", disks[i].readwrite);
-        printf("is_cdrom %d\n", disks[i].is_cdrom);
-    }
-
-    for (i = 0; i < num_vifs; i++) {
-        printf("\n\n\n*** vifs_info: %d ***\n", i);
-        printf("backend_domid %d\n", vifs[i].backend_domid);
-        printf("domid %d\n", vifs[i].domid);
-        printf("devid %d\n", vifs[i].devid);
-        printf("mtu %d\n", vifs[i].mtu);
-        printf("model %s\n", vifs[i].model);
-        printf("mac %02x:%02x:%02x:%02x:%02x:%02x\n", vifs[i].mac[0], 
vifs[i].mac[1], vifs[i].mac[2], vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
-    }
-
-    for (i = 0; i < num_pcidevs; i++) {
-        printf("\n\n\n*** pcidevs_info: %d ***\n", i);
-        printf("pci dev "PCI_BDF_VDEVFN"\n", pcidevs[i].domain, 
pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func, pcidevs[i].vdevfn);
-        printf("opts msitranslate %d power_mgmt %d\n", 
pcidevs[i].msitranslate, pcidevs[i].power_mgmt);
-    }
-
-    for (i = 0; i < num_vfbs; i++) {
-        printf("\n\n\n*** vfbs_info: %d ***\n", i);
-        printf("backend_domid %d\n", vfbs[i].backend_domid);
-        printf("domid %d\n", vfbs[i].domid);
-        printf("devid %d\n", vfbs[i].devid);
-        printf("vnc: %d\n", vfbs[i].vnc);
-        printf("vnclisten: %s\n", vfbs[i].vnclisten);
-        printf("vncdisplay: %d\n", vfbs[i].vncdisplay);
-        printf("vncunused: %d\n", vfbs[i].vncunused);
-        printf("keymap: %s\n", vfbs[i].keymap);
-        printf("sdl: %d\n", vfbs[i].sdl);
-        printf("opengl: %d\n", vfbs[i].opengl);
-        printf("display: %s\n", vfbs[i].display);
-        printf("xauthority: %s\n", vfbs[i].xauthority);
-    }
-
-    if (c_info->hvm) {
-        printf("\n\n\n*** device_model_info ***\n");
-        printf("domid: %d\n", dm_info->domid);
-        printf("dom_name: %s\n", dm_info->dom_name);
-        printf("device_model: %s\n", dm_info->device_model);
-        printf("videoram: %d\n", dm_info->videoram);
-        printf("stdvga: %d\n", dm_info->stdvga);
-        printf("vnc: %d\n", dm_info->vnc);
-        printf("vnclisten: %s\n", dm_info->vnclisten);
-        printf("vncdisplay: %d\n", dm_info->vncdisplay);
-        printf("vncunused: %d\n", dm_info->vncunused);
-        printf("keymap: %s\n", dm_info->keymap);
-        printf("sdl: %d\n", dm_info->sdl);
-        printf("opengl: %d\n", dm_info->opengl);
-        printf("nographic: %d\n", dm_info->nographic);
-        printf("serial: %s\n", dm_info->serial);
-        printf("boot: %s\n", dm_info->boot);
-        printf("usb: %d\n", dm_info->usb);
-        printf("usbdevice: %s\n", dm_info->usbdevice);
-        printf("apic: %d\n", dm_info->apic);
-    }
-}
-
-static void parse_config_data(const char *configfile_filename_report,
-                              const char *configfile_data,
-                              int configfile_len,
-                              libxl_domain_create_info *c_info,
-                              libxl_domain_build_info *b_info,
-                              libxl_device_disk **disks,
-                              int *num_disks,
-                              libxl_device_nic **vifs,
-                              int *num_vifs,
-                              libxl_device_pci **pcidevs,
-                              int *num_pcidevs,
-                              libxl_device_vfb **vfbs,
-                              int *num_vfbs,
-                              libxl_device_vkb **vkbs,
-                              int *num_vkbs,
-                              libxl_device_model_info *dm_info)
-{
-    const char *buf;
-    long l;
-    XLU_Config *config;
-    XLU_ConfigList *vbds, *nics, *pcis, *cvfbs;
-    int pci_power_mgmt = 0;
-    int pci_msitranslate = 1;
-    int i, e;
-
-    config= xlu_cfg_init(stderr, configfile_filename_report);
-    if (!config) {
-        fprintf(stderr, "Failed to allocate for configuration\n");
-        exit(1);
-    }
-
-    e= xlu_cfg_readdata(config, configfile_data, configfile_len);
-    if (e) {
-        fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
-        exit(1);
-    }
-
-    init_create_info(c_info);
-
-    c_info->hvm = 0;
-    if (!xlu_cfg_get_string (config, "builder", &buf) &&
-        !strncmp(buf, "hvm", strlen(buf)))
-        c_info->hvm = 1;
-
-    /* hap is missing */
-    if (!xlu_cfg_get_string (config, "name", &buf))
-        c_info->name = strdup(buf);
-    else
-        c_info->name = "test";
-    for (i = 0; i < 16; i++) {
-        c_info->uuid[i] = rand();
-    }
-
-    if (!xlu_cfg_get_long(config, "oos", &l))
-        c_info->oos = l;
-
-    init_build_info(b_info, c_info);
-
-    /* the following is the actual config parsing with overriding values in 
the structures */
-    if (!xlu_cfg_get_long (config, "vcpus", &l))
-        b_info->max_vcpus = l;
-
-    if (!xlu_cfg_get_long (config, "memory", &l)) {
-        b_info->max_memkb = l * 1024;
-        b_info->target_memkb = b_info->max_memkb;
-    }
-
-    if (!xlu_cfg_get_long(config, "tsc_mode", &l))
-        b_info->tsc_mode = l;
-
-    if (!xlu_cfg_get_long (config, "shadow_memory", &l))
-        b_info->shadow_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long (config, "videoram", &l))
-        b_info->video_memkb = l * 1024;
-
-    if (!xlu_cfg_get_string (config, "kernel", &buf))
-        b_info->kernel = strdup(buf);
-
-    if (c_info->hvm == 1) {
-        if (!xlu_cfg_get_long (config, "pae", &l))
-            b_info->u.hvm.pae = l;
-        if (!xlu_cfg_get_long (config, "apic", &l))
-            b_info->u.hvm.apic = l;
-        if (!xlu_cfg_get_long (config, "acpi", &l))
-            b_info->u.hvm.acpi = l;
-        if (!xlu_cfg_get_long (config, "nx", &l))
-            b_info->u.hvm.nx = l;
-        if (!xlu_cfg_get_long (config, "viridian", &l))
-            b_info->u.hvm.viridian = l;
-    } else {
-        char *cmdline;
-        if (!xlu_cfg_get_string (config, "root", &buf)) {
-            asprintf(&cmdline, "root=%s", buf);
-            b_info->u.pv.cmdline = cmdline;
-        }
-        if (!xlu_cfg_get_string (config, "ramdisk", &buf))
-            b_info->u.pv.ramdisk = strdup(buf);
-    }
-
-    if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
-        *num_disks = 0;
-        *disks = NULL;
-        while ((buf = xlu_cfg_get_listitem (vbds, *num_disks)) != NULL) {
-            char *buf2 = strdup(buf);
-            char *p, *p2;
-            *disks = (libxl_device_disk *) realloc(*disks, sizeof 
(libxl_device_disk) * ((*num_disks) + 1));
-            (*disks)[*num_disks].backend_domid = 0;
-            (*disks)[*num_disks].domid = 0;
-            (*disks)[*num_disks].unpluggable = 0;
-            p = strtok(buf2, ",:");
-            while (*p == ' ')
-                p++;
-            if (!strcmp(p, "phy")) {
-                (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
-            } else if (!strcmp(p, "file")) {
-                (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
-            } else if (!strcmp(p, "tap")) {
-                p = strtok(NULL, ":");
-                if (!strcmp(p, "aio")) {
-                    (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
-                } else if (!strcmp(p, "vhd")) {
-                    (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
-                } else if (!strcmp(p, "qcow")) {
-                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
-                } else if (!strcmp(p, "qcow2")) {
-                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
-                }
-            }
-            p = strtok(NULL, ",");
-            while (*p == ' ')
-                p++;
-            (*disks)[*num_disks].physpath= strdup(p);
-            p = strtok(NULL, ",");
-            while (*p == ' ')
-                p++;
-            p2 = strchr(p, ':');
-            if (p2 == NULL) {
-                (*disks)[*num_disks].virtpath = strdup(p);
-                (*disks)[*num_disks].is_cdrom = 0;
-                (*disks)[*num_disks].unpluggable = 1;
-            } else {
-                *p2 = '\0';
-                (*disks)[*num_disks].virtpath = strdup(p);
-                if (!strcmp(p2 + 1, "cdrom")) {
-                    (*disks)[*num_disks].is_cdrom = 1;
-                    (*disks)[*num_disks].unpluggable = 1;
-                } else
-                    (*disks)[*num_disks].is_cdrom = 0;
-            }
-            p = strtok(NULL, ",");
-            while (*p == ' ')
-                p++;
-            (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
-            free(buf2);
-            *num_disks = (*num_disks) + 1;
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "vif", &nics, 0)) {
-        *num_vifs = 0;
-        *vifs = NULL;
-        while ((buf = xlu_cfg_get_listitem (nics, *num_vifs)) != NULL) {
-            char *buf2 = strdup(buf);
-            char *p, *p2;
-            *vifs = (libxl_device_nic *) realloc(*vifs, sizeof 
(libxl_device_nic) * ((*num_vifs) + 1));
-            init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip;
-            do {
-                while (*p == ' ')
-                    p++;
-                if ((p2 = strchr(p, '=')) == NULL)
-                    break;
-                *p2 = '\0';
-                if (!strcmp(p, "model")) {
-                    (*vifs)[*num_vifs].model = strdup(p2 + 1);
-                } else if (!strcmp(p, "mac")) {
-                    char *p3 = p2 + 1;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
-                } else if (!strcmp(p, "bridge")) {
-                    (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
-                } else if (!strcmp(p, "type")) {
-                    if (!strcmp(p2 + 1, "ioemu"))
-                        (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
-                    else
-                        (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
-                } else if (!strcmp(p, "ip")) {
-                    inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
-                } else if (!strcmp(p, "script")) {
-                    (*vifs)[*num_vifs].script = strdup(p2 + 1);
-                } else if (!strcmp(p, "vifname")) {
-                    (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
-                } else if (!strcmp(p, "rate")) {
-                    fprintf(stderr, "the rate parameter for vifs is currently 
not supported\n");
-                } else if (!strcmp(p, "accel")) {
-                    fprintf(stderr, "the accel parameter for vifs is currently 
not supported\n");
-                }
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip:
-            free(buf2);
-            *num_vifs = (*num_vifs) + 1;
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
-        *num_vfbs = 0;
-        *num_vkbs = 0;
-        *vfbs = NULL;
-        *vkbs = NULL;
-        while ((buf = xlu_cfg_get_listitem (cvfbs, *num_vfbs)) != NULL) {
-            char *buf2 = strdup(buf);
-            char *p, *p2;
-            *vfbs = (libxl_device_vfb *) realloc(*vfbs, 
sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
-            init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
-
-            *vkbs = (libxl_device_vkb *) realloc(*vkbs, 
sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
-            init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
-
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_vfb;
-            do {
-                while (*p == ' ')
-                    p++;
-                if ((p2 = strchr(p, '=')) == NULL)
-                    break;
-                *p2 = '\0';
-                if (!strcmp(p, "vnc")) {
-                    (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
-                } else if (!strcmp(p, "vnclisten")) {
-                    (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
-                } else if (!strcmp(p, "vncdisplay")) {
-                    (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
-                } else if (!strcmp(p, "vncunused")) {
-                    (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
-                } else if (!strcmp(p, "keymap")) {
-                    (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
-                } else if (!strcmp(p, "sdl")) {
-                    (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
-                } else if (!strcmp(p, "opengl")) {
-                    (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
-                } else if (!strcmp(p, "display")) {
-                    (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
-                } else if (!strcmp(p, "xauthority")) {
-                    (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
-                }
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_vfb:
-            free(buf2);
-            *num_vfbs = (*num_vfbs) + 1;
-            *num_vkbs = (*num_vkbs) + 1;
-        }
-    }
-
-    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
-        pci_msitranslate = l;
-
-    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
-        pci_power_mgmt = l;
-
-    if (!xlu_cfg_get_list (config, "pci", &pcis, 0)) {
-        *num_pcidevs = 0;
-        *pcidevs = NULL;
-        while ((buf = xlu_cfg_get_listitem (pcis, *num_pcidevs)) != NULL) {
-            unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
-            char *buf2 = strdup(buf);
-            char *p;
-            *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof 
(libxl_device_pci) * ((*num_pcidevs) + 1));
-            memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_pci;
-            if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, 
&vdevfn)) {
-                sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
-                domain = 0;
-            }
-            libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, 
func, vdevfn);
-            (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
-            (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
-            while ((p = strtok(NULL, ",=")) != NULL) {
-                while (*p == ' ')
-                    p++;
-                if (!strcmp(p, "msitranslate")) {
-                    p = strtok(NULL, ",=");
-                    (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
-                } else if (!strcmp(p, "power_mgmt")) {
-                    p = strtok(NULL, ",=");
-                    (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
-                }
-            }
-            *num_pcidevs = (*num_pcidevs) + 1;
-skip_pci:
-            free(buf2);
-        }
-    }
-
-    if (c_info->hvm == 1) {
-        /* init dm from c and b */
-        init_dm_info(dm_info, c_info, b_info);
-
-        /* then process config related to dm */
-        if (!xlu_cfg_get_string (config, "device_model", &buf))
-            dm_info->device_model = strdup(buf);
-        if (!xlu_cfg_get_long (config, "stdvga", &l))
-            dm_info->stdvga = l;
-        if (!xlu_cfg_get_long (config, "vnc", &l))
-            dm_info->vnc = l;
-        if (!xlu_cfg_get_string (config, "vnclisten", &buf))
-            dm_info->vnclisten = strdup(buf);
-        if (!xlu_cfg_get_long (config, "vncdisplay", &l))
-            dm_info->vncdisplay = l;
-        if (!xlu_cfg_get_long (config, "vncunused", &l))
-            dm_info->vncunused = l;
-        if (!xlu_cfg_get_string (config, "keymap", &buf))
-            dm_info->keymap = strdup(buf);
-        if (!xlu_cfg_get_long (config, "sdl", &l))
-            dm_info->sdl = l;
-        if (!xlu_cfg_get_long (config, "opengl", &l))
-            dm_info->opengl = l;
-        if (!xlu_cfg_get_long (config, "nographic", &l))
-            dm_info->nographic = l;
-        if (!xlu_cfg_get_string (config, "serial", &buf))
-            dm_info->serial = strdup(buf);
-        if (!xlu_cfg_get_string (config, "boot", &buf))
-            dm_info->boot = strdup(buf);
-        if (!xlu_cfg_get_long (config, "usb", &l))
-            dm_info->usb = l;
-        if (!xlu_cfg_get_string (config, "usbdevice", &buf))
-            dm_info->usbdevice = strdup(buf);
-    }
-
-    dm_info->type = c_info->hvm ? XENFV : XENPV;
-
-    xlu_cfg_destroy(config);
-}
-
-#define CHK_ERRNO( call ) ({                                            \
-        int chk_errno = (call);                                         \
-        if (chk_errno) {                                                \
-            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
-                    __FILE__,__LINE__, strerror(chk_errno), #call);     \
-            exit(-ERROR_FAIL);                                          \
-        }                                                               \
-    })
-
-#define MUST( call ) ({                                                 \
-        int must_rc = (call);                                           \
-        if (must_rc) {                                                  \
-            fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
-                    __FILE__,__LINE__, must_rc, #call);                 \
-            exit(-must_rc);                                             \
-        }                                                               \
-    })
-
-static void *xmalloc(size_t sz) {
-    void *r;
-    r = malloc(sz);
-    if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
-                      (unsigned long)sz); exit(-ERROR_FAIL); }
-    return r;
-}
-
-static void *xrealloc(void *ptr, size_t sz) {
-    void *r;
-    if (!sz) { free(ptr); return 0; }
-      /* realloc(non-0, 0) has a useless return value;
-       * but xrealloc(anything, 0) is like free
-       */
-    r = realloc(ptr, sz);
-    if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
-                      (unsigned long)sz); exit(-ERROR_FAIL); }
-    return r;
-}
-
-static int create_domain(int debug, int daemonize, const char *config_file, 
const char *restore_file, int paused, int migrate_fd /* -1 means none */, char 
**migration_domname_r)
-{
-    libxl_domain_create_info info1;
-    libxl_domain_build_info info2;
-    libxl_domain_build_state state;
-    libxl_device_model_info dm_info;
-    libxl_device_disk *disks = NULL;
-    libxl_device_nic *vifs = NULL;
-    libxl_device_pci *pcidevs = NULL;
-    libxl_device_vfb *vfbs = NULL;
-    libxl_device_vkb *vkbs = NULL;
-    libxl_device_console console;
-    int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 
0;
-    int i, fd;
-    int need_daemon = 1;
-    int ret, rc;
-    libxl_device_model_starting *dm_starting = 0;
-    libxl_waiter *w1 = NULL, *w2 = NULL;
-    void *config_data = 0;
-    int config_len = 0;
-    int restore_fd = -1;
-    struct save_file_header hdr;
-
-    memset(&dm_info, 0x00, sizeof(dm_info));
-
-    if (restore_file) {
-        uint8_t *optdata_begin = 0;
-        const uint8_t *optdata_here = 0;
-        union { uint32_t u32; char b[4]; } u32buf;
-        uint32_t badflags;
-
-        restore_fd = migrate_fd >= 0 ? migrate_fd :
-            open(restore_file, O_RDONLY);
-
-        CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, &hdr,
-                   sizeof(hdr), restore_file, "header") );
-        if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
-            fprintf(stderr, "File has wrong magic number -"
-                    " corrupt or for a different tool?\n");
-            return ERROR_INVAL;
-        }
-        if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
-            fprintf(stderr, "File has wrong byte order\n");
-            return ERROR_INVAL;
-        }
-        fprintf(stderr, "Loading new save file %s"
-                " (new xl fmt info"
-                " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
-                restore_file, hdr.mandatory_flags, hdr.optional_flags,
-                hdr.optional_data_len);
-
-        badflags = hdr.mandatory_flags & ~( 0 /* none understood yet */ );
-        if (badflags) {
-            fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
-                    "which are not supported; need newer xl\n",
-                    badflags);
-            return ERROR_INVAL;
-        }
-        if (hdr.optional_data_len) {
-            optdata_begin = xmalloc(hdr.optional_data_len);
-            CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, optdata_begin,
-                   hdr.optional_data_len, restore_file, "optdata") );
-        }
-
-#define OPTDATA_LEFT  (hdr.optional_data_len - (optdata_here - optdata_begin))
-#define WITH_OPTDATA(amt, body)                                 \
-            if (OPTDATA_LEFT < (amt)) {                         \
-                fprintf(stderr, "Savefile truncated.\n");       \
-                return ERROR_INVAL;                             \
-            } else {                                            \
-                body;                                           \
-                optdata_here += (amt);                          \
-            }
-
-        optdata_here = optdata_begin;
-
-        if (OPTDATA_LEFT) {
-            fprintf(stderr, " Savefile contains xl domain config\n");
-            WITH_OPTDATA(4, {
-                memcpy(u32buf.b, optdata_here, 4);
-                config_len = u32buf.u32;
-            });
-            WITH_OPTDATA(config_len, {
-                config_data = xmalloc(config_len);
-                memcpy(config_data, optdata_here, config_len);
-            });
-        }
-
-    }
-
-    if (config_file) {
-        free(config_data);  config_data = 0;
-        ret = libxl_read_file_contents(&ctx, config_file,
-                                       &config_data, &config_len);
-        if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
-                           config_file, strerror(errno)); return ERROR_FAIL; }
-    } else {
-        if (!config_data) {
-            fprintf(stderr, "Config file not specified and"
-                    " none in save file\n");
-            return ERROR_INVAL;
-        }
-        config_file = "<saved>";
-    }
-
-    printf("Parsing config file %s\n", config_file);
-
-    parse_config_data(config_file, config_data, config_len, &info1, &info2, 
&disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, 
&vkbs, &num_vkbs, &dm_info);
-
-    if (migrate_fd >= 0) {
-        if (info1.name) {
-            /* when we receive a domain we get its name from the config
-             * file; and we receive it to a temporary name */
-            assert(!common_domname);
-            common_domname = info1.name;
-            asprintf(migration_domname_r, "%s--incoming", info1.name);
-            info1.name = *migration_domname_r;
-        }
-    }
-
-    if (debug)
-        printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, 
num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
-
-start:
-    domid = 0;
-
-    ret = libxl_domain_make(&ctx, &info1, &domid);
-    if (ret) {
-        fprintf(stderr, "cannot make domain: %d\n", ret);
-        return ERROR_FAIL;
-    }
-
-    ret = libxl_userdata_store(&ctx, domid, "xl",
-                                    config_data, config_len);
-    if (ret) {
-        perror("cannot save config file");
-        return ERROR_FAIL;
-    }
-
-    if (!restore_file || !need_daemon) {
-        if (dm_info.saved_state) {
-            free(dm_info.saved_state);
-            dm_info.saved_state = NULL;
-        }
-        ret = libxl_domain_build(&ctx, &info2, domid, &state);
-    } else {
-        ret = libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, 
&dm_info);
-    }
-
-    if (ret) {
-        fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
-        return ERROR_FAIL;
-    }
-
-    for (i = 0; i < num_disks; i++) {
-        disks[i].domid = domid;
-        ret = libxl_device_disk_add(&ctx, domid, &disks[i]);
-        if (ret) {
-            fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
-            return ERROR_FAIL;
-        }
-    }
-    for (i = 0; i < num_vifs; i++) {
-        vifs[i].domid = domid;
-        ret = libxl_device_nic_add(&ctx, domid, &vifs[i]);
-        if (ret) {
-            fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
-            return ERROR_FAIL;
-        }
-    }
-    if (info1.hvm) {
-        dm_info.domid = domid;
-        MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
-                                        vifs, num_vifs, &dm_starting) );
-    } else {
-        for (i = 0; i < num_vfbs; i++) {
-            vfbs[i].domid = domid;
-            libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
-            vkbs[i].domid = domid;
-            libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
-        }
-        init_console_info(&console, 0, &state);
-        console.domid = domid;
-        if (num_vfbs)
-            console.constype = CONSTYPE_IOEMU;
-        libxl_device_console_add(&ctx, domid, &console);
-        if (num_vfbs)
-            libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
-    }
-
-    if (dm_starting)
-        MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
-    for (i = 0; i < num_pcidevs; i++)
-        libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
-
-    if (!paused)
-        libxl_domain_unpause(&ctx, domid);
-
-    if (!daemonize)
-        return 0; /* caller gets success in parent */
-
-    if (need_daemon) {
-        char *fullname, *name;
-        pid_t child1, got_child;
-        int nullfd;
-
-        child1 = libxl_fork(&ctx);
-        if (child1) {
-            int status;
-            for (;;) {
-                got_child = waitpid(child1, &status, 0);
-                if (got_child == child1) break;
-                assert(got_child == -1);
-                if (errno != EINTR) {
-                    perror("failed to wait for daemonizing child");
-                    return ERROR_FAIL;
-                }
-            }
-            if (status) {
-                libxl_report_child_exitstatus(&ctx, XL_LOG_ERROR,
-                           "daemonizing child", child1, status);
-                return ERROR_FAIL;
-            }
-            return 0; /* caller gets success in parent */
-        }
-
-        rc = libxl_ctx_postfork(&ctx);
-        if (rc) {
-            LOG("failed to reinitialise context after fork");
-            exit(-1);
-        }
-
-        asprintf(&name, "xl-%s", info1.name);
-        rc = libxl_create_logfile(&ctx, name, &fullname);
-        if (rc) {
-            LOG("failed to open logfile %s",fullname,strerror(errno));
-            exit(-1);
-        }
-
-        CHK_ERRNO(( logfile = open(fullname, O_WRONLY|O_CREAT, 0644) )<0);
-        free(fullname);
-        free(name);
-
-        CHK_ERRNO(( nullfd = open("/dev/null", O_RDONLY) )<0);
-        dup2(nullfd, 0);
-        dup2(logfile, 1);
-        dup2(logfile, 2);
-
-        daemon(0, 1);
-        need_daemon = 0;
-    }
-    LOG("Waiting for domain %s (domid %d) to die [pid %ld]",
-        info1.name, domid, (long)getpid());
-    w1 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter) * num_disks);
-    w2 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter));
-    libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
-    libxl_wait_for_domain_death(&ctx, domid, w2);
-    libxl_get_wait_fd(&ctx, &fd);
-    while (1) {
-        int ret;
-        fd_set rfds;
-        xc_domaininfo_t info;
-        libxl_event event;
-        libxl_device_disk disk;
-        memset(&info, 0x00, sizeof(xc_dominfo_t));
-
-        FD_ZERO(&rfds);
-        FD_SET(fd, &rfds);
-
-        ret = select(fd + 1, &rfds, NULL, NULL, NULL);
-        if (!ret)
-            continue;
-        libxl_get_event(&ctx, &event);
-        switch (event.type) {
-            case DOMAIN_DEATH:
-                if (libxl_event_get_domain_death_info(&ctx, domid, &event, 
&info)) {
-                    LOG("Domain %d is dead", domid);
-                    if (info.flags & XEN_DOMINF_dying || (info.flags & 
XEN_DOMINF_shutdown && (((info.flags >> XEN_DOMINF_shutdownshift) & 
XEN_DOMINF_shutdownmask) != SHUTDOWN_suspend))) {
-                        LOG("Domain %d needs to be clean: destroying the 
domain", domid);
-                        libxl_domain_destroy(&ctx, domid, 0);
-                        if (info.flags & XEN_DOMINF_shutdown &&
-                            (((info.flags >> XEN_DOMINF_shutdownshift) & 
XEN_DOMINF_shutdownmask) == SHUTDOWN_reboot)) {
-                            libxl_free_waiter(w1);
-                            libxl_free_waiter(w2);
-                            free(w1);
-                            free(w2);
-                            LOG("Done. Rebooting now");
-                            goto start;
-                        }
-                        LOG("Done. Exiting now");
-                    }
-                    LOG("Domain %d does not need to be clean, exiting now", 
domid);
-                    exit(0);
-                }
-                break;
-            case DISK_EJECT:
-                if (libxl_event_get_disk_eject_info(&ctx, domid, &event, 
&disk))
-                    libxl_cdrom_insert(&ctx, domid, &disk);
-                break;
-        }
-        libxl_free_event(&event);
-    }
-
-    close(logfile);
-    exit(0);
-}
-
-static void help(char *command)
-{
-    if (!command || !strcmp(command, "help")) {
-        printf("Usage xl <subcommand> [args]\n\n");
-        printf("xl full list of subcommands:\n\n");
-        printf(" create                        create a domain from config 
file <filename>\n\n");
-        printf(" list                          list information about all 
domains\n\n");
-        printf(" destroy                       terminate a domain 
immediately\n\n");
-        printf(" pci-attach                    insert a new pass-through pci 
device\n\n");
-        printf(" pci-detach                    remove a domain's pass-through 
pci device\n\n");
-        printf(" pci-list                      list pass-through pci devices 
for a domain\n\n");
-        printf(" pause                         pause execution of a 
domain\n\n");
-        printf(" unpause                       unpause a paused domain\n\n");
-        printf(" console                       attach to domain's 
console\n\n");
-        printf(" save                          save a domain state to restore 
later\n\n");
-        printf(" restore                       restore a domain from a saved 
state\n\n");
-        printf(" cd-insert                     insert a cdrom into a guest's 
cd drive\n\n");
-        printf(" cd-eject                      eject a cdrom from a guest's cd 
drive\n\n");
-        printf(" mem-set                       set the current memory usage 
for a domain\n\n");
-        printf(" button-press                  indicate an ACPI button press 
to the domain\n\n");
-        printf(" vcpu-list                     list the VCPUs for all/some 
domains.\n\n");
-        printf(" vcpu-pin                      Set which CPUs a VCPU can 
use.\n\n");
-        printf(" vcpu-set                      Set the number of active VCPUs 
allowed for the domain.\n\n");
-    } else if(!strcmp(command, "create")) {
-        printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
-        printf("Create a domain based on <ConfigFile>.\n\n");
-        printf("Options:\n\n");
-        printf("-h                     Print this help.\n");
-        printf("-p                     Leave the domain paused after it is 
created.\n");
-        printf("-d                     Enable debug messages.\n");
-        printf("-e                     Do not wait in the background for the 
death of the domain.\n");
-    } else if(!strcmp(command, "list")) {
-        printf("Usage: xl list [-v] [Domain]\n\n");
-        printf("List information about all/some domains.\n\n");
-    } else if(!strcmp(command, "pci-attach")) {
-        printf("Usage: xl pci-attach <Domain> <BDF> [Virtual Slot]\n\n");
-        printf("Insert a new pass-through pci device.\n\n");
-    } else if(!strcmp(command, "pci-detach")) {
-        printf("Usage: xl pci-detach <Domain> <BDF>\n\n");
-        printf("Remove a domain's pass-through pci device.\n\n");
-    } else if(!strcmp(command, "pci-list")) {
-        printf("Usage: xl pci-list <Domain>\n\n");
-        printf("List pass-through pci devices for a domain.\n\n");
-    } else if(!strcmp(command, "pause")) {
-        printf("Usage: xl pause <Domain>\n\n");
-        printf("Pause execution of a domain.\n\n");
-    } else if(!strcmp(command, "unpause")) {
-        printf("Usage: xl unpause <Domain>\n\n");
-        printf("Unpause a paused domain.\n\n");
-    } else if(!strcmp(command, "save")) {
-        printf("Usage: xl save [options] <Domain> <CheckpointFile> 
[<ConfigFile>]\n\n");
-        printf("Save a domain state to restore later.\n\n");
-        printf("Options:\n\n");
-        printf("-h                     Print this help.\n");
-        printf("-c                     Leave domain running after creating the 
snapshot.\n");
-    } else if(!strcmp(command, "restore")) {
-        printf("Usage: xl restore [options] [<ConfigFile>] 
<CheckpointFile>\n\n");
-        printf("Restore a domain from a saved state.\n\n");
-        printf("Options:\n\n");
-        printf("-h                     Print this help.\n");
-        printf("-p                     Do not unpause domain after restoring 
it.\n");
-        printf("-e                     Do not wait in the background for the 
death of the domain.\n");
-        printf("-d                     Enable debug messages.\n");
-    } else if(!strcmp(command, "migrate")) {
-        printf("Usage: xl migrate [options] <Domain> <host>\n\n");
-        printf("Save a domain state to restore later.\n\n");
-        printf("Options:\n\n");
-        printf("-h                     Print this help.\n");
-        printf("-C <config>            Send <config> instead of config file 
from creation.\n");
-        printf("-s <sshcommand>        Use <sshcommand> instead of ssh.  
String will be passed to sh.  If empty, run <host> instead of ssh <host> xl 
migrate-receive [-d -e]\n");
-        printf("-e                     Do not wait in the background (on 
<host>) for the death of the domain.\n");
-    } else if(!strcmp(command, "migrate-receive")) {
-        printf("Usage: xl migrate-receive  - for internal use only");
-    } else if(!strcmp(command, "restore")) {
-        printf("Usage: xl restore [options] [<ConfigFile>] 
<CheckpointFile>\n\n");
-        printf("Restore a domain from a saved state.\n\n");
-        printf("Options:\n\n");
-        printf("-h                     Print this help.\n");
-        printf("-O                     Old (configless) xl save format.\n");
-        printf("-p                     Do not unpause domain after restoring 
it.\n");
-        printf("-e                     Do not wait in the background for the 
death of the domain.\n");
-    } else if(!strcmp(command, "destroy")) {
-        printf("Usage: xl destroy <Domain>\n\n");
-        printf("Terminate a domain immediately.\n\n");
-    } else if (!strcmp(command, "console")) {
-        printf("Usage: xl console <Domain>\n\n");
-        printf("Attach to domain's console.\n\n");
-    } else if (!strcmp(command, "cd-insert")) {
-        printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
-        printf("Insert a cdrom into a guest's cd drive.\n\n");
-    } else if (!strcmp(command, "cd-eject")) {
-        printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
-        printf("Eject a cdrom from a guest's cd drive.\n\n");
-    } else if (!strcmp(command, "mem-set")) {
-        printf("Usage: xl mem-set <Domain> <MemKB>\n\n");
-        printf("Set the current memory usage for a domain.\n\n");
-    } else if (!strcmp(command, "button-press")) {
-        printf("Usage: xl button-press <Domain> <Button>\n\n");
-        printf("Indicate <Button> press to a domain.\n");
-        printf("<Button> may be 'power' or 'sleep'.\n\n");
-    } else if (!strcmp(command, "vcpu-list")) {
-        printf("Usage: xl vcpu-list [Domain, ...]\n\n");
-        printf("List the VCPUs for all/some domains.\n\n");
-    } else if (!strcmp(command, "vcpu-pin")) {
-        printf("Usage: xl vcpu-pin <Domain> <VCPU|all> <CPUs|all>\n\n");
-        printf("Set which CPUs a VCPU can use.\n\n");
-    } else if (!strcmp(command, "vcpu-set")) {
-        printf("Usage: xl vcpu-set <Domain> <vCPUs>\n\n");
-        printf("Set the number of active VCPUs for allowed for the 
domain.\n\n");
-    }
-}
-
-void set_memory_target(char *p, char *mem)
-{
-    char *endptr;
-    uint32_t memorykb;
-
-    find_domain(p);
-
-    memorykb = strtoul(mem, &endptr, 10);
-    if (*endptr != '\0') {
-        fprintf(stderr, "invalid memory size: %s\n", mem);
-        exit(3);
-    }
-    printf("setting domid %d memory to : %d\n", domid, memorykb);
-    libxl_set_memory_target(&ctx, domid, memorykb);
-}
-
-int main_memset(int argc, char **argv)
-{
-    int opt = 0;
-    char *p = NULL, *mem;
-
-    while ((opt = getopt(argc, argv, "h:")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("mem-set");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("mem-set");
-        exit(2);
-    }
-
-    p = argv[optind];
-    mem = argv[optind + 1];
-
-    set_memory_target(p, mem);
-    exit(0);
-}
-
-void console(char *p, int cons_num)
-{
-    find_domain(p);
-    libxl_console_attach(&ctx, domid, cons_num);
-}
-
-void cd_insert(char *dom, char *virtdev, char *phys)
-{
-    libxl_device_disk disk;
-    char *p;
-
-    find_domain(dom);
-
-    disk.backend_domid = 0;
-    disk.domid = domid;
-    if (phys) {
-        p = strchr(phys, ':');
-        if (!p) {
-            fprintf(stderr, "No type specified, ");
-            disk.physpath = phys;
-            if (!strncmp(phys, "/dev", 4)) {
-                fprintf(stderr, "assuming phy:\n");
-                disk.phystype = PHYSTYPE_PHY;
-            } else {
-                fprintf(stderr, "assuming file:\n");
-                disk.phystype = PHYSTYPE_FILE;
-            }
-        } else {
-            *p = '\0';
-            p++;
-            disk.physpath = p;
-            libxl_string_to_phystype(&ctx, phys, &disk.phystype);
-        }
-    } else {
-            disk.physpath = NULL;
-            disk.phystype = 0;
-    }
-    disk.virtpath = virtdev;
-    disk.unpluggable = 1;
-    disk.readwrite = 0;
-    disk.is_cdrom = 1;
-
-    libxl_cdrom_insert(&ctx, domid, &disk);
-}
-
-int main_cd_eject(int argc, char **argv)
-{
-    int opt = 0;
-    char *p = NULL, *virtdev;
-
-    while ((opt = getopt(argc, argv, "hn:")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("cd-eject");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("cd-eject");
-        exit(2);
-    }
-
-    p = argv[optind];
-    virtdev = argv[optind + 1];
-
-    cd_insert(p, virtdev, NULL);
-    exit(0);
-}
-
-int main_cd_insert(int argc, char **argv)
-{
-    int opt = 0;
-    char *p = NULL, *file = NULL, *virtdev;
-
-    while ((opt = getopt(argc, argv, "hn:")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("cd-insert");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 2) {
-        help("cd-insert");
-        exit(2);
-    }
-
-    p = argv[optind];
-    virtdev = argv[optind + 1];
-    file = argv[optind + 2];
-
-    cd_insert(p, virtdev, file);
-    exit(0);
-}
-
-int main_console(int argc, char **argv)
-{
-    int opt = 0, cons_num = 0;
-    char *p = NULL;
-
-    while ((opt = getopt(argc, argv, "hn:")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("console");
-            exit(0);
-        case 'n':
-            if (optarg) {
-                cons_num = strtol(optarg, NULL, 10);
-            }
-            break;
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("console");
-        exit(2);
-    }
-
-    p = argv[optind];
-
-    console(p, cons_num);
-    exit(0);
-}
-
-void pcilist(char *dom)
-{
-    libxl_device_pci *pcidevs;
-    int num, i;
-
-    find_domain(dom);
-
-    pcidevs = libxl_device_pci_list(&ctx, domid, &num);
-    if (!num)
-        return;
-    printf("VFn  domain bus  slot func\n");
-    for (i = 0; i < num; i++) {
-        printf("0x%02x 0x%04x 0x%02x 0x%02x 0x%01x\n", pcidevs[i].vdevfn, 
pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
-    }
-    free(pcidevs);
-}
-
-int main_pcilist(int argc, char **argv)
-{
-    int opt;
-    char *domname = NULL;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("pci-list");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("pci-list");
-        exit(2);
-    }
-
-    domname = argv[optind];
-
-    pcilist(domname);
-    exit(0);
-}
-
-void pcidetach(char *dom, char *bdf)
-{
-    libxl_device_pci pcidev;
-    unsigned int domain, bus, dev, func;
-
-    find_domain(dom);
-
-    memset(&pcidev, 0x00, sizeof(pcidev));
-    sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
-    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
-    libxl_device_pci_remove(&ctx, domid, &pcidev);
-}
-
-int main_pcidetach(int argc, char **argv)
-{
-    int opt;
-    char *domname = NULL, *bdf = NULL;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("pci-attach");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("pci-detach");
-        exit(2);
-    }
-
-    domname = argv[optind];
-    bdf = argv[optind + 1];
-
-    pcidetach(domname, bdf);
-    exit(0);
-}
-void pciattach(char *dom, char *bdf, char *vs)
-{
-    libxl_device_pci pcidev;
-    unsigned int domain, bus, dev, func;
-
-    find_domain(dom);
-
-    memset(&pcidev, 0x00, sizeof(pcidev));
-    sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
-    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
-    libxl_device_pci_add(&ctx, domid, &pcidev);
-}
-
-int main_pciattach(int argc, char **argv)
-{
-    int opt;
-    char *domname = NULL, *bdf = NULL, *vs = NULL;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("pci-attach");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("pci-attach");
-        exit(2);
-    }
-
-    domname = argv[optind];
-    bdf = argv[optind + 1];
-
-    if (optind + 1 < argc)
-        vs = argv[optind + 2];
-
-    pciattach(domname, bdf, vs);
-    exit(0);
-}
-
-void pause_domain(char *p)
-{
-    find_domain(p);
-    libxl_domain_pause(&ctx, domid);
-}
-
-void unpause_domain(char *p)
-{
-    find_domain(p);
-    libxl_domain_unpause(&ctx, domid);
-}
-
-void destroy_domain(char *p)
-{
-    int rc;
-    find_domain(p);
-    rc = libxl_domain_destroy(&ctx, domid, 0);
-    if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n.",rc); exit(-1); }
-}
-
-void list_domains(int verbose)
-{
-    struct libxl_dominfo *info;
-    int nb_domain, i;
-
-    info = libxl_list_domain(&ctx, &nb_domain);
-
-    if (!info) {
-        fprintf(stderr, "libxl_domain_infolist failed.\n");
-        exit(1);
-    }
-    printf("Name                                        ID   Mem 
VCPUs\tState\tTime(s)\n");
-    for (i = 0; i < nb_domain; i++) {
-        printf("%-40s %5d %5lu %5d        %c%c%c %8.1f",
-                libxl_domid_to_name(&ctx, info[i].domid),
-                info[i].domid,
-                (unsigned long) (info[i].max_memkb / 1024),
-                info[i].vcpu_online,
-                info[i].running ? 'r' : '-',
-                info[i].paused ? 'p' : '-',
-                info[i].dying ? 'd' : '-',
-                ((float)info[i].cpu_time / 1e9));
-        if (verbose) {
-            char *uuid = libxl_uuid2string(&ctx, info[i].uuid);
-            printf(" %s", uuid);
-        }
-        putchar('\n');
-    }
-    free(info);
-}
-
-void list_vm(void)
-{
-    struct libxl_vminfo *info;
-    int nb_vm, i;
-
-    info = libxl_list_vm(&ctx, &nb_vm);
-
-    if (info < 0) {
-        fprintf(stderr, "libxl_domain_infolist failed.\n");
-        exit(1);
-    }
-    printf("UUID                                  ID    name\n");
-    for (i = 0; i < nb_vm; i++) {
-        printf(UUID_FMT "  %d    %-30s\n",
-            info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
-            info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
-            info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], 
info[i].uuid[11],
-            info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], 
info[i].uuid[15],
-            info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
-    }
-    free(info);
-}
-
-static void save_domain_core_begin(char *domain_spec,
-                                   const char *override_config_file,
-                                   uint8_t **config_data_r,
-                                   int *config_len_r)
-{
-    int rc;
-
-    find_domain(domain_spec);
-
-    /* configuration file in optional data: */
-
-    if (override_config_file) {
-        void *config_v = 0;
-        rc = libxl_read_file_contents(&ctx, override_config_file,
-                                      &config_v, config_len_r);
-        *config_data_r = config_v;
-    } else {
-        rc = libxl_userdata_retrieve(&ctx, domid, "xl",
-                                     config_data_r, config_len_r);
-    }
-    if (rc) {
-        fputs("Unable to get config file\n",stderr);
-        exit(2);
-    }
-}
-
-void save_domain_core_writeconfig(int fd, const char *filename,
-                                  const uint8_t *config_data, int config_len)
-{
-    struct save_file_header hdr;
-    uint8_t *optdata_begin;
-    union { uint32_t u32; char b[4]; } u32buf;
-
-    memset(&hdr, 0, sizeof(hdr));
-    memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
-    hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
-
-    optdata_begin= 0;
-
-#define ADD_OPTDATA(ptr, len) ({                                            \
-    if ((len)) {                                                        \
-        hdr.optional_data_len += (len);                                 \
-        optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
-        memcpy(optdata_begin + hdr.optional_data_len - (len),           \
-               (ptr), (len));                                           \
-    }                                                                   \
-                          })
-
-    u32buf.u32 = config_len;
-    ADD_OPTDATA(u32buf.b,    4);
-    ADD_OPTDATA(config_data, config_len);
-
-    /* that's the optional data */
-
-    CHK_ERRNO( libxl_write_exactly(&ctx, fd,
-        &hdr, sizeof(hdr), filename, "header") );
-    CHK_ERRNO( libxl_write_exactly(&ctx, fd,
-        optdata_begin, hdr.optional_data_len, filename, "header") );
-
-    fprintf(stderr, "Saving to %s new xl format (info"
-            " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
-            filename, hdr.mandatory_flags, hdr.optional_flags,
-            hdr.optional_data_len);
-}
-
-int save_domain(char *p, char *filename, int checkpoint,
-                const char *override_config_file)
-{
-    int fd;
-    uint8_t *config_data;
-    int config_len;
-
-    save_domain_core_begin(p, override_config_file, &config_data, &config_len);
-
-    if (!config_len) {
-        fputs(" Savefile will not contain xl domain config\n", stderr);
-    }
-
-    fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
-    if (fd < 0) {
-        fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
-        exit(2);
-    }
-
-    save_domain_core_writeconfig(fd, filename, config_data, config_len);
-
-    libxl_domain_suspend(&ctx, NULL, domid, fd);
-    close(fd);
-
-    if (checkpoint)
-        libxl_domain_unpause(&ctx, domid);
-    else
-        libxl_domain_destroy(&ctx, domid, 0);
-
-    exit(0);
-}
-
-static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
-                                     const char *what, const char *rune) {
-    char buf[msgsz];
-    const char *stream;
-    int rc;
-
-    stream = rune ? "migration receiver stream" : "migration stream";
-    rc = libxl_read_exactly(&ctx, fd, buf, msgsz, stream, what);
-    if (rc) return ERROR_FAIL;
-
-    if (memcmp(buf, msg, msgsz)) {
-        fprintf(stderr, "%s contained unexpected data instead of %s\n",
-                stream, what);
-        if (rune)
-            fprintf(stderr, "(command run was: %s )\n", rune);
-        return ERROR_FAIL;
-    }
-    return 0;
-}
-
-static void migration_child_report(pid_t migration_child, int recv_fd) {
-    pid_t child;
-    int status, sr;
-    struct timeval now, waituntil, timeout;
-    static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
-
-    if (!migration_child) return;
-
-    CHK_ERRNO( gettimeofday(&waituntil, 0) );
-    waituntil.tv_sec += 2;
-
-    for (;;) {
-        child = waitpid(migration_child, &status, WNOHANG);
-
-        if (child == migration_child) {
-            if (status)
-                libxl_report_child_exitstatus(&ctx, XL_LOG_INFO,
-                                              "migration target process",
-                                              migration_child, status);
-            break;
-        }
-        if (child == -1) {
-            if (errno == EINTR) continue;
-            fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
-                    (long)migration_child, strerror(errno));
-            break;
-        }
-        assert(child == 0);
-
-        CHK_ERRNO( gettimeofday(&now, 0) );
-        if (timercmp(&now, &waituntil, >)) {
-            fprintf(stderr, "migration child [%ld] not exiting, no longer"
-                    " waiting (exit status will be unreported)\n",
-                    (long)migration_child);
-            break;
-        }
-        timersub(&waituntil, &now, &timeout);
-
-        if (recv_fd >= 0) {
-            fd_set readfds, exceptfds;
-            FD_ZERO(&readfds);
-            FD_ZERO(&exceptfds);
-            FD_SET(recv_fd, &readfds);
-            FD_SET(recv_fd, &exceptfds);
-            sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
-        } else {
-            if (timercmp(&timeout, &pollinterval, >))
-                timeout = pollinterval;
-            sr = select(0,0,0,0, &timeout);
-        }
-        if (sr > 0) {
-            recv_fd = -1;
-        } else if (sr == 0) {
-        } else if (sr == -1) {
-            if (errno != EINTR) {
-                fprintf(stderr, "migration child [%ld] exit wait select"
-                        " failed unexpectedly: %s\n",
-                        (long)migration_child, strerror(errno));
-                break;
-            }
-        }
-    }
-    migration_child = 0;
-}
-
-static void migrate_domain(char *domain_spec, const char *rune,
-                           const char *override_config_file)
-{
-    pid_t child = -1;
-    int rc;
-    int sendpipe[2], recvpipe[2];
-    int send_fd, recv_fd;
-    libxl_domain_suspend_info suspinfo;
-    char *away_domname;
-    char rc_buf;
-    uint8_t *config_data;
-    int config_len;
-
-    save_domain_core_begin(domain_spec, override_config_file,
-                           &config_data, &config_len);
-
-    if (!common_domname) {
-        common_domname = libxl_domid_to_name(&ctx, domid);
-        /* libxl_domid_to_name fails ?  don't bother with names then */
-    }
-
-    if (!config_len) {
-        fprintf(stderr, "No config file stored for running domain and "
-                "none supplied - cannot migrate.\n");
-        exit(1);
-    }
-
-    MUST( libxl_pipe(&ctx, sendpipe) );
-    MUST( libxl_pipe(&ctx, recvpipe) );
-
-    child = libxl_fork(&ctx);
-    if (child==-1) exit(1);
-
-    if (!child) {
-        dup2(sendpipe[0], 0);
-        dup2(recvpipe[1], 1);
-        close(sendpipe[0]); close(sendpipe[1]);
-        close(recvpipe[0]); close(recvpipe[1]);
-        execlp("sh","sh","-c",rune,(char*)0);
-        perror("failed to exec sh");
-        exit(-1);
-    }
-
-    close(sendpipe[0]);
-    close(recvpipe[1]);
-    send_fd = sendpipe[1];
-    recv_fd = recvpipe[0];
-
-    signal(SIGPIPE, SIG_IGN);
-    /* if receiver dies, we get an error and can clean up
-       rather than just dying */
-
-    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
-                                   sizeof(migrate_receiver_banner)-1,
-                                   "banner", rune);
-    if (rc) {
-        close(send_fd);
-        migration_child_report(child, recv_fd);
-        exit(-rc);
-    }
-
-    save_domain_core_writeconfig(send_fd, "migration stream",
-                                 config_data, config_len);
-
-    memset(&suspinfo, 0, sizeof(suspinfo));
-    suspinfo.flags |= XL_SUSPEND_LIVE;
-    rc = libxl_domain_suspend(&ctx, &suspinfo, domid, send_fd);
-    if (rc) {
-        fprintf(stderr, "migration sender: libxl_domain_suspend failed"
-                " (rc=%d)\n", rc);
-        goto failed_resume;
-    }
-
-    fprintf(stderr, "migration sender: Transfer complete.\n");
-
-    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
-                                   sizeof(migrate_receiver_ready),
-                                   "ready message", rune);
-    if (rc) goto failed_resume;
-
-    /* right, at this point we are about give the destination
-     * permission to rename and resume, so we must first rename the
-     * domain away ourselves */
-
-    fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
-
-    if (common_domname) {
-        asprintf(&away_domname, "%s--migratedaway", common_domname);
-        rc = libxl_domain_rename(&ctx, domid,
-                                 common_domname, away_domname, 0);
-        if (rc) goto failed_resume;
-    }
-
-    /* point of no return - as soon as we have tried to say
-     * "go" to the receiver, it's not safe to carry on.  We leave
-     * the domain renamed to %s--migratedaway in case that's helpful.
-     */
-
-    fprintf(stderr, "migration sender: Giving target permission to start.\n");
-
-    rc = libxl_write_exactly(&ctx, send_fd,
-                             migrate_permission_to_go,
-                             sizeof(migrate_permission_to_go),
-                             "migration stream", "GO message");
-    if (rc) goto failed_badly;
-
-    rc = migrate_read_fixedmessage(recv_fd, migrate_report,
-                                   sizeof(migrate_report),
-                                   "success/failure report message", rune);
-    if (rc) goto failed_badly;
-
-    rc = libxl_read_exactly(&ctx, recv_fd,
-                            &rc_buf, 1,
-                            "migration ack stream", "success/failure status");
-    if (rc) goto failed_badly;
-
-    if (rc_buf) {
-        fprintf(stderr, "migration sender: Target reports startup failure"
-                " (status code %d).\n", rc_buf);
-
-        rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
-                                       sizeof(migrate_permission_to_go),
-                                       "permission for sender to resume",
-                                       rune);
-        if (rc) goto failed_badly;
-
-        fprintf(stderr, "migration sender: Trying to resume at our end.\n");
-
-        if (common_domname) {
-            libxl_domain_rename(&ctx, domid,
-                                away_domname, common_domname, 0);
-        }
-        rc = libxl_domain_resume(&ctx, domid);
-        if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
-
-        fprintf(stderr, "Migration failed due to problems at target.\n");
-        exit(-ERROR_FAIL);
-    }
-
-    fprintf(stderr, "migration sender: Target reports successful startup.\n");
-    libxl_domain_destroy(&ctx, domid, 1); /* bang! */
-    fprintf(stderr, "Migration successful.\n");
-    exit(0);
-
- failed_resume:
-    close(send_fd);
-    migration_child_report(child, recv_fd);
-    fprintf(stderr, "Migration failed, resuming at sender.\n");
-    libxl_domain_resume(&ctx, domid);
-    exit(-ERROR_FAIL);
-
- failed_badly:
-    fprintf(stderr,
- "** Migration failed during final handshake **\n"
- "Domain state is now undefined !\n"
- "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
- " resuming at most one instance.  Two simultaneous instances of the domain\n"
- " would probably result in SEVERE DATA LOSS and it is now your\n"
- " responsibility to avoid that.  Sorry.\n");
-
-    close(send_fd);
-    migration_child_report(child, recv_fd);
-    exit(-ERROR_BADFAIL);
-}
-
-static void migrate_receive(int debug, int daemonize)
-{
-    int rc, rc2;
-    char rc_buf;
-    char *migration_domname;
-
-    signal(SIGPIPE, SIG_IGN);
-    /* if we get SIGPIPE we'd rather just have it as an error */
-
-    fprintf(stderr, "migration target: Ready to receive domain.\n");
-
-    CHK_ERRNO( libxl_write_exactly(&ctx, 1,
-                                   migrate_receiver_banner,
-                                   sizeof(migrate_receiver_banner)-1,
-                                   "migration ack stream",
-                                   "banner") );
-
-    rc = create_domain(debug, daemonize,
-                       0 /* no config file, use incoming */,
-                       "incoming migration stream", 1,
-                       0, &migration_domname);
-    if (rc) {
-        fprintf(stderr, "migration target: Domain creation failed"
-                " (code %d).\n", rc);
-        exit(-rc);
-    }
-
-    fprintf(stderr, "migration target: Transfer complete,"
-            " requesting permission to start domain.\n");
-
-    rc = libxl_write_exactly(&ctx, 1,
-                             migrate_receiver_ready,
-                             sizeof(migrate_receiver_ready),
-                             "migration ack stream", "ready message");
-    if (rc) exit(-rc);
-
-    rc = migrate_read_fixedmessage(0, migrate_permission_to_go,
-                                   sizeof(migrate_permission_to_go),
-                                   "GO message", 0);
-    if (rc) goto perhaps_destroy_notify_rc;
-
-    fprintf(stderr, "migration target: Got permission, starting domain.\n");
-
-    if (migration_domname) {
-        rc = libxl_domain_rename(&ctx, domid,
-                                 migration_domname, common_domname, 0);
-        if (rc) goto perhaps_destroy_notify_rc;
-    }
-
-    rc = libxl_domain_unpause(&ctx, domid);
-    if (rc) goto perhaps_destroy_notify_rc;
-
-    fprintf(stderr, "migration target: Domain started successsfully.\n");
-    rc = 0;
-
- perhaps_destroy_notify_rc:
-    rc2 = libxl_write_exactly(&ctx, 1,
-                              migrate_report, sizeof(migrate_report),
-                              "migration ack stream",
-                              "success/failure report");
-    if (rc2) exit(-ERROR_BADFAIL);
-
-    rc_buf = -rc;
-    assert(!!rc_buf == !!rc);
-    rc2 = libxl_write_exactly(&ctx, 1, &rc_buf, 1,
-                              "migration ack stream",
-                              "success/failure code");
-    if (rc2) exit(-ERROR_BADFAIL);
-
-    if (rc) {
-        fprintf(stderr, "migration target: Failure, destroying our copy.\n");
-
-        rc2 = libxl_domain_destroy(&ctx, domid, 1);
-        if (rc2) {
-            fprintf(stderr, "migration target: Failed to destroy our copy"
-                    " (code %d).\n", rc2);
-            exit(-ERROR_BADFAIL);
-        }
-
-        fprintf(stderr, "migration target: Cleanup OK, granting sender"
-                " permission to resume.\n");
-
-        rc2 = libxl_write_exactly(&ctx, 1,
-                                  migrate_permission_to_go,
-                                  sizeof(migrate_permission_to_go),
-                                  "migration ack stream",
-                                  "permission to sender to have domain back");
-        if (rc2) exit(-ERROR_BADFAIL);
-    }
-
-    exit(0);
-}
-
-int main_restore(int argc, char **argv)
-{
-    char *checkpoint_file = NULL;
-    char *config_file = NULL;
-    int paused = 0, debug = 0, daemonize = 1;
-    int opt, rc;
-
-    while ((opt = getopt(argc, argv, "hpde")) != -1) {
-        switch (opt) {
-        case 'p':
-            paused = 1;
-            break;
-        case 'd':
-            debug = 1;
-            break;
-        case 'e':
-            daemonize = 0;
-            break;
-        case 'h':
-            help("restore");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    if (argc-optind == 1) {
-        checkpoint_file = argv[optind];
-    } else if (argc-optind == 2) {
-        config_file = argv[optind];
-        checkpoint_file = argv[optind + 1];
-    } else {
-        help("restore");
-        exit(2);
-    }
-    rc = create_domain(debug, daemonize, config_file,
-                       checkpoint_file, paused, -1, 0);
-    exit(-rc);
-}
-
-int main_migrate_receive(int argc, char **argv)
-{
-    int debug = 0, daemonize = 1;
-    int opt;
-
-    while ((opt = getopt(argc, argv, "hed")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("restore");
-            exit(2);
-            break;
-        case 'e':
-            daemonize = 0;
-            break;
-        case 'd':
-            debug = 1;
-            break;
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    if (argc-optind != 0) {
-        help("restore");
-        exit(2);
-    }
-    migrate_receive(debug, daemonize);
-    exit(0);
-}
-
-int main_save(int argc, char **argv)
-{
-    char *filename = NULL, *p = NULL;
-    const char *config_filename;
-    int checkpoint = 0;
-    int opt;
-
-    while ((opt = getopt(argc, argv, "hc")) != -1) {
-        switch (opt) {
-        case 'c':
-            checkpoint = 1;
-            break;
-        case 'h':
-            help("save");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    if (argc-optind < 1 || argc-optind > 3) {
-        help("save");
-        exit(2);
-    }
-
-    p = argv[optind];
-    filename = argv[optind + 1];
-    config_filename = argv[optind + 2];
-    save_domain(p, filename, checkpoint, config_filename);
-    exit(0);
-}
-
-int main_migrate(int argc, char **argv)
-{
-    char *p = NULL;
-    const char *config_filename = NULL;
-    const char *ssh_command = "ssh";
-    char *rune = NULL;
-    char *host;
-    int opt, daemonize = 1, debug = 0;
-
-    while ((opt = getopt(argc, argv, "hC:s:ed")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("migrate");
-            exit(0);
-        case 'C':
-            config_filename = optarg;
-            break;
-        case 's':
-            ssh_command = optarg;
-            break;
-        case 'e':
-            daemonize = 0;
-            break;
-        case 'd':
-            debug = 1;
-            break;
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    if (argc-optind < 2 || argc-optind > 2) {
-        help("save");
-        exit(2);
-    }
-
-    p = argv[optind];
-    host = argv[optind + 1];
-
-    if (!ssh_command[0]) {
-        rune= host;
-    } else {
-        asprintf(&rune, "exec %s %s xl migrate-receive%s%s",
-                 ssh_command, host,
-                 daemonize ? "" : " -e",
-                 debug ? " -d" : "");
-    }
-
-    migrate_domain(p, rune, config_filename);
-    exit(0);
-}
-
-int main_pause(int argc, char **argv)
-{
-    int opt;
-    char *p;
-    
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("pause");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("pause");
-        exit(2);
-    }
-
-    p = argv[optind];
-
-    pause_domain(p);
-    exit(0);
-}
-
-int main_unpause(int argc, char **argv)
-{
-    int opt;
-    char *p;
-    
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("unpause");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("unpause");
-        exit(2);
-    }
-
-    p = argv[optind];
-
-    unpause_domain(p);
-    exit(0);
-}
-
-int main_destroy(int argc, char **argv)
-{
-    int opt;
-    char *p;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("destroy");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("destroy");
-        exit(2);
-    }
-
-    p = argv[optind];
-
-    destroy_domain(p);
-    exit(0);
-}
-
-int main_list(int argc, char **argv)
-{
-    int opt, verbose = 0;
-
-    while ((opt = getopt(argc, argv, "hv")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("list");
-            exit(0);
-        case 'v':
-            verbose = 1;
-            break;
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    list_domains(verbose);
-    exit(0);
-}
-
-int main_list_vm(int argc, char **argv)
-{
-    int opt;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("list-vm");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    list_vm();
-    exit(0);
-}
-
-int main_create(int argc, char **argv)
-{
-    char *filename = NULL;
-    int paused = 0, debug = 0, daemonize = 1;
-    int opt, rc;
-
-    while ((opt = getopt(argc, argv, "hdep")) != -1) {
-        switch (opt) {
-        case 'p':
-            paused = 1;
-            break;
-        case 'd':
-            debug = 1;
-            break;
-        case 'e':
-            daemonize = 0;
-            break;
-        case 'h':
-            help("create");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    if (optind >= argc) {
-        help("create");
-        exit(2);
-    }
-
-    filename = argv[optind];
-    rc = create_domain(debug, daemonize, filename, NULL, paused,
-                       -1, 0);
-    exit(-rc);
-}
-
-void button_press(char *p, char *b)
-{
-    libxl_button button;
-
-    find_domain(p);
-
-    if (!strcmp(b, "power")) {
-        button = POWER_BUTTON;
-    } else if (!strcmp(b, "sleep")) {
-        button = SLEEP_BUTTON;
-    } else {
-        fprintf(stderr, "%s is an invalid button identifier\n", b);
-        exit(2);
-    }
-
-    libxl_button_press(&ctx, domid, button);
-}
-
-int main_button_press(int argc, char **argv)
-{
-    int opt;
-    char *p;
-    char *b;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("button-press");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("button-press");
-        exit(2);
-    }
-
-    p = argv[optind];
-    b = argv[optind + 1];
-
-    button_press(p, b);
-    exit(0);
-}
-
-static void print_vcpuinfo(uint32_t tdomid,
-                           const struct libxl_vcpuinfo *vcpuinfo,
-                           uint32_t nr_cpus)
-{
-    int i, l;
-    uint64_t *cpumap;
-    uint64_t pcpumap;
-
-    /*      NAME  ID  VCPU */
-    printf("%-32s %5u %5u",
-           libxl_domid_to_name(&ctx, tdomid), tdomid, vcpuinfo->vcpuid);
-    if (!vcpuinfo->online) {
-        /*      CPU STA */
-        printf("%5c %3c%cp ", '-', '-', '-');
-    } else {
-        /*      CPU STA */
-        printf("%5u %3c%c- ", vcpuinfo->cpu,
-               vcpuinfo->running ? 'r' : '-',
-               vcpuinfo->blocked ? 'b' : '-');
-    }
-    /*      TIM */
-    printf("%9.1f  ", ((float)vcpuinfo->vcpu_time / 1e9));
-    /* CPU AFFINITY */
-    pcpumap = nr_cpus > 64 ? -1 : ((1 << nr_cpus) - 1);
-    for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
-        if (*cpumap < pcpumap) {
-            break;
-        }
-        if (nr_cpus > 64) {
-            pcpumap = -1;
-            nr_cpus -= 64;
-        } else {
-            pcpumap = ((1 << nr_cpus) - 1);
-            nr_cpus = 0;
-        }
-    }
-    if (!nr_cpus) {
-        printf("any cpu\n");
-    } else {
-        for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
-            pcpumap = *cpumap;
-            for (i = 0; !(pcpumap & 1); ++i, pcpumap >>= 1)
-                ;
-            printf("%u", i);
-            for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap 
>>= 1)
-                ;
-            if (l < i) {
-                printf("-%u", i);
-            }
-            for (++i; pcpumap; ++i, pcpumap >>= 1) {
-                if (pcpumap & 1) {
-                    printf(",%u", i);
-                    for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, 
pcpumap >>= 1)
-                        ;
-                    if (l < i) {
-                        printf("-%u", i);
-                    }
-                    ++i;
-                }
-            }
-            printf("\n");
-            nr_cpus = nr_cpus > 64 ? nr_cpus - 64 : 0;
-        }
-    }
-}
-
-void vcpulist(int argc, char **argv)
-{
-    struct libxl_dominfo *dominfo;
-    struct libxl_vcpuinfo *vcpuinfo;
-    struct libxl_physinfo physinfo;
-    int nb_vcpu, nb_domain, cpusize;
-
-    if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
-        fprintf(stderr, "libxl_physinfo failed.\n");
-        goto vcpulist_out;
-    }
-    printf("%-32s %5s %5s %5s %5s %9s %s\n",
-           "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
-    if (!argc) {
-        if (!(dominfo = libxl_list_domain(&ctx, &nb_domain))) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            goto vcpulist_out;
-        }
-        for (; nb_domain > 0; --nb_domain, ++dominfo) {
-            if (!(vcpuinfo = libxl_list_vcpu(&ctx, dominfo->domid, &nb_vcpu, 
&cpusize))) {
-                fprintf(stderr, "libxl_list_vcpu failed.\n");
-                goto vcpulist_out;
-            }
-            for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
-                print_vcpuinfo(dominfo->domid, vcpuinfo, physinfo.nr_cpus);
-            }
-        }
-    } else {
-        for (; argc > 0; ++argv, --argc) {
-            if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
-                fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
-            }
-            if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, 
&cpusize))) {
-                fprintf(stderr, "libxl_list_vcpu failed.\n");
-                goto vcpulist_out;
-            }
-            for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
-                print_vcpuinfo(domid, vcpuinfo, physinfo.nr_cpus);
-            }
-        }
-    }
-  vcpulist_out:
-    ;
-}
-
-void main_vcpulist(int argc, char **argv)
-{
-    int opt;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("vcpu-list");
-            exit(0);
-        default:
-            fprintf(stderr, "option `%c' not supported.\n", opt);
-            break;
-        }
-    }
-
-    vcpulist(argc - 1, argv + 1);
-    exit(0);
-}
-
-void vcpupin(char *d, const char *vcpu, char *cpu)
-{
-    struct libxl_vcpuinfo *vcpuinfo;
-    struct libxl_physinfo physinfo;
-    uint64_t *cpumap = NULL;
-
-    uint32_t vcpuid, cpuida, cpuidb;
-    char *endptr, *toka, *tokb;
-    int i, nb_vcpu, cpusize;
-
-    vcpuid = strtoul(vcpu, &endptr, 10);
-    if (vcpu == endptr) {
-        if (strcmp(vcpu, "all")) {
-            fprintf(stderr, "Error: Invalid argument.\n");
-            return;
-        }
-        vcpuid = -1;
-    }
-
-    find_domain(d);
-
-    if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
-        fprintf(stderr, "libxl_get_physinfo failed.\n");
-        goto vcpupin_out1;
-    }
-
-    cpumap = calloc(physinfo.max_cpu_id + 1, sizeof (uint64_t));
-    if (!cpumap) {
-        goto vcpupin_out1;
-    }
-    if (strcmp(cpu, "all")) {
-        for (toka = strtok(cpu, ","), i = 0; toka; toka = strtok(NULL, ","), 
++i) {
-            cpuida = strtoul(toka, &endptr, 10);
-            if (toka == endptr) {
-                fprintf(stderr, "Error: Invalid argument.\n");
-                goto vcpupin_out;
-            }
-            if (*endptr == '-') {
-                tokb = endptr + 1;
-                cpuidb = strtoul(tokb, &endptr, 10);
-                if ((tokb == endptr) || (cpuida > cpuidb)) {
-                    fprintf(stderr, "Error: Invalid argument.\n");
-                    goto vcpupin_out;
-                }
-                while (cpuida <= cpuidb) {
-                    cpumap[cpuida / 64] |= (1 << (cpuida % 64));
-                    ++cpuida;
-                }
-            } else {
-                cpumap[cpuida / 64] |= (1 << (cpuida % 64));
-            }
-        }
-    }
-    else {
-        memset(cpumap, -1, sizeof (uint64_t) * (physinfo.max_cpu_id + 1));
-    }
-
-    if (vcpuid != -1) {
-        if (libxl_set_vcpuaffinity(&ctx, domid, vcpuid,
-                                   cpumap, physinfo.max_cpu_id + 1) == -1) {
-            fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid);
-        }
-    }
-    else {
-        if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &cpusize))) {
-            fprintf(stderr, "libxl_list_vcpu failed.\n");
-            goto vcpupin_out;
-        }
-        for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
-            if (libxl_set_vcpuaffinity(&ctx, domid, vcpuinfo->vcpuid,
-                                       cpumap, physinfo.max_cpu_id + 1) == -1) 
{
-                fprintf(stderr, "libxl_list_vcpu failed on vcpu `%u'.\n", 
vcpuinfo->vcpuid);
-            }
-        }
-    }
-  vcpupin_out1:
-    free(cpumap);
-  vcpupin_out:
-    ;
-}
-
-int main_vcpupin(int argc, char **argv)
-{
-    int opt;
-
-    if (argc != 4) {
-        help("vcpu-pin");
-        exit(0);
-    }
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("vcpu-pin");
-            exit(0);
-        default:
-            fprintf(stderr, "option `%c' not supported.\n", opt);
-            break;
-        }
-    }
-
-    vcpupin(argv[1], argv[2] , argv[3]);
-    exit(0);
-}
-
-void vcpuset(char *d, char* nr_vcpus)
-{
-    char *endptr;
-    unsigned int max_vcpus;
-
-    max_vcpus = strtoul(nr_vcpus, &endptr, 10);
-    if (nr_vcpus == endptr) {
-        fprintf(stderr, "Error: Invalid argument.\n");
-        return;
-    }
-
-    find_domain(d);
-
-    if (libxl_set_vcpucount(&ctx, domid, max_vcpus) == ERROR_INVAL) {
-        fprintf(stderr, "Error: Cannot set vcpus greater than max vcpus on 
running domain or lesser than 1.\n");
-    }
-}
-
-int main_vcpuset(int argc, char **argv)
-{
-    int opt;
-
-    if (argc != 3) {
-        help("vcpu-set");
-        exit(0);
-    }
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-        help("vcpu-set");
-            exit(0);
-        default:
-            fprintf(stderr, "option `%c' not supported.\n", opt);
-            break;
-        }
-    }
-
-    vcpuset(argv[1], argv[2]);
-    exit(0);
-}
-
-static void output_xeninfo(void)
-{
-    const libxl_version_info *info;
-    int sched_id;
-
-    info = libxl_get_version_info(&ctx);
-    if ((sched_id = libxl_get_sched_id(&ctx)) < 0) {
-        fprintf(stderr, "get_sched_id sysctl failed.\n");
-        return;
-    }
-
-    printf("xen_major              : %d\n", info->xen_version_major);
-    printf("xen_minor              : %d\n", info->xen_version_minor);
-    printf("xen_extra              : %s\n", info->xen_version_extra);
-    printf("xen_caps               : %s\n", info->capabilities);
-    printf("xen_scheduler          : %s\n",
-        sched_id == XEN_SCHEDULER_SEDF ? "sedf" :
-        sched_id == XEN_SCHEDULER_CREDIT ? "credit" :
-        sched_id == XEN_SCHEDULER_CREDIT2 ? "credit2" : "unknown");
-    printf("xen_pagesize           : %lu\n", info->pagesize);
-    printf("platform_params        : virt_start=0x%lx\n", info->virt_start);
-    printf("xen_changeset          : %s\n", info->changeset);
-    printf("xen_commandline        : %s\n", info->commandline);
-    printf("cc_compiler            : %s\n", info->compiler);
-    printf("cc_compile_by          : %s\n", info->compile_by);
-    printf("cc_compile_domain      : %s\n", info->compile_domain);
-    printf("cc_compile_date        : %s\n", info->compile_date);
-
-    return;
-}
-
-static void output_nodeinfo(void)
-{
-    struct utsname utsbuf;
-
-    uname(&utsbuf);
-
-    printf("host                   : %s\n", utsbuf.nodename);
-    printf("release                : %s\n", utsbuf.release);
-    printf("version                : %s\n", utsbuf.version);
-    printf("machine                : %s\n", utsbuf.machine);
-
-    return;
-}
-
-static void output_physinfo(void)
-{
-    struct libxl_physinfo info;
-    const libxl_version_info *vinfo;
-    unsigned int i;
-
-    if (libxl_get_physinfo(&ctx, &info) != 0) {
-        fprintf(stderr, "libxl_physinfo failed.\n");
-        return;
-    }
-
-    printf("nr_cpus                : %d\n", info.nr_cpus);
-    printf("nr_nodes               : %d\n", info.nr_nodes);
-    printf("cores_per_socket       : %d\n", info.cores_per_socket);
-    printf("threads_per_core       : %d\n", info.threads_per_core);
-    printf("cpu_mhz                : %d\n", info.cpu_khz / 1000);
-    printf("hw_caps                : ");
-    for (i = 0; i < 8; i++)
-        printf("%08x%c", info.hw_cap[i], i < 7 ? ':' : '\n');
-    printf("virt_caps              :");
-    if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm)
-        printf(" hvm");
-    if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm_directio)
-        printf(" hvm_directio");
-    printf("\n");
-    vinfo = libxl_get_version_info(&ctx);
-    i = (1 << 20) / vinfo->pagesize;
-    printf("total_memory           : %lu\n", info.total_pages / i);
-    printf("free_memory            : %lu\n", info.free_pages / i);
-
-    return;
-}
-
-void info(int verbose)
-{
-    output_nodeinfo();
-
-    output_physinfo();
-
-    output_xeninfo();
-
-    printf("xend_config_format     : 4\n");
-
-    return;
-}
-
-void main_info(int argc, char **argv)
-{
-    int opt, verbose;
-
-    verbose = 0;
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("vcpu-list");
-            exit(0);
-        default:
-            fprintf(stderr, "option `%c' not supported.\n", opt);
-            break;
-        }
-    }
-
-    info(verbose);
-    exit(0);
-}
-
 int main(int argc, char **argv)
 {
     if (argc < 2) {
diff -r 9a1d7caa2024 -r d23a0a1823ef tools/libxl/xl_cmdimpl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/xl_cmdimpl.c  Thu Apr 29 22:07:08 2010 +0800
@@ -0,0 +1,2750 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h> /* for time */
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <sys/utsname.h> /* for utsname in xl info */
+#include <xenctrl.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include "libxl.h"
+#include "libxl_utils.h"
+#include "libxlutil.h"
+
+#define UUID_FMT 
"%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+
+int logfile = 2;
+
+/* every libxl action in xl uses this same libxl context */
+struct libxl_ctx ctx;
+
+/* when we operate on a domain, it is this one: */
+static uint32_t domid;
+static const char *common_domname;
+
+
+static const char savefileheader_magic[32]=
+    "Xen saved domain, xl format\n \0 \r";
+
+static const char migrate_receiver_banner[]=
+    "xl migration receiver ready, send binary domain data.\n";
+static const char migrate_receiver_ready[]=
+    "domain received, ready to unpause";
+static const char migrate_permission_to_go[]=
+    "domain is yours, you are cleared to unpause";
+static const char migrate_report[]=
+    "my copy unpause results are as follows";
+  /* followed by one byte:
+   *     0: everything went well, domain is running
+   *            next thing is we all exit
+   * non-0: things went badly
+   *            next thing should be a migrate_permission_to_go
+   *            from target to source
+   */
+
+struct save_file_header {
+    char magic[32]; /* savefileheader_magic */
+    /* All uint32_ts are in domain's byte order. */
+    uint32_t byteorder; /* SAVEFILE_BYTEORDER_VALUE */
+    uint32_t mandatory_flags; /* unknown flags => reject restore */
+    uint32_t optional_flags; /* unknown flags => reject restore */
+    uint32_t optional_data_len; /* skip, or skip tail, if not understood */
+};
+
+/* Optional data, in order:
+ *   4 bytes uint32_t  config file size
+ *   n bytes           config file in Unix text file format
+ */
+
+#define SAVEFILE_BYTEORDER_VALUE ((uint32_t)0x01020304UL)
+
+static int domain_qualifier_to_domid(const char *p, uint32_t *domid_r,
+                                     int *was_name_r)
+{
+    int i, alldigit;
+
+    alldigit = 1;
+    for (i = 0; p[i]; i++) {
+        if (!isdigit((uint8_t)p[i])) {
+            alldigit = 0;
+            break;
+        }
+    }
+
+    if (i > 0 && alldigit) {
+        *domid_r = strtoul(p, NULL, 10);
+        if (was_name_r) *was_name_r = 0;
+        return 0;
+    } else {
+        /* check here if it's a uuid and do proper conversion */
+    }
+    if (was_name_r) *was_name_r = 1;
+    return libxl_name_to_domid(&ctx, p, domid_r);
+}
+
+static void find_domain(const char *p)
+{
+    int rc, was_name;
+
+    rc = domain_qualifier_to_domid(p, &domid, &was_name);
+    if (rc) {
+        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
+        exit(2);
+    }
+    common_domname = was_name ? p : 0;
+}
+
+#define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
+
+void dolog(const char *file, int line, const char *func, char *fmt, ...)
+{
+    va_list ap;
+    char *s;
+    int rc;
+
+    va_start(ap, fmt);
+    rc = vasprintf(&s, fmt, ap);
+    va_end(ap);
+    if (rc >= 0)
+        write(logfile, s, rc);
+}
+
+static void init_create_info(libxl_domain_create_info *c_info)
+{
+    memset(c_info, '\0', sizeof(*c_info));
+    c_info->xsdata = NULL;
+    c_info->platformdata = NULL;
+    c_info->hvm = 1;
+    c_info->oos = 1;
+    c_info->ssidref = 0;
+}
+
+static void init_build_info(libxl_domain_build_info *b_info, 
libxl_domain_create_info *c_info)
+{
+    memset(b_info, '\0', sizeof(*b_info));
+    b_info->timer_mode = -1;
+    b_info->hpet = 1;
+    b_info->vpt_align = -1;
+    b_info->max_vcpus = 1;
+    b_info->max_memkb = 32 * 1024;
+    b_info->target_memkb = b_info->max_memkb;
+    if (c_info->hvm) {
+        b_info->shadow_memkb = 
libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus);
+        b_info->video_memkb = 8 * 1024;
+        b_info->kernel = "/usr/lib/xen/boot/hvmloader";
+        b_info->hvm = 1;
+        b_info->u.hvm.pae = 1;
+        b_info->u.hvm.apic = 1;
+        b_info->u.hvm.acpi = 1;
+        b_info->u.hvm.nx = 1;
+        b_info->u.hvm.viridian = 0;
+    } else {
+        b_info->u.pv.slack_memkb = 8 * 1024;
+    }
+}
+
+static void init_dm_info(libxl_device_model_info *dm_info,
+        libxl_domain_create_info *c_info, libxl_domain_build_info *b_info)
+{
+    int i;
+    memset(dm_info, '\0', sizeof(*dm_info));
+
+    for (i = 0; i < 16; i++) {
+        dm_info->uuid[i] = rand();
+    }
+
+    dm_info->dom_name = c_info->name;
+    dm_info->device_model = "/usr/lib/xen/bin/qemu-dm";
+    dm_info->videoram = b_info->video_memkb / 1024;
+    dm_info->apic = b_info->u.hvm.apic;
+
+    dm_info->stdvga = 0;
+    dm_info->vnc = 1;
+    dm_info->vnclisten = "127.0.0.1";
+    dm_info->vncdisplay = 0;
+    dm_info->vncunused = 0;
+    dm_info->keymap = NULL;
+    dm_info->sdl = 0;
+    dm_info->opengl = 0;
+    dm_info->nographic = 0;
+    dm_info->serial = NULL;
+    dm_info->boot = "cda";
+    dm_info->usb = 0;
+    dm_info->usbdevice = NULL;
+}
+
+static void init_nic_info(libxl_device_nic *nic_info, int devnum)
+{
+    memset(nic_info, '\0', sizeof(*nic_info));
+
+    nic_info->backend_domid = 0;
+    nic_info->domid = 0;
+    nic_info->devid = devnum;
+    nic_info->mtu = 1492;
+    nic_info->model = "e1000";
+    nic_info->mac[0] = 0x00;
+    nic_info->mac[1] = 0x16;
+    nic_info->mac[2] = 0x3e;
+    nic_info->mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
+    nic_info->mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    nic_info->mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    nic_info->ifname = NULL;
+    nic_info->bridge = "xenbr0";
+    nic_info->script = "/etc/xen/scripts/vif-bridge";
+    nic_info->nictype = NICTYPE_IOEMU;
+}
+
+static void init_vfb_info(libxl_device_vfb *vfb, int dev_num)
+{
+    memset(vfb, 0x00, sizeof(libxl_device_vfb));
+    vfb->devid = dev_num;
+    vfb->vnc = 1;
+    vfb->vnclisten = "127.0.0.1";
+    vfb->vncdisplay = 0;
+    vfb->vncunused = 1;
+    vfb->keymap = NULL;
+    vfb->sdl = 0;
+    vfb->opengl = 0;
+}
+
+static void init_vkb_info(libxl_device_vkb *vkb, int dev_num)
+{
+    memset(vkb, 0x00, sizeof(libxl_device_vkb));
+    vkb->devid = dev_num;
+}
+
+static void init_console_info(libxl_device_console *console, int dev_num, 
libxl_domain_build_state *state)
+{
+    memset(console, 0x00, sizeof(libxl_device_console));
+    console->devid = dev_num;
+    console->constype = CONSTYPE_XENCONSOLED;
+    if (state)
+        console->build_state = state;
+}
+
+static void printf_info(libxl_domain_create_info *c_info,
+                        libxl_domain_build_info *b_info,
+                        libxl_device_disk *disks,
+                        int num_disks,
+                        libxl_device_nic *vifs,
+                        int num_vifs,
+                        libxl_device_pci *pcidevs,
+                        int num_pcidevs,
+                        libxl_device_vfb *vfbs,
+                        int num_vfbs,
+                        libxl_device_vkb *vkb,
+                        int num_vkbs,
+                        libxl_device_model_info *dm_info)
+{
+    int i;
+    printf("*** domain_create_info ***\n");
+    printf("hvm: %d\n", c_info->hvm);
+    printf("hap: %d\n", c_info->hap);
+    printf("oos: %d\n", c_info->oos);
+    printf("ssidref: %d\n", c_info->ssidref);
+    printf("name: %s\n", c_info->name);
+    printf("uuid: " UUID_FMT "\n",
+           (c_info->uuid)[0], (c_info->uuid)[1], (c_info->uuid)[2], 
(c_info->uuid)[3],
+           (c_info->uuid)[4], (c_info->uuid)[5], (c_info->uuid)[6], 
(c_info->uuid)[7],
+           (c_info->uuid)[8], (c_info->uuid)[9], (c_info->uuid)[10], 
(c_info->uuid)[11],
+           (c_info->uuid)[12], (c_info->uuid)[13], (c_info->uuid)[14], 
(c_info->uuid)[15]);
+    if (c_info->xsdata)
+        printf("xsdata: contains data\n");
+    else
+        printf("xsdata: (null)\n");
+    if (c_info->platformdata)
+        printf("platformdata: contains data\n");
+    else
+        printf("platformdata: (null)\n");
+
+
+    printf("\n\n\n*** domain_build_info ***\n");
+    printf("timer_mode: %d\n", b_info->timer_mode);
+    printf("hpet: %d\n", b_info->hpet);
+    printf("vpt_align: %d\n", b_info->vpt_align);
+    printf("max_vcpus: %d\n", b_info->max_vcpus);
+    printf("tsc_mode: %d\n", b_info->tsc_mode);
+    printf("max_memkb: %d\n", b_info->max_memkb);
+    printf("target_memkb: %d\n", b_info->target_memkb);
+    printf("kernel: %s\n", b_info->kernel);
+    printf("hvm: %d\n", b_info->hvm);
+
+    if (c_info->hvm) {
+        printf("video_memkb: %d\n", b_info->video_memkb);
+        printf("shadow_memkb: %d\n", b_info->shadow_memkb);
+        printf("    pae: %d\n", b_info->u.hvm.pae);
+        printf("    apic: %d\n", b_info->u.hvm.apic);
+        printf("    acpi: %d\n", b_info->u.hvm.acpi);
+        printf("    nx: %d\n", b_info->u.hvm.nx);
+        printf("    viridian: %d\n", b_info->u.hvm.viridian);
+    } else {
+        printf("cmdline: %s\n", b_info->u.pv.cmdline);
+        printf("ramdisk: %s\n", b_info->u.pv.ramdisk);
+    }
+
+    for (i = 0; i < num_disks; i++) {
+        printf("\n\n\n*** disks_info: %d ***\n", i);
+        printf("backend_domid %d\n", disks[i].backend_domid);
+        printf("domid %d\n", disks[i].domid);
+        printf("physpath %s\n", disks[i].physpath);
+        printf("phystype %d\n", disks[i].phystype);
+        printf("virtpath %s\n", disks[i].virtpath);
+        printf("unpluggable %d\n", disks[i].unpluggable);
+        printf("readwrite %d\n", disks[i].readwrite);
+        printf("is_cdrom %d\n", disks[i].is_cdrom);
+    }
+
+    for (i = 0; i < num_vifs; i++) {
+        printf("\n\n\n*** vifs_info: %d ***\n", i);
+        printf("backend_domid %d\n", vifs[i].backend_domid);
+        printf("domid %d\n", vifs[i].domid);
+        printf("devid %d\n", vifs[i].devid);
+        printf("mtu %d\n", vifs[i].mtu);
+        printf("model %s\n", vifs[i].model);
+        printf("mac %02x:%02x:%02x:%02x:%02x:%02x\n", vifs[i].mac[0], 
vifs[i].mac[1], vifs[i].mac[2], vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
+    }
+
+    for (i = 0; i < num_pcidevs; i++) {
+        printf("\n\n\n*** pcidevs_info: %d ***\n", i);
+        printf("pci dev "PCI_BDF_VDEVFN"\n", pcidevs[i].domain, 
pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func, pcidevs[i].vdevfn);
+        printf("opts msitranslate %d power_mgmt %d\n", 
pcidevs[i].msitranslate, pcidevs[i].power_mgmt);
+    }
+
+    for (i = 0; i < num_vfbs; i++) {
+        printf("\n\n\n*** vfbs_info: %d ***\n", i);
+        printf("backend_domid %d\n", vfbs[i].backend_domid);
+        printf("domid %d\n", vfbs[i].domid);
+        printf("devid %d\n", vfbs[i].devid);
+        printf("vnc: %d\n", vfbs[i].vnc);
+        printf("vnclisten: %s\n", vfbs[i].vnclisten);
+        printf("vncdisplay: %d\n", vfbs[i].vncdisplay);
+        printf("vncunused: %d\n", vfbs[i].vncunused);
+        printf("keymap: %s\n", vfbs[i].keymap);
+        printf("sdl: %d\n", vfbs[i].sdl);
+        printf("opengl: %d\n", vfbs[i].opengl);
+        printf("display: %s\n", vfbs[i].display);
+        printf("xauthority: %s\n", vfbs[i].xauthority);
+    }
+
+    if (c_info->hvm) {
+        printf("\n\n\n*** device_model_info ***\n");
+        printf("domid: %d\n", dm_info->domid);
+        printf("dom_name: %s\n", dm_info->dom_name);
+        printf("device_model: %s\n", dm_info->device_model);
+        printf("videoram: %d\n", dm_info->videoram);
+        printf("stdvga: %d\n", dm_info->stdvga);
+        printf("vnc: %d\n", dm_info->vnc);
+        printf("vnclisten: %s\n", dm_info->vnclisten);
+        printf("vncdisplay: %d\n", dm_info->vncdisplay);
+        printf("vncunused: %d\n", dm_info->vncunused);
+        printf("keymap: %s\n", dm_info->keymap);
+        printf("sdl: %d\n", dm_info->sdl);
+        printf("opengl: %d\n", dm_info->opengl);
+        printf("nographic: %d\n", dm_info->nographic);
+        printf("serial: %s\n", dm_info->serial);
+        printf("boot: %s\n", dm_info->boot);
+        printf("usb: %d\n", dm_info->usb);
+        printf("usbdevice: %s\n", dm_info->usbdevice);
+        printf("apic: %d\n", dm_info->apic);
+    }
+}
+
+static void parse_config_data(const char *configfile_filename_report,
+                              const char *configfile_data,
+                              int configfile_len,
+                              libxl_domain_create_info *c_info,
+                              libxl_domain_build_info *b_info,
+                              libxl_device_disk **disks,
+                              int *num_disks,
+                              libxl_device_nic **vifs,
+                              int *num_vifs,
+                              libxl_device_pci **pcidevs,
+                              int *num_pcidevs,
+                              libxl_device_vfb **vfbs,
+                              int *num_vfbs,
+                              libxl_device_vkb **vkbs,
+                              int *num_vkbs,
+                              libxl_device_model_info *dm_info)
+{
+    const char *buf;
+    long l;
+    XLU_Config *config;
+    XLU_ConfigList *vbds, *nics, *pcis, *cvfbs;
+    int pci_power_mgmt = 0;
+    int pci_msitranslate = 1;
+    int i, e;
+
+    config= xlu_cfg_init(stderr, configfile_filename_report);
+    if (!config) {
+        fprintf(stderr, "Failed to allocate for configuration\n");
+        exit(1);
+    }
+
+    e= xlu_cfg_readdata(config, configfile_data, configfile_len);
+    if (e) {
+        fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
+        exit(1);
+    }
+
+    init_create_info(c_info);
+
+    c_info->hvm = 0;
+    if (!xlu_cfg_get_string (config, "builder", &buf) &&
+        !strncmp(buf, "hvm", strlen(buf)))
+        c_info->hvm = 1;
+
+    /* hap is missing */
+    if (!xlu_cfg_get_string (config, "name", &buf))
+        c_info->name = strdup(buf);
+    else
+        c_info->name = "test";
+    for (i = 0; i < 16; i++) {
+        c_info->uuid[i] = rand();
+    }
+
+    if (!xlu_cfg_get_long(config, "oos", &l))
+        c_info->oos = l;
+
+    init_build_info(b_info, c_info);
+
+    /* the following is the actual config parsing with overriding values in 
the structures */
+    if (!xlu_cfg_get_long (config, "vcpus", &l))
+        b_info->max_vcpus = l;
+
+    if (!xlu_cfg_get_long (config, "memory", &l)) {
+        b_info->max_memkb = l * 1024;
+        b_info->target_memkb = b_info->max_memkb;
+    }
+
+    if (!xlu_cfg_get_long(config, "tsc_mode", &l))
+        b_info->tsc_mode = l;
+
+    if (!xlu_cfg_get_long (config, "shadow_memory", &l))
+        b_info->shadow_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long (config, "videoram", &l))
+        b_info->video_memkb = l * 1024;
+
+    if (!xlu_cfg_get_string (config, "kernel", &buf))
+        b_info->kernel = strdup(buf);
+
+    if (c_info->hvm == 1) {
+        if (!xlu_cfg_get_long (config, "pae", &l))
+            b_info->u.hvm.pae = l;
+        if (!xlu_cfg_get_long (config, "apic", &l))
+            b_info->u.hvm.apic = l;
+        if (!xlu_cfg_get_long (config, "acpi", &l))
+            b_info->u.hvm.acpi = l;
+        if (!xlu_cfg_get_long (config, "nx", &l))
+            b_info->u.hvm.nx = l;
+        if (!xlu_cfg_get_long (config, "viridian", &l))
+            b_info->u.hvm.viridian = l;
+    } else {
+        char *cmdline;
+        if (!xlu_cfg_get_string (config, "root", &buf)) {
+            asprintf(&cmdline, "root=%s", buf);
+            b_info->u.pv.cmdline = cmdline;
+        }
+        if (!xlu_cfg_get_string (config, "ramdisk", &buf))
+            b_info->u.pv.ramdisk = strdup(buf);
+    }
+
+    if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
+        *num_disks = 0;
+        *disks = NULL;
+        while ((buf = xlu_cfg_get_listitem (vbds, *num_disks)) != NULL) {
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+            *disks = (libxl_device_disk *) realloc(*disks, sizeof 
(libxl_device_disk) * ((*num_disks) + 1));
+            (*disks)[*num_disks].backend_domid = 0;
+            (*disks)[*num_disks].domid = 0;
+            (*disks)[*num_disks].unpluggable = 0;
+            p = strtok(buf2, ",:");
+            while (*p == ' ')
+                p++;
+            if (!strcmp(p, "phy")) {
+                (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
+            } else if (!strcmp(p, "file")) {
+                (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
+            } else if (!strcmp(p, "tap")) {
+                p = strtok(NULL, ":");
+                if (!strcmp(p, "aio")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
+                } else if (!strcmp(p, "vhd")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
+                } else if (!strcmp(p, "qcow")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
+                } else if (!strcmp(p, "qcow2")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
+                }
+            }
+            p = strtok(NULL, ",");
+            while (*p == ' ')
+                p++;
+            (*disks)[*num_disks].physpath= strdup(p);
+            p = strtok(NULL, ",");
+            while (*p == ' ')
+                p++;
+            p2 = strchr(p, ':');
+            if (p2 == NULL) {
+                (*disks)[*num_disks].virtpath = strdup(p);
+                (*disks)[*num_disks].is_cdrom = 0;
+                (*disks)[*num_disks].unpluggable = 1;
+            } else {
+                *p2 = '\0';
+                (*disks)[*num_disks].virtpath = strdup(p);
+                if (!strcmp(p2 + 1, "cdrom")) {
+                    (*disks)[*num_disks].is_cdrom = 1;
+                    (*disks)[*num_disks].unpluggable = 1;
+                } else
+                    (*disks)[*num_disks].is_cdrom = 0;
+            }
+            p = strtok(NULL, ",");
+            while (*p == ' ')
+                p++;
+            (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
+            free(buf2);
+            *num_disks = (*num_disks) + 1;
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "vif", &nics, 0)) {
+        *num_vifs = 0;
+        *vifs = NULL;
+        while ((buf = xlu_cfg_get_listitem (nics, *num_vifs)) != NULL) {
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+            *vifs = (libxl_device_nic *) realloc(*vifs, sizeof 
(libxl_device_nic) * ((*num_vifs) + 1));
+            init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "model")) {
+                    (*vifs)[*num_vifs].model = strdup(p2 + 1);
+                } else if (!strcmp(p, "mac")) {
+                    char *p3 = p2 + 1;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
+                } else if (!strcmp(p, "bridge")) {
+                    (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
+                } else if (!strcmp(p, "type")) {
+                    if (!strcmp(p2 + 1, "ioemu"))
+                        (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
+                    else
+                        (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
+                } else if (!strcmp(p, "ip")) {
+                    inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
+                } else if (!strcmp(p, "script")) {
+                    (*vifs)[*num_vifs].script = strdup(p2 + 1);
+                } else if (!strcmp(p, "vifname")) {
+                    (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
+                } else if (!strcmp(p, "rate")) {
+                    fprintf(stderr, "the rate parameter for vifs is currently 
not supported\n");
+                } else if (!strcmp(p, "accel")) {
+                    fprintf(stderr, "the accel parameter for vifs is currently 
not supported\n");
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip:
+            free(buf2);
+            *num_vifs = (*num_vifs) + 1;
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
+        *num_vfbs = 0;
+        *num_vkbs = 0;
+        *vfbs = NULL;
+        *vkbs = NULL;
+        while ((buf = xlu_cfg_get_listitem (cvfbs, *num_vfbs)) != NULL) {
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+            *vfbs = (libxl_device_vfb *) realloc(*vfbs, 
sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
+            init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
+
+            *vkbs = (libxl_device_vkb *) realloc(*vkbs, 
sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
+            init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
+
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_vfb;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "vnc")) {
+                    (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
+                } else if (!strcmp(p, "vnclisten")) {
+                    (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncdisplay")) {
+                    (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
+                } else if (!strcmp(p, "vncunused")) {
+                    (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
+                } else if (!strcmp(p, "keymap")) {
+                    (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
+                } else if (!strcmp(p, "sdl")) {
+                    (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
+                } else if (!strcmp(p, "opengl")) {
+                    (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
+                } else if (!strcmp(p, "display")) {
+                    (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
+                } else if (!strcmp(p, "xauthority")) {
+                    (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_vfb:
+            free(buf2);
+            *num_vfbs = (*num_vfbs) + 1;
+            *num_vkbs = (*num_vkbs) + 1;
+        }
+    }
+
+    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
+        pci_msitranslate = l;
+
+    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
+        pci_power_mgmt = l;
+
+    if (!xlu_cfg_get_list (config, "pci", &pcis, 0)) {
+        *num_pcidevs = 0;
+        *pcidevs = NULL;
+        while ((buf = xlu_cfg_get_listitem (pcis, *num_pcidevs)) != NULL) {
+            unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
+            char *buf2 = strdup(buf);
+            char *p;
+            *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof 
(libxl_device_pci) * ((*num_pcidevs) + 1));
+            memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_pci;
+            if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, 
&vdevfn)) {
+                sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
+                domain = 0;
+            }
+            libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, 
func, vdevfn);
+            (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
+            (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
+            while ((p = strtok(NULL, ",=")) != NULL) {
+                while (*p == ' ')
+                    p++;
+                if (!strcmp(p, "msitranslate")) {
+                    p = strtok(NULL, ",=");
+                    (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
+                } else if (!strcmp(p, "power_mgmt")) {
+                    p = strtok(NULL, ",=");
+                    (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
+                }
+            }
+            *num_pcidevs = (*num_pcidevs) + 1;
+skip_pci:
+            free(buf2);
+        }
+    }
+
+    if (c_info->hvm == 1) {
+        /* init dm from c and b */
+        init_dm_info(dm_info, c_info, b_info);
+
+        /* then process config related to dm */
+        if (!xlu_cfg_get_string (config, "device_model", &buf))
+            dm_info->device_model = strdup(buf);
+        if (!xlu_cfg_get_long (config, "stdvga", &l))
+            dm_info->stdvga = l;
+        if (!xlu_cfg_get_long (config, "vnc", &l))
+            dm_info->vnc = l;
+        if (!xlu_cfg_get_string (config, "vnclisten", &buf))
+            dm_info->vnclisten = strdup(buf);
+        if (!xlu_cfg_get_long (config, "vncdisplay", &l))
+            dm_info->vncdisplay = l;
+        if (!xlu_cfg_get_long (config, "vncunused", &l))
+            dm_info->vncunused = l;
+        if (!xlu_cfg_get_string (config, "keymap", &buf))
+            dm_info->keymap = strdup(buf);
+        if (!xlu_cfg_get_long (config, "sdl", &l))
+            dm_info->sdl = l;
+        if (!xlu_cfg_get_long (config, "opengl", &l))
+            dm_info->opengl = l;
+        if (!xlu_cfg_get_long (config, "nographic", &l))
+            dm_info->nographic = l;
+        if (!xlu_cfg_get_string (config, "serial", &buf))
+            dm_info->serial = strdup(buf);
+        if (!xlu_cfg_get_string (config, "boot", &buf))
+            dm_info->boot = strdup(buf);
+        if (!xlu_cfg_get_long (config, "usb", &l))
+            dm_info->usb = l;
+        if (!xlu_cfg_get_string (config, "usbdevice", &buf))
+            dm_info->usbdevice = strdup(buf);
+    }
+
+    dm_info->type = c_info->hvm ? XENFV : XENPV;
+
+    xlu_cfg_destroy(config);
+}
+
+#define CHK_ERRNO( call ) ({                                            \
+        int chk_errno = (call);                                         \
+        if (chk_errno) {                                                \
+            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
+                    __FILE__,__LINE__, strerror(chk_errno), #call);     \
+            exit(-ERROR_FAIL);                                          \
+        }                                                               \
+    })
+
+#define MUST( call ) ({                                                 \
+        int must_rc = (call);                                           \
+        if (must_rc) {                                                  \
+            fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
+                    __FILE__,__LINE__, must_rc, #call);                 \
+            exit(-must_rc);                                             \
+        }                                                               \
+    })
+
+static void *xmalloc(size_t sz) {
+    void *r;
+    r = malloc(sz);
+    if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
+                      (unsigned long)sz); exit(-ERROR_FAIL); }
+    return r;
+}
+
+static void *xrealloc(void *ptr, size_t sz) {
+    void *r;
+    if (!sz) { free(ptr); return 0; }
+      /* realloc(non-0, 0) has a useless return value;
+       * but xrealloc(anything, 0) is like free
+       */
+    r = realloc(ptr, sz);
+    if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
+                      (unsigned long)sz); exit(-ERROR_FAIL); }
+    return r;
+}
+
+static int create_domain(int debug, int daemonize, const char *config_file, 
const char *restore_file, int paused, int migrate_fd /* -1 means none */, char 
**migration_domname_r)
+{
+    libxl_domain_create_info info1;
+    libxl_domain_build_info info2;
+    libxl_domain_build_state state;
+    libxl_device_model_info dm_info;
+    libxl_device_disk *disks = NULL;
+    libxl_device_nic *vifs = NULL;
+    libxl_device_pci *pcidevs = NULL;
+    libxl_device_vfb *vfbs = NULL;
+    libxl_device_vkb *vkbs = NULL;
+    libxl_device_console console;
+    int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 
0;
+    int i, fd;
+    int need_daemon = 1;
+    int ret, rc;
+    libxl_device_model_starting *dm_starting = 0;
+    libxl_waiter *w1 = NULL, *w2 = NULL;
+    void *config_data = 0;
+    int config_len = 0;
+    int restore_fd = -1;
+    struct save_file_header hdr;
+
+    memset(&dm_info, 0x00, sizeof(dm_info));
+
+    if (restore_file) {
+        uint8_t *optdata_begin = 0;
+        const uint8_t *optdata_here = 0;
+        union { uint32_t u32; char b[4]; } u32buf;
+        uint32_t badflags;
+
+        restore_fd = migrate_fd >= 0 ? migrate_fd :
+            open(restore_file, O_RDONLY);
+
+        CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, &hdr,
+                   sizeof(hdr), restore_file, "header") );
+        if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
+            fprintf(stderr, "File has wrong magic number -"
+                    " corrupt or for a different tool?\n");
+            return ERROR_INVAL;
+        }
+        if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
+            fprintf(stderr, "File has wrong byte order\n");
+            return ERROR_INVAL;
+        }
+        fprintf(stderr, "Loading new save file %s"
+                " (new xl fmt info"
+                " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
+                restore_file, hdr.mandatory_flags, hdr.optional_flags,
+                hdr.optional_data_len);
+
+        badflags = hdr.mandatory_flags & ~( 0 /* none understood yet */ );
+        if (badflags) {
+            fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
+                    "which are not supported; need newer xl\n",
+                    badflags);
+            return ERROR_INVAL;
+        }
+        if (hdr.optional_data_len) {
+            optdata_begin = xmalloc(hdr.optional_data_len);
+            CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, optdata_begin,
+                   hdr.optional_data_len, restore_file, "optdata") );
+        }
+
+#define OPTDATA_LEFT  (hdr.optional_data_len - (optdata_here - optdata_begin))
+#define WITH_OPTDATA(amt, body)                                 \
+            if (OPTDATA_LEFT < (amt)) {                         \
+                fprintf(stderr, "Savefile truncated.\n");       \
+                return ERROR_INVAL;                             \
+            } else {                                            \
+                body;                                           \
+                optdata_here += (amt);                          \
+            }
+
+        optdata_here = optdata_begin;
+
+        if (OPTDATA_LEFT) {
+            fprintf(stderr, " Savefile contains xl domain config\n");
+            WITH_OPTDATA(4, {
+                memcpy(u32buf.b, optdata_here, 4);
+                config_len = u32buf.u32;
+            });
+            WITH_OPTDATA(config_len, {
+                config_data = xmalloc(config_len);
+                memcpy(config_data, optdata_here, config_len);
+            });
+        }
+
+    }
+
+    if (config_file) {
+        free(config_data);  config_data = 0;
+        ret = libxl_read_file_contents(&ctx, config_file,
+                                       &config_data, &config_len);
+        if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
+                           config_file, strerror(errno)); return ERROR_FAIL; }
+    } else {
+        if (!config_data) {
+            fprintf(stderr, "Config file not specified and"
+                    " none in save file\n");
+            return ERROR_INVAL;
+        }
+        config_file = "<saved>";
+    }
+
+    printf("Parsing config file %s\n", config_file);
+
+    parse_config_data(config_file, config_data, config_len, &info1, &info2, 
&disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, 
&vkbs, &num_vkbs, &dm_info);
+
+    if (migrate_fd >= 0) {
+        if (info1.name) {
+            /* when we receive a domain we get its name from the config
+             * file; and we receive it to a temporary name */
+            assert(!common_domname);
+            common_domname = info1.name;
+            asprintf(migration_domname_r, "%s--incoming", info1.name);
+            info1.name = *migration_domname_r;
+        }
+    }
+
+    if (debug)
+        printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, 
num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
+
+start:
+    domid = 0;
+
+    ret = libxl_domain_make(&ctx, &info1, &domid);
+    if (ret) {
+        fprintf(stderr, "cannot make domain: %d\n", ret);
+        return ERROR_FAIL;
+    }
+
+    ret = libxl_userdata_store(&ctx, domid, "xl",
+                                    config_data, config_len);
+    if (ret) {
+        perror("cannot save config file");
+        return ERROR_FAIL;
+    }
+
+    if (!restore_file || !need_daemon) {
+        if (dm_info.saved_state) {
+            free(dm_info.saved_state);
+            dm_info.saved_state = NULL;
+        }
+        ret = libxl_domain_build(&ctx, &info2, domid, &state);
+    } else {
+        ret = libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, 
&dm_info);
+    }
+
+    if (ret) {
+        fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
+        return ERROR_FAIL;
+    }
+
+    for (i = 0; i < num_disks; i++) {
+        disks[i].domid = domid;
+        ret = libxl_device_disk_add(&ctx, domid, &disks[i]);
+        if (ret) {
+            fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
+            return ERROR_FAIL;
+        }
+    }
+    for (i = 0; i < num_vifs; i++) {
+        vifs[i].domid = domid;
+        ret = libxl_device_nic_add(&ctx, domid, &vifs[i]);
+        if (ret) {
+            fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
+            return ERROR_FAIL;
+        }
+    }
+    if (info1.hvm) {
+        dm_info.domid = domid;
+        MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
+                                        vifs, num_vifs, &dm_starting) );
+    } else {
+        for (i = 0; i < num_vfbs; i++) {
+            vfbs[i].domid = domid;
+            libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
+            vkbs[i].domid = domid;
+            libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
+        }
+        init_console_info(&console, 0, &state);
+        console.domid = domid;
+        if (num_vfbs)
+            console.constype = CONSTYPE_IOEMU;
+        libxl_device_console_add(&ctx, domid, &console);
+        if (num_vfbs)
+            libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
+    }
+
+    if (dm_starting)
+        MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
+    for (i = 0; i < num_pcidevs; i++)
+        libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
+
+    if (!paused)
+        libxl_domain_unpause(&ctx, domid);
+
+    if (!daemonize)
+        return 0; /* caller gets success in parent */
+
+    if (need_daemon) {
+        char *fullname, *name;
+        pid_t child1, got_child;
+        int nullfd;
+
+        child1 = libxl_fork(&ctx);
+        if (child1) {
+            int status;
+            for (;;) {
+                got_child = waitpid(child1, &status, 0);
+                if (got_child == child1) break;
+                assert(got_child == -1);
+                if (errno != EINTR) {
+                    perror("failed to wait for daemonizing child");
+                    return ERROR_FAIL;
+                }
+            }
+            if (status) {
+                libxl_report_child_exitstatus(&ctx, XL_LOG_ERROR,
+                           "daemonizing child", child1, status);
+                return ERROR_FAIL;
+            }
+            return 0; /* caller gets success in parent */
+        }
+
+        rc = libxl_ctx_postfork(&ctx);
+        if (rc) {
+            LOG("failed to reinitialise context after fork");
+            exit(-1);
+        }
+
+        asprintf(&name, "xl-%s", info1.name);
+        rc = libxl_create_logfile(&ctx, name, &fullname);
+        if (rc) {
+            LOG("failed to open logfile %s",fullname,strerror(errno));
+            exit(-1);
+        }
+
+        CHK_ERRNO(( logfile = open(fullname, O_WRONLY|O_CREAT, 0644) )<0);
+        free(fullname);
+        free(name);
+
+        CHK_ERRNO(( nullfd = open("/dev/null", O_RDONLY) )<0);
+        dup2(nullfd, 0);
+        dup2(logfile, 1);
+        dup2(logfile, 2);
+
+        daemon(0, 1);
+        need_daemon = 0;
+    }
+    LOG("Waiting for domain %s (domid %d) to die [pid %ld]",
+        info1.name, domid, (long)getpid());
+    w1 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter) * num_disks);
+    w2 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter));
+    libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
+    libxl_wait_for_domain_death(&ctx, domid, w2);
+    libxl_get_wait_fd(&ctx, &fd);
+    while (1) {
+        int ret;
+        fd_set rfds;
+        xc_domaininfo_t info;
+        libxl_event event;
+        libxl_device_disk disk;
+        memset(&info, 0x00, sizeof(xc_dominfo_t));
+
+        FD_ZERO(&rfds);
+        FD_SET(fd, &rfds);
+
+        ret = select(fd + 1, &rfds, NULL, NULL, NULL);
+        if (!ret)
+            continue;
+        libxl_get_event(&ctx, &event);
+        switch (event.type) {
+            case DOMAIN_DEATH:
+                if (libxl_event_get_domain_death_info(&ctx, domid, &event, 
&info)) {
+                    LOG("Domain %d is dead", domid);
+                    if (info.flags & XEN_DOMINF_dying || (info.flags & 
XEN_DOMINF_shutdown && (((info.flags >> XEN_DOMINF_shutdownshift) & 
XEN_DOMINF_shutdownmask) != SHUTDOWN_suspend))) {
+                        LOG("Domain %d needs to be clean: destroying the 
domain", domid);
+                        libxl_domain_destroy(&ctx, domid, 0);
+                        if (info.flags & XEN_DOMINF_shutdown &&
+                            (((info.flags >> XEN_DOMINF_shutdownshift) & 
XEN_DOMINF_shutdownmask) == SHUTDOWN_reboot)) {
+                            libxl_free_waiter(w1);
+                            libxl_free_waiter(w2);
+                            free(w1);
+                            free(w2);
+                            LOG("Done. Rebooting now");
+                            goto start;
+                        }
+                        LOG("Done. Exiting now");
+                    }
+                    LOG("Domain %d does not need to be clean, exiting now", 
domid);
+                    exit(0);
+                }
+                break;
+            case DISK_EJECT:
+                if (libxl_event_get_disk_eject_info(&ctx, domid, &event, 
&disk))
+                    libxl_cdrom_insert(&ctx, domid, &disk);
+                break;
+        }
+        libxl_free_event(&event);
+    }
+
+    close(logfile);
+    exit(0);
+}
+
+void help(char *command)
+{
+    if (!command || !strcmp(command, "help")) {
+        printf("Usage xl <subcommand> [args]\n\n");
+        printf("xl full list of subcommands:\n\n");
+        printf(" create                        create a domain from config 
file <filename>\n\n");
+        printf(" list                          list information about all 
domains\n\n");
+        printf(" destroy                       terminate a domain 
immediately\n\n");
+        printf(" pci-attach                    insert a new pass-through pci 
device\n\n");
+        printf(" pci-detach                    remove a domain's pass-through 
pci device\n\n");
+        printf(" pci-list                      list pass-through pci devices 
for a domain\n\n");
+        printf(" pause                         pause execution of a 
domain\n\n");
+        printf(" unpause                       unpause a paused domain\n\n");
+        printf(" console                       attach to domain's 
console\n\n");
+        printf(" save                          save a domain state to restore 
later\n\n");
+        printf(" restore                       restore a domain from a saved 
state\n\n");
+        printf(" cd-insert                     insert a cdrom into a guest's 
cd drive\n\n");
+        printf(" cd-eject                      eject a cdrom from a guest's cd 
drive\n\n");
+        printf(" mem-set                       set the current memory usage 
for a domain\n\n");
+        printf(" button-press                  indicate an ACPI button press 
to the domain\n\n");
+        printf(" vcpu-list                     list the VCPUs for all/some 
domains.\n\n");
+        printf(" vcpu-pin                      Set which CPUs a VCPU can 
use.\n\n");
+        printf(" vcpu-set                      Set the number of active VCPUs 
allowed for the domain.\n\n");
+    } else if(!strcmp(command, "create")) {
+        printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
+        printf("Create a domain based on <ConfigFile>.\n\n");
+        printf("Options:\n\n");
+        printf("-h                     Print this help.\n");
+        printf("-p                     Leave the domain paused after it is 
created.\n");
+        printf("-d                     Enable debug messages.\n");
+        printf("-e                     Do not wait in the background for the 
death of the domain.\n");
+    } else if(!strcmp(command, "list")) {
+        printf("Usage: xl list [-v] [Domain]\n\n");
+        printf("List information about all/some domains.\n\n");
+    } else if(!strcmp(command, "pci-attach")) {
+        printf("Usage: xl pci-attach <Domain> <BDF> [Virtual Slot]\n\n");
+        printf("Insert a new pass-through pci device.\n\n");
+    } else if(!strcmp(command, "pci-detach")) {
+        printf("Usage: xl pci-detach <Domain> <BDF>\n\n");
+        printf("Remove a domain's pass-through pci device.\n\n");
+    } else if(!strcmp(command, "pci-list")) {
+        printf("Usage: xl pci-list <Domain>\n\n");
+        printf("List pass-through pci devices for a domain.\n\n");
+    } else if(!strcmp(command, "pause")) {
+        printf("Usage: xl pause <Domain>\n\n");
+        printf("Pause execution of a domain.\n\n");
+    } else if(!strcmp(command, "unpause")) {
+        printf("Usage: xl unpause <Domain>\n\n");
+        printf("Unpause a paused domain.\n\n");
+    } else if(!strcmp(command, "save")) {
+        printf("Usage: xl save [options] <Domain> <CheckpointFile> 
[<ConfigFile>]\n\n");
+        printf("Save a domain state to restore later.\n\n");
+        printf("Options:\n\n");
+        printf("-h                     Print this help.\n");
+        printf("-c                     Leave domain running after creating the 
snapshot.\n");
+    } else if(!strcmp(command, "restore")) {
+        printf("Usage: xl restore [options] [<ConfigFile>] 
<CheckpointFile>\n\n");
+        printf("Restore a domain from a saved state.\n\n");
+        printf("Options:\n\n");
+        printf("-h                     Print this help.\n");
+        printf("-p                     Do not unpause domain after restoring 
it.\n");
+        printf("-e                     Do not wait in the background for the 
death of the domain.\n");
+        printf("-d                     Enable debug messages.\n");
+    } else if(!strcmp(command, "migrate")) {
+        printf("Usage: xl migrate [options] <Domain> <host>\n\n");
+        printf("Save a domain state to restore later.\n\n");
+        printf("Options:\n\n");
+        printf("-h                     Print this help.\n");
+        printf("-C <config>            Send <config> instead of config file 
from creation.\n");
+        printf("-s <sshcommand>        Use <sshcommand> instead of ssh.  
String will be passed to sh.  If empty, run <host> instead of ssh <host> xl 
migrate-receive [-d -e]\n");
+        printf("-e                     Do not wait in the background (on 
<host>) for the death of the domain.\n");
+    } else if(!strcmp(command, "migrate-receive")) {
+        printf("Usage: xl migrate-receive  - for internal use only");
+    } else if(!strcmp(command, "restore")) {
+        printf("Usage: xl restore [options] [<ConfigFile>] 
<CheckpointFile>\n\n");
+        printf("Restore a domain from a saved state.\n\n");
+        printf("Options:\n\n");
+        printf("-h                     Print this help.\n");
+        printf("-O                     Old (configless) xl save format.\n");
+        printf("-p                     Do not unpause domain after restoring 
it.\n");
+        printf("-e                     Do not wait in the background for the 
death of the domain.\n");
+    } else if(!strcmp(command, "destroy")) {
+        printf("Usage: xl destroy <Domain>\n\n");
+        printf("Terminate a domain immediately.\n\n");
+    } else if (!strcmp(command, "console")) {
+        printf("Usage: xl console <Domain>\n\n");
+        printf("Attach to domain's console.\n\n");
+    } else if (!strcmp(command, "cd-insert")) {
+        printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
+        printf("Insert a cdrom into a guest's cd drive.\n\n");
+    } else if (!strcmp(command, "cd-eject")) {
+        printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
+        printf("Eject a cdrom from a guest's cd drive.\n\n");
+    } else if (!strcmp(command, "mem-set")) {
+        printf("Usage: xl mem-set <Domain> <MemKB>\n\n");
+        printf("Set the current memory usage for a domain.\n\n");
+    } else if (!strcmp(command, "button-press")) {
+        printf("Usage: xl button-press <Domain> <Button>\n\n");
+        printf("Indicate <Button> press to a domain.\n");
+        printf("<Button> may be 'power' or 'sleep'.\n\n");
+    } else if (!strcmp(command, "vcpu-list")) {
+        printf("Usage: xl vcpu-list [Domain, ...]\n\n");
+        printf("List the VCPUs for all/some domains.\n\n");
+    } else if (!strcmp(command, "vcpu-pin")) {
+        printf("Usage: xl vcpu-pin <Domain> <VCPU|all> <CPUs|all>\n\n");
+        printf("Set which CPUs a VCPU can use.\n\n");
+    } else if (!strcmp(command, "vcpu-set")) {
+        printf("Usage: xl vcpu-set <Domain> <vCPUs>\n\n");
+        printf("Set the number of active VCPUs for allowed for the 
domain.\n\n");
+    }
+}
+
+void set_memory_target(char *p, char *mem)
+{
+    char *endptr;
+    uint32_t memorykb;
+
+    find_domain(p);
+
+    memorykb = strtoul(mem, &endptr, 10);
+    if (*endptr != '\0') {
+        fprintf(stderr, "invalid memory size: %s\n", mem);
+        exit(3);
+    }
+    printf("setting domid %d memory to : %d\n", domid, memorykb);
+    libxl_set_memory_target(&ctx, domid, memorykb);
+}
+
+int main_memset(int argc, char **argv)
+{
+    int opt = 0;
+    char *p = NULL, *mem;
+
+    while ((opt = getopt(argc, argv, "h:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("mem-set");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("mem-set");
+        exit(2);
+    }
+
+    p = argv[optind];
+    mem = argv[optind + 1];
+
+    set_memory_target(p, mem);
+    exit(0);
+}
+
+void console(char *p, int cons_num)
+{
+    find_domain(p);
+    libxl_console_attach(&ctx, domid, cons_num);
+}
+
+void cd_insert(char *dom, char *virtdev, char *phys)
+{
+    libxl_device_disk disk;
+    char *p;
+
+    find_domain(dom);
+
+    disk.backend_domid = 0;
+    disk.domid = domid;
+    if (phys) {
+        p = strchr(phys, ':');
+        if (!p) {
+            fprintf(stderr, "No type specified, ");
+            disk.physpath = phys;
+            if (!strncmp(phys, "/dev", 4)) {
+                fprintf(stderr, "assuming phy:\n");
+                disk.phystype = PHYSTYPE_PHY;
+            } else {
+                fprintf(stderr, "assuming file:\n");
+                disk.phystype = PHYSTYPE_FILE;
+            }
+        } else {
+            *p = '\0';
+            p++;
+            disk.physpath = p;
+            libxl_string_to_phystype(&ctx, phys, &disk.phystype);
+        }
+    } else {
+            disk.physpath = NULL;
+            disk.phystype = 0;
+    }
+    disk.virtpath = virtdev;
+    disk.unpluggable = 1;
+    disk.readwrite = 0;
+    disk.is_cdrom = 1;
+
+    libxl_cdrom_insert(&ctx, domid, &disk);
+}
+
+int main_cd_eject(int argc, char **argv)
+{
+    int opt = 0;
+    char *p = NULL, *virtdev;
+
+    while ((opt = getopt(argc, argv, "hn:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("cd-eject");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("cd-eject");
+        exit(2);
+    }
+
+    p = argv[optind];
+    virtdev = argv[optind + 1];
+
+    cd_insert(p, virtdev, NULL);
+    exit(0);
+}
+
+int main_cd_insert(int argc, char **argv)
+{
+    int opt = 0;
+    char *p = NULL, *file = NULL, *virtdev;
+
+    while ((opt = getopt(argc, argv, "hn:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("cd-insert");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 2) {
+        help("cd-insert");
+        exit(2);
+    }
+
+    p = argv[optind];
+    virtdev = argv[optind + 1];
+    file = argv[optind + 2];
+
+    cd_insert(p, virtdev, file);
+    exit(0);
+}
+
+int main_console(int argc, char **argv)
+{
+    int opt = 0, cons_num = 0;
+    char *p = NULL;
+
+    while ((opt = getopt(argc, argv, "hn:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("console");
+            exit(0);
+        case 'n':
+            if (optarg) {
+                cons_num = strtol(optarg, NULL, 10);
+            }
+            break;
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("console");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    console(p, cons_num);
+    exit(0);
+}
+
+void pcilist(char *dom)
+{
+    libxl_device_pci *pcidevs;
+    int num, i;
+
+    find_domain(dom);
+
+    pcidevs = libxl_device_pci_list(&ctx, domid, &num);
+    if (!num)
+        return;
+    printf("VFn  domain bus  slot func\n");
+    for (i = 0; i < num; i++) {
+        printf("0x%02x 0x%04x 0x%02x 0x%02x 0x%01x\n", pcidevs[i].vdevfn, 
pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
+    }
+    free(pcidevs);
+}
+
+int main_pcilist(int argc, char **argv)
+{
+    int opt;
+    char *domname = NULL;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pci-list");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("pci-list");
+        exit(2);
+    }
+
+    domname = argv[optind];
+
+    pcilist(domname);
+    exit(0);
+}
+
+void pcidetach(char *dom, char *bdf)
+{
+    libxl_device_pci pcidev;
+    unsigned int domain, bus, dev, func;
+
+    find_domain(dom);
+
+    memset(&pcidev, 0x00, sizeof(pcidev));
+    sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
+    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
+    libxl_device_pci_remove(&ctx, domid, &pcidev);
+}
+
+int main_pcidetach(int argc, char **argv)
+{
+    int opt;
+    char *domname = NULL, *bdf = NULL;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pci-attach");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("pci-detach");
+        exit(2);
+    }
+
+    domname = argv[optind];
+    bdf = argv[optind + 1];
+
+    pcidetach(domname, bdf);
+    exit(0);
+}
+void pciattach(char *dom, char *bdf, char *vs)
+{
+    libxl_device_pci pcidev;
+    unsigned int domain, bus, dev, func;
+
+    find_domain(dom);
+
+    memset(&pcidev, 0x00, sizeof(pcidev));
+    sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
+    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
+    libxl_device_pci_add(&ctx, domid, &pcidev);
+}
+
+int main_pciattach(int argc, char **argv)
+{
+    int opt;
+    char *domname = NULL, *bdf = NULL, *vs = NULL;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pci-attach");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("pci-attach");
+        exit(2);
+    }
+
+    domname = argv[optind];
+    bdf = argv[optind + 1];
+
+    if (optind + 1 < argc)
+        vs = argv[optind + 2];
+
+    pciattach(domname, bdf, vs);
+    exit(0);
+}
+
+void pause_domain(char *p)
+{
+    find_domain(p);
+    libxl_domain_pause(&ctx, domid);
+}
+
+void unpause_domain(char *p)
+{
+    find_domain(p);
+    libxl_domain_unpause(&ctx, domid);
+}
+
+void destroy_domain(char *p)
+{
+    int rc;
+    find_domain(p);
+    rc = libxl_domain_destroy(&ctx, domid, 0);
+    if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n.",rc); exit(-1); }
+}
+
+void list_domains(int verbose)
+{
+    struct libxl_dominfo *info;
+    int nb_domain, i;
+
+    info = libxl_list_domain(&ctx, &nb_domain);
+
+    if (!info) {
+        fprintf(stderr, "libxl_domain_infolist failed.\n");
+        exit(1);
+    }
+    printf("Name                                        ID   Mem 
VCPUs\tState\tTime(s)\n");
+    for (i = 0; i < nb_domain; i++) {
+        printf("%-40s %5d %5lu %5d        %c%c%c %8.1f",
+                libxl_domid_to_name(&ctx, info[i].domid),
+                info[i].domid,
+                (unsigned long) (info[i].max_memkb / 1024),
+                info[i].vcpu_online,
+                info[i].running ? 'r' : '-',
+                info[i].paused ? 'p' : '-',
+                info[i].dying ? 'd' : '-',
+                ((float)info[i].cpu_time / 1e9));
+        if (verbose) {
+            char *uuid = libxl_uuid2string(&ctx, info[i].uuid);
+            printf(" %s", uuid);
+        }
+        putchar('\n');
+    }
+    free(info);
+}
+
+void list_vm(void)
+{
+    struct libxl_vminfo *info;
+    int nb_vm, i;
+
+    info = libxl_list_vm(&ctx, &nb_vm);
+
+    if (info < 0) {
+        fprintf(stderr, "libxl_domain_infolist failed.\n");
+        exit(1);
+    }
+    printf("UUID                                  ID    name\n");
+    for (i = 0; i < nb_vm; i++) {
+        printf(UUID_FMT "  %d    %-30s\n",
+            info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
+            info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
+            info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], 
info[i].uuid[11],
+            info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], 
info[i].uuid[15],
+            info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
+    }
+    free(info);
+}
+
+static void save_domain_core_begin(char *domain_spec,
+                                   const char *override_config_file,
+                                   uint8_t **config_data_r,
+                                   int *config_len_r)
+{
+    int rc;
+
+    find_domain(domain_spec);
+
+    /* configuration file in optional data: */
+
+    if (override_config_file) {
+        void *config_v = 0;
+        rc = libxl_read_file_contents(&ctx, override_config_file,
+                                      &config_v, config_len_r);
+        *config_data_r = config_v;
+    } else {
+        rc = libxl_userdata_retrieve(&ctx, domid, "xl",
+                                     config_data_r, config_len_r);
+    }
+    if (rc) {
+        fputs("Unable to get config file\n",stderr);
+        exit(2);
+    }
+}
+
+void save_domain_core_writeconfig(int fd, const char *filename,
+                                  const uint8_t *config_data, int config_len)
+{
+    struct save_file_header hdr;
+    uint8_t *optdata_begin;
+    union { uint32_t u32; char b[4]; } u32buf;
+
+    memset(&hdr, 0, sizeof(hdr));
+    memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
+    hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
+
+    optdata_begin= 0;
+
+#define ADD_OPTDATA(ptr, len) ({                                            \
+    if ((len)) {                                                        \
+        hdr.optional_data_len += (len);                                 \
+        optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
+        memcpy(optdata_begin + hdr.optional_data_len - (len),           \
+               (ptr), (len));                                           \
+    }                                                                   \
+                          })
+
+    u32buf.u32 = config_len;
+    ADD_OPTDATA(u32buf.b,    4);
+    ADD_OPTDATA(config_data, config_len);
+
+    /* that's the optional data */
+
+    CHK_ERRNO( libxl_write_exactly(&ctx, fd,
+        &hdr, sizeof(hdr), filename, "header") );
+    CHK_ERRNO( libxl_write_exactly(&ctx, fd,
+        optdata_begin, hdr.optional_data_len, filename, "header") );
+
+    fprintf(stderr, "Saving to %s new xl format (info"
+            " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
+            filename, hdr.mandatory_flags, hdr.optional_flags,
+            hdr.optional_data_len);
+}
+
+int save_domain(char *p, char *filename, int checkpoint,
+                const char *override_config_file)
+{
+    int fd;
+    uint8_t *config_data;
+    int config_len;
+
+    save_domain_core_begin(p, override_config_file, &config_data, &config_len);
+
+    if (!config_len) {
+        fputs(" Savefile will not contain xl domain config\n", stderr);
+    }
+
+    fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if (fd < 0) {
+        fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
+        exit(2);
+    }
+
+    save_domain_core_writeconfig(fd, filename, config_data, config_len);
+
+    libxl_domain_suspend(&ctx, NULL, domid, fd);
+    close(fd);
+
+    if (checkpoint)
+        libxl_domain_unpause(&ctx, domid);
+    else
+        libxl_domain_destroy(&ctx, domid, 0);
+
+    exit(0);
+}
+
+static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
+                                     const char *what, const char *rune) {
+    char buf[msgsz];
+    const char *stream;
+    int rc;
+
+    stream = rune ? "migration receiver stream" : "migration stream";
+    rc = libxl_read_exactly(&ctx, fd, buf, msgsz, stream, what);
+    if (rc) return ERROR_FAIL;
+
+    if (memcmp(buf, msg, msgsz)) {
+        fprintf(stderr, "%s contained unexpected data instead of %s\n",
+                stream, what);
+        if (rune)
+            fprintf(stderr, "(command run was: %s )\n", rune);
+        return ERROR_FAIL;
+    }
+    return 0;
+}
+
+static void migration_child_report(pid_t migration_child, int recv_fd) {
+    pid_t child;
+    int status, sr;
+    struct timeval now, waituntil, timeout;
+    static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
+
+    if (!migration_child) return;
+
+    CHK_ERRNO( gettimeofday(&waituntil, 0) );
+    waituntil.tv_sec += 2;
+
+    for (;;) {
+        child = waitpid(migration_child, &status, WNOHANG);
+
+        if (child == migration_child) {
+            if (status)
+                libxl_report_child_exitstatus(&ctx, XL_LOG_INFO,
+                                              "migration target process",
+                                              migration_child, status);
+            break;
+        }
+        if (child == -1) {
+            if (errno == EINTR) continue;
+            fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
+                    (long)migration_child, strerror(errno));
+            break;
+        }
+        assert(child == 0);
+
+        CHK_ERRNO( gettimeofday(&now, 0) );
+        if (timercmp(&now, &waituntil, >)) {
+            fprintf(stderr, "migration child [%ld] not exiting, no longer"
+                    " waiting (exit status will be unreported)\n",
+                    (long)migration_child);
+            break;
+        }
+        timersub(&waituntil, &now, &timeout);
+
+        if (recv_fd >= 0) {
+            fd_set readfds, exceptfds;
+            FD_ZERO(&readfds);
+            FD_ZERO(&exceptfds);
+            FD_SET(recv_fd, &readfds);
+            FD_SET(recv_fd, &exceptfds);
+            sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
+        } else {
+            if (timercmp(&timeout, &pollinterval, >))
+                timeout = pollinterval;
+            sr = select(0,0,0,0, &timeout);
+        }
+        if (sr > 0) {
+            recv_fd = -1;
+        } else if (sr == 0) {
+        } else if (sr == -1) {
+            if (errno != EINTR) {
+                fprintf(stderr, "migration child [%ld] exit wait select"
+                        " failed unexpectedly: %s\n",
+                        (long)migration_child, strerror(errno));
+                break;
+            }
+        }
+    }
+    migration_child = 0;
+}
+
+static void migrate_domain(char *domain_spec, const char *rune,
+                           const char *override_config_file)
+{
+    pid_t child = -1;
+    int rc;
+    int sendpipe[2], recvpipe[2];
+    int send_fd, recv_fd;
+    libxl_domain_suspend_info suspinfo;
+    char *away_domname;
+    char rc_buf;
+    uint8_t *config_data;
+    int config_len;
+
+    save_domain_core_begin(domain_spec, override_config_file,
+                           &config_data, &config_len);
+
+    if (!common_domname) {
+        common_domname = libxl_domid_to_name(&ctx, domid);
+        /* libxl_domid_to_name fails ?  don't bother with names then */
+    }
+
+    if (!config_len) {
+        fprintf(stderr, "No config file stored for running domain and "
+                "none supplied - cannot migrate.\n");
+        exit(1);
+    }
+
+    MUST( libxl_pipe(&ctx, sendpipe) );
+    MUST( libxl_pipe(&ctx, recvpipe) );
+
+    child = libxl_fork(&ctx);
+    if (child==-1) exit(1);
+
+    if (!child) {
+        dup2(sendpipe[0], 0);
+        dup2(recvpipe[1], 1);
+        close(sendpipe[0]); close(sendpipe[1]);
+        close(recvpipe[0]); close(recvpipe[1]);
+        execlp("sh","sh","-c",rune,(char*)0);
+        perror("failed to exec sh");
+        exit(-1);
+    }
+
+    close(sendpipe[0]);
+    close(recvpipe[1]);
+    send_fd = sendpipe[1];
+    recv_fd = recvpipe[0];
+
+    signal(SIGPIPE, SIG_IGN);
+    /* if receiver dies, we get an error and can clean up
+       rather than just dying */
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
+                                   sizeof(migrate_receiver_banner)-1,
+                                   "banner", rune);
+    if (rc) {
+        close(send_fd);
+        migration_child_report(child, recv_fd);
+        exit(-rc);
+    }
+
+    save_domain_core_writeconfig(send_fd, "migration stream",
+                                 config_data, config_len);
+
+    memset(&suspinfo, 0, sizeof(suspinfo));
+    suspinfo.flags |= XL_SUSPEND_LIVE;
+    rc = libxl_domain_suspend(&ctx, &suspinfo, domid, send_fd);
+    if (rc) {
+        fprintf(stderr, "migration sender: libxl_domain_suspend failed"
+                " (rc=%d)\n", rc);
+        goto failed_resume;
+    }
+
+    fprintf(stderr, "migration sender: Transfer complete.\n");
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
+                                   sizeof(migrate_receiver_ready),
+                                   "ready message", rune);
+    if (rc) goto failed_resume;
+
+    /* right, at this point we are about give the destination
+     * permission to rename and resume, so we must first rename the
+     * domain away ourselves */
+
+    fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
+
+    if (common_domname) {
+        asprintf(&away_domname, "%s--migratedaway", common_domname);
+        rc = libxl_domain_rename(&ctx, domid,
+                                 common_domname, away_domname, 0);
+        if (rc) goto failed_resume;
+    }
+
+    /* point of no return - as soon as we have tried to say
+     * "go" to the receiver, it's not safe to carry on.  We leave
+     * the domain renamed to %s--migratedaway in case that's helpful.
+     */
+
+    fprintf(stderr, "migration sender: Giving target permission to start.\n");
+
+    rc = libxl_write_exactly(&ctx, send_fd,
+                             migrate_permission_to_go,
+                             sizeof(migrate_permission_to_go),
+                             "migration stream", "GO message");
+    if (rc) goto failed_badly;
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_report,
+                                   sizeof(migrate_report),
+                                   "success/failure report message", rune);
+    if (rc) goto failed_badly;
+
+    rc = libxl_read_exactly(&ctx, recv_fd,
+                            &rc_buf, 1,
+                            "migration ack stream", "success/failure status");
+    if (rc) goto failed_badly;
+
+    if (rc_buf) {
+        fprintf(stderr, "migration sender: Target reports startup failure"
+                " (status code %d).\n", rc_buf);
+
+        rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
+                                       sizeof(migrate_permission_to_go),
+                                       "permission for sender to resume",
+                                       rune);
+        if (rc) goto failed_badly;
+
+        fprintf(stderr, "migration sender: Trying to resume at our end.\n");
+
+        if (common_domname) {
+            libxl_domain_rename(&ctx, domid,
+                                away_domname, common_domname, 0);
+        }
+        rc = libxl_domain_resume(&ctx, domid);
+        if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
+
+        fprintf(stderr, "Migration failed due to problems at target.\n");
+        exit(-ERROR_FAIL);
+    }
+
+    fprintf(stderr, "migration sender: Target reports successful startup.\n");
+    libxl_domain_destroy(&ctx, domid, 1); /* bang! */
+    fprintf(stderr, "Migration successful.\n");
+    exit(0);
+
+ failed_resume:
+    close(send_fd);
+    migration_child_report(child, recv_fd);
+    fprintf(stderr, "Migration failed, resuming at sender.\n");
+    libxl_domain_resume(&ctx, domid);
+    exit(-ERROR_FAIL);
+
+ failed_badly:
+    fprintf(stderr,
+ "** Migration failed during final handshake **\n"
+ "Domain state is now undefined !\n"
+ "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
+ " resuming at most one instance.  Two simultaneous instances of the domain\n"
+ " would probably result in SEVERE DATA LOSS and it is now your\n"
+ " responsibility to avoid that.  Sorry.\n");
+
+    close(send_fd);
+    migration_child_report(child, recv_fd);
+    exit(-ERROR_BADFAIL);
+}
+
+static void migrate_receive(int debug, int daemonize)
+{
+    int rc, rc2;
+    char rc_buf;
+    char *migration_domname;
+
+    signal(SIGPIPE, SIG_IGN);
+    /* if we get SIGPIPE we'd rather just have it as an error */
+
+    fprintf(stderr, "migration target: Ready to receive domain.\n");
+
+    CHK_ERRNO( libxl_write_exactly(&ctx, 1,
+                                   migrate_receiver_banner,
+                                   sizeof(migrate_receiver_banner)-1,
+                                   "migration ack stream",
+                                   "banner") );
+
+    rc = create_domain(debug, daemonize,
+                       0 /* no config file, use incoming */,
+                       "incoming migration stream", 1,
+                       0, &migration_domname);
+    if (rc) {
+        fprintf(stderr, "migration target: Domain creation failed"
+                " (code %d).\n", rc);
+        exit(-rc);
+    }
+
+    fprintf(stderr, "migration target: Transfer complete,"
+            " requesting permission to start domain.\n");
+
+    rc = libxl_write_exactly(&ctx, 1,
+                             migrate_receiver_ready,
+                             sizeof(migrate_receiver_ready),
+                             "migration ack stream", "ready message");
+    if (rc) exit(-rc);
+
+    rc = migrate_read_fixedmessage(0, migrate_permission_to_go,
+                                   sizeof(migrate_permission_to_go),
+                                   "GO message", 0);
+    if (rc) goto perhaps_destroy_notify_rc;
+
+    fprintf(stderr, "migration target: Got permission, starting domain.\n");
+
+    if (migration_domname) {
+        rc = libxl_domain_rename(&ctx, domid,
+                                 migration_domname, common_domname, 0);
+        if (rc) goto perhaps_destroy_notify_rc;
+    }
+
+    rc = libxl_domain_unpause(&ctx, domid);
+    if (rc) goto perhaps_destroy_notify_rc;
+
+    fprintf(stderr, "migration target: Domain started successsfully.\n");
+    rc = 0;
+
+ perhaps_destroy_notify_rc:
+    rc2 = libxl_write_exactly(&ctx, 1,
+                              migrate_report, sizeof(migrate_report),
+                              "migration ack stream",
+                              "success/failure report");
+    if (rc2) exit(-ERROR_BADFAIL);
+
+    rc_buf = -rc;
+    assert(!!rc_buf == !!rc);
+    rc2 = libxl_write_exactly(&ctx, 1, &rc_buf, 1,
+                              "migration ack stream",
+                              "success/failure code");
+    if (rc2) exit(-ERROR_BADFAIL);
+
+    if (rc) {
+        fprintf(stderr, "migration target: Failure, destroying our copy.\n");
+
+        rc2 = libxl_domain_destroy(&ctx, domid, 1);
+        if (rc2) {
+            fprintf(stderr, "migration target: Failed to destroy our copy"
+                    " (code %d).\n", rc2);
+            exit(-ERROR_BADFAIL);
+        }
+
+        fprintf(stderr, "migration target: Cleanup OK, granting sender"
+                " permission to resume.\n");
+
+        rc2 = libxl_write_exactly(&ctx, 1,
+                                  migrate_permission_to_go,
+                                  sizeof(migrate_permission_to_go),
+                                  "migration ack stream",
+                                  "permission to sender to have domain back");
+        if (rc2) exit(-ERROR_BADFAIL);
+    }
+
+    exit(0);
+}
+
+int main_restore(int argc, char **argv)
+{
+    char *checkpoint_file = NULL;
+    char *config_file = NULL;
+    int paused = 0, debug = 0, daemonize = 1;
+    int opt, rc;
+
+    while ((opt = getopt(argc, argv, "hpde")) != -1) {
+        switch (opt) {
+        case 'p':
+            paused = 1;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        case 'e':
+            daemonize = 0;
+            break;
+        case 'h':
+            help("restore");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (argc-optind == 1) {
+        checkpoint_file = argv[optind];
+    } else if (argc-optind == 2) {
+        config_file = argv[optind];
+        checkpoint_file = argv[optind + 1];
+    } else {
+        help("restore");
+        exit(2);
+    }
+    rc = create_domain(debug, daemonize, config_file,
+                       checkpoint_file, paused, -1, 0);
+    exit(-rc);
+}
+
+int main_migrate_receive(int argc, char **argv)
+{
+    int debug = 0, daemonize = 1;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "hed")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("restore");
+            exit(2);
+            break;
+        case 'e':
+            daemonize = 0;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (argc-optind != 0) {
+        help("restore");
+        exit(2);
+    }
+    migrate_receive(debug, daemonize);
+    exit(0);
+}
+
+int main_save(int argc, char **argv)
+{
+    char *filename = NULL, *p = NULL;
+    const char *config_filename;
+    int checkpoint = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "hc")) != -1) {
+        switch (opt) {
+        case 'c':
+            checkpoint = 1;
+            break;
+        case 'h':
+            help("save");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (argc-optind < 1 || argc-optind > 3) {
+        help("save");
+        exit(2);
+    }
+
+    p = argv[optind];
+    filename = argv[optind + 1];
+    config_filename = argv[optind + 2];
+    save_domain(p, filename, checkpoint, config_filename);
+    exit(0);
+}
+
+int main_migrate(int argc, char **argv)
+{
+    char *p = NULL;
+    const char *config_filename = NULL;
+    const char *ssh_command = "ssh";
+    char *rune = NULL;
+    char *host;
+    int opt, daemonize = 1, debug = 0;
+
+    while ((opt = getopt(argc, argv, "hC:s:ed")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("migrate");
+            exit(0);
+        case 'C':
+            config_filename = optarg;
+            break;
+        case 's':
+            ssh_command = optarg;
+            break;
+        case 'e':
+            daemonize = 0;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (argc-optind < 2 || argc-optind > 2) {
+        help("save");
+        exit(2);
+    }
+
+    p = argv[optind];
+    host = argv[optind + 1];
+
+    if (!ssh_command[0]) {
+        rune= host;
+    } else {
+        asprintf(&rune, "exec %s %s xl migrate-receive%s%s",
+                 ssh_command, host,
+                 daemonize ? "" : " -e",
+                 debug ? " -d" : "");
+    }
+
+    migrate_domain(p, rune, config_filename);
+    exit(0);
+}
+
+int main_pause(int argc, char **argv)
+{
+    int opt;
+    char *p;
+    
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pause");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("pause");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    pause_domain(p);
+    exit(0);
+}
+
+int main_unpause(int argc, char **argv)
+{
+    int opt;
+    char *p;
+    
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("unpause");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("unpause");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    unpause_domain(p);
+    exit(0);
+}
+
+int main_destroy(int argc, char **argv)
+{
+    int opt;
+    char *p;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("destroy");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("destroy");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    destroy_domain(p);
+    exit(0);
+}
+
+int main_list(int argc, char **argv)
+{
+    int opt, verbose = 0;
+
+    while ((opt = getopt(argc, argv, "hv")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("list");
+            exit(0);
+        case 'v':
+            verbose = 1;
+            break;
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    list_domains(verbose);
+    exit(0);
+}
+
+int main_list_vm(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("list-vm");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    list_vm();
+    exit(0);
+}
+
+int main_create(int argc, char **argv)
+{
+    char *filename = NULL;
+    int paused = 0, debug = 0, daemonize = 1;
+    int opt, rc;
+
+    while ((opt = getopt(argc, argv, "hdep")) != -1) {
+        switch (opt) {
+        case 'p':
+            paused = 1;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        case 'e':
+            daemonize = 0;
+            break;
+        case 'h':
+            help("create");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (optind >= argc) {
+        help("create");
+        exit(2);
+    }
+
+    filename = argv[optind];
+    rc = create_domain(debug, daemonize, filename, NULL, paused,
+                       -1, 0);
+    exit(-rc);
+}
+
+void button_press(char *p, char *b)
+{
+    libxl_button button;
+
+    find_domain(p);
+
+    if (!strcmp(b, "power")) {
+        button = POWER_BUTTON;
+    } else if (!strcmp(b, "sleep")) {
+        button = SLEEP_BUTTON;
+    } else {
+        fprintf(stderr, "%s is an invalid button identifier\n", b);
+        exit(2);
+    }
+
+    libxl_button_press(&ctx, domid, button);
+}
+
+int main_button_press(int argc, char **argv)
+{
+    int opt;
+    char *p;
+    char *b;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("button-press");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("button-press");
+        exit(2);
+    }
+
+    p = argv[optind];
+    b = argv[optind + 1];
+
+    button_press(p, b);
+    exit(0);
+}
+
+static void print_vcpuinfo(uint32_t tdomid,
+                           const struct libxl_vcpuinfo *vcpuinfo,
+                           uint32_t nr_cpus)
+{
+    int i, l;
+    uint64_t *cpumap;
+    uint64_t pcpumap;
+
+    /*      NAME  ID  VCPU */
+    printf("%-32s %5u %5u",
+           libxl_domid_to_name(&ctx, tdomid), tdomid, vcpuinfo->vcpuid);
+    if (!vcpuinfo->online) {
+        /*      CPU STA */
+        printf("%5c %3c%cp ", '-', '-', '-');
+    } else {
+        /*      CPU STA */
+        printf("%5u %3c%c- ", vcpuinfo->cpu,
+               vcpuinfo->running ? 'r' : '-',
+               vcpuinfo->blocked ? 'b' : '-');
+    }
+    /*      TIM */
+    printf("%9.1f  ", ((float)vcpuinfo->vcpu_time / 1e9));
+    /* CPU AFFINITY */
+    pcpumap = nr_cpus > 64 ? -1 : ((1 << nr_cpus) - 1);
+    for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
+        if (*cpumap < pcpumap) {
+            break;
+        }
+        if (nr_cpus > 64) {
+            pcpumap = -1;
+            nr_cpus -= 64;
+        } else {
+            pcpumap = ((1 << nr_cpus) - 1);
+            nr_cpus = 0;
+        }
+    }
+    if (!nr_cpus) {
+        printf("any cpu\n");
+    } else {
+        for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
+            pcpumap = *cpumap;
+            for (i = 0; !(pcpumap & 1); ++i, pcpumap >>= 1)
+                ;
+            printf("%u", i);
+            for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap 
>>= 1)
+                ;
+            if (l < i) {
+                printf("-%u", i);
+            }
+            for (++i; pcpumap; ++i, pcpumap >>= 1) {
+                if (pcpumap & 1) {
+                    printf(",%u", i);
+                    for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, 
pcpumap >>= 1)
+                        ;
+                    if (l < i) {
+                        printf("-%u", i);
+                    }
+                    ++i;
+                }
+            }
+            printf("\n");
+            nr_cpus = nr_cpus > 64 ? nr_cpus - 64 : 0;
+        }
+    }
+}
+
+void vcpulist(int argc, char **argv)
+{
+    struct libxl_dominfo *dominfo;
+    struct libxl_vcpuinfo *vcpuinfo;
+    struct libxl_physinfo physinfo;
+    int nb_vcpu, nb_domain, cpusize;
+
+    if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
+        fprintf(stderr, "libxl_physinfo failed.\n");
+        goto vcpulist_out;
+    }
+    printf("%-32s %5s %5s %5s %5s %9s %s\n",
+           "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
+    if (!argc) {
+        if (!(dominfo = libxl_list_domain(&ctx, &nb_domain))) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            goto vcpulist_out;
+        }
+        for (; nb_domain > 0; --nb_domain, ++dominfo) {
+            if (!(vcpuinfo = libxl_list_vcpu(&ctx, dominfo->domid, &nb_vcpu, 
&cpusize))) {
+                fprintf(stderr, "libxl_list_vcpu failed.\n");
+                goto vcpulist_out;
+            }
+            for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
+                print_vcpuinfo(dominfo->domid, vcpuinfo, physinfo.nr_cpus);
+            }
+        }
+    } else {
+        for (; argc > 0; ++argv, --argc) {
+            if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
+                fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            }
+            if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, 
&cpusize))) {
+                fprintf(stderr, "libxl_list_vcpu failed.\n");
+                goto vcpulist_out;
+            }
+            for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
+                print_vcpuinfo(domid, vcpuinfo, physinfo.nr_cpus);
+            }
+        }
+    }
+  vcpulist_out:
+    ;
+}
+
+int main_vcpulist(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("vcpu-list");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    vcpulist(argc - 1, argv + 1);
+    exit(0);
+}
+
+void vcpupin(char *d, const char *vcpu, char *cpu)
+{
+    struct libxl_vcpuinfo *vcpuinfo;
+    struct libxl_physinfo physinfo;
+    uint64_t *cpumap = NULL;
+
+    uint32_t vcpuid, cpuida, cpuidb;
+    char *endptr, *toka, *tokb;
+    int i, nb_vcpu, cpusize;
+
+    vcpuid = strtoul(vcpu, &endptr, 10);
+    if (vcpu == endptr) {
+        if (strcmp(vcpu, "all")) {
+            fprintf(stderr, "Error: Invalid argument.\n");
+            return;
+        }
+        vcpuid = -1;
+    }
+
+    find_domain(d);
+
+    if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
+        fprintf(stderr, "libxl_get_physinfo failed.\n");
+        goto vcpupin_out1;
+    }
+
+    cpumap = calloc(physinfo.max_cpu_id + 1, sizeof (uint64_t));
+    if (!cpumap) {
+        goto vcpupin_out1;
+    }
+    if (strcmp(cpu, "all")) {
+        for (toka = strtok(cpu, ","), i = 0; toka; toka = strtok(NULL, ","), 
++i) {
+            cpuida = strtoul(toka, &endptr, 10);
+            if (toka == endptr) {
+                fprintf(stderr, "Error: Invalid argument.\n");
+                goto vcpupin_out;
+            }
+            if (*endptr == '-') {
+                tokb = endptr + 1;
+                cpuidb = strtoul(tokb, &endptr, 10);
+                if ((tokb == endptr) || (cpuida > cpuidb)) {
+                    fprintf(stderr, "Error: Invalid argument.\n");
+                    goto vcpupin_out;
+                }
+                while (cpuida <= cpuidb) {
+                    cpumap[cpuida / 64] |= (1 << (cpuida % 64));
+                    ++cpuida;
+                }
+            } else {
+                cpumap[cpuida / 64] |= (1 << (cpuida % 64));
+            }
+        }
+    }
+    else {
+        memset(cpumap, -1, sizeof (uint64_t) * (physinfo.max_cpu_id + 1));
+    }
+
+    if (vcpuid != -1) {
+        if (libxl_set_vcpuaffinity(&ctx, domid, vcpuid,
+                                   cpumap, physinfo.max_cpu_id + 1) == -1) {
+            fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid);
+        }
+    }
+    else {
+        if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &cpusize))) {
+            fprintf(stderr, "libxl_list_vcpu failed.\n");
+            goto vcpupin_out;
+        }
+        for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
+            if (libxl_set_vcpuaffinity(&ctx, domid, vcpuinfo->vcpuid,
+                                       cpumap, physinfo.max_cpu_id + 1) == -1) 
{
+                fprintf(stderr, "libxl_list_vcpu failed on vcpu `%u'.\n", 
vcpuinfo->vcpuid);
+            }
+        }
+    }
+  vcpupin_out1:
+    free(cpumap);
+  vcpupin_out:
+    ;
+}
+
+int main_vcpupin(int argc, char **argv)
+{
+    int opt;
+
+    if (argc != 4) {
+        help("vcpu-pin");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("vcpu-pin");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    vcpupin(argv[1], argv[2] , argv[3]);
+    exit(0);
+}
+
+void vcpuset(char *d, char* nr_vcpus)
+{
+    char *endptr;
+    unsigned int max_vcpus;
+
+    max_vcpus = strtoul(nr_vcpus, &endptr, 10);
+    if (nr_vcpus == endptr) {
+        fprintf(stderr, "Error: Invalid argument.\n");
+        return;
+    }
+
+    find_domain(d);
+
+    if (libxl_set_vcpucount(&ctx, domid, max_vcpus) == ERROR_INVAL) {
+        fprintf(stderr, "Error: Cannot set vcpus greater than max vcpus on 
running domain or lesser than 1.\n");
+    }
+}
+
+int main_vcpuset(int argc, char **argv)
+{
+    int opt;
+
+    if (argc != 3) {
+        help("vcpu-set");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+        help("vcpu-set");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    vcpuset(argv[1], argv[2]);
+    exit(0);
+}
+
+static void output_xeninfo(void)
+{
+    const libxl_version_info *info;
+    int sched_id;
+
+    info = libxl_get_version_info(&ctx);
+    if ((sched_id = libxl_get_sched_id(&ctx)) < 0) {
+        fprintf(stderr, "get_sched_id sysctl failed.\n");
+        return;
+    }
+
+    printf("xen_major              : %d\n", info->xen_version_major);
+    printf("xen_minor              : %d\n", info->xen_version_minor);
+    printf("xen_extra              : %s\n", info->xen_version_extra);
+    printf("xen_caps               : %s\n", info->capabilities);
+    printf("xen_scheduler          : %s\n",
+        sched_id == XEN_SCHEDULER_SEDF ? "sedf" :
+        sched_id == XEN_SCHEDULER_CREDIT ? "credit" :
+        sched_id == XEN_SCHEDULER_CREDIT2 ? "credit2" : "unknown");
+    printf("xen_pagesize           : %lu\n", info->pagesize);
+    printf("platform_params        : virt_start=0x%lx\n", info->virt_start);
+    printf("xen_changeset          : %s\n", info->changeset);
+    printf("xen_commandline        : %s\n", info->commandline);
+    printf("cc_compiler            : %s\n", info->compiler);
+    printf("cc_compile_by          : %s\n", info->compile_by);
+    printf("cc_compile_domain      : %s\n", info->compile_domain);
+    printf("cc_compile_date        : %s\n", info->compile_date);
+
+    return;
+}
+
+static void output_nodeinfo(void)
+{
+    struct utsname utsbuf;
+
+    uname(&utsbuf);
+
+    printf("host                   : %s\n", utsbuf.nodename);
+    printf("release                : %s\n", utsbuf.release);
+    printf("version                : %s\n", utsbuf.version);
+    printf("machine                : %s\n", utsbuf.machine);
+
+    return;
+}
+
+static void output_physinfo(void)
+{
+    struct libxl_physinfo info;
+    const libxl_version_info *vinfo;
+    unsigned int i;
+
+    if (libxl_get_physinfo(&ctx, &info) != 0) {
+        fprintf(stderr, "libxl_physinfo failed.\n");
+        return;
+    }
+
+    printf("nr_cpus                : %d\n", info.nr_cpus);
+    printf("nr_nodes               : %d\n", info.nr_nodes);
+    printf("cores_per_socket       : %d\n", info.cores_per_socket);
+    printf("threads_per_core       : %d\n", info.threads_per_core);
+    printf("cpu_mhz                : %d\n", info.cpu_khz / 1000);
+    printf("hw_caps                : ");
+    for (i = 0; i < 8; i++)
+        printf("%08x%c", info.hw_cap[i], i < 7 ? ':' : '\n');
+    printf("virt_caps              :");
+    if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm)
+        printf(" hvm");
+    if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm_directio)
+        printf(" hvm_directio");
+    printf("\n");
+    vinfo = libxl_get_version_info(&ctx);
+    i = (1 << 20) / vinfo->pagesize;
+    printf("total_memory           : %lu\n", info.total_pages / i);
+    printf("free_memory            : %lu\n", info.free_pages / i);
+
+    return;
+}
+
+void info(int verbose)
+{
+    output_nodeinfo();
+
+    output_physinfo();
+
+    output_xeninfo();
+
+    printf("xend_config_format     : 4\n");
+
+    return;
+}
+
+int main_info(int argc, char **argv)
+{
+    int opt, verbose;
+
+    verbose = 0;
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("vcpu-list");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    info(verbose);
+    exit(0);
+}
diff -r 9a1d7caa2024 -r d23a0a1823ef tools/libxl/xl_cmdimpl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/xl_cmdimpl.h  Thu Apr 29 22:07:08 2010 +0800
@@ -0,0 +1,38 @@
+/*
+ * Author Yang Hongyang <yanghy@xxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+int main_vcpulist(int argc, char **argv);
+int main_info(int argc, char **argv);
+int main_cd_eject(int argc, char **argv);
+int main_cd_insert(int argc, char **argv);
+int main_console(int argc, char **argv);
+int main_pcilist(int argc, char **argv);
+int main_pcidetach(int argc, char **argv);
+int main_pciattach(int argc, char **argv);
+int main_restore(int argc, char **argv);
+int main_migrate_receive(int argc, char **argv);
+int main_save(int argc, char **argv);
+int main_migrate(int argc, char **argv);
+int main_pause(int argc, char **argv);
+int main_unpause(int argc, char **argv);
+int main_destroy(int argc, char **argv);
+int main_list(int argc, char **argv);
+int main_list_vm(int argc, char **argv);
+int main_create(int argc, char **argv);
+int main_button_press(int argc, char **argv);
+int main_vcpupin(int argc, char **argv);
+int main_vcpuset(int argc, char **argv);
+int main_memset(int argc, char **argv);
+
+void help(char *command);

 
-- 
Regards
Yang Hongyang

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 1/3]xl: Move xl command implementation to a seperate file, Yang Hongyang <=