[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.