]> xenbits.xensource.com Git - xen.git/commitdiff
tools: move xl to a dedicated directory
authorWei Liu <wei.liu2@citrix.com>
Tue, 21 Feb 2017 14:52:46 +0000 (14:52 +0000)
committerWei Liu <wei.liu2@citrix.com>
Thu, 23 Feb 2017 17:29:18 +0000 (17:29 +0000)
It makes clear distinction between the client (xl) and library (libxl),
which should help design better APIs.  This will also help reduce the
code size in libxl directory.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
16 files changed:
.gitignore
tools/Makefile
tools/libxl/Makefile
tools/libxl/bash-completion [deleted file]
tools/libxl/xl.c [deleted file]
tools/libxl/xl.h [deleted file]
tools/libxl/xl_cmdimpl.c [deleted file]
tools/libxl/xl_cmdtable.c [deleted file]
tools/libxl/xl_sxp.c [deleted file]
tools/xl/Makefile [new file with mode: 0644]
tools/xl/bash-completion [new file with mode: 0644]
tools/xl/xl.c [new file with mode: 0644]
tools/xl/xl.h [new file with mode: 0644]
tools/xl/xl_cmdimpl.c [new file with mode: 0644]
tools/xl/xl_cmdtable.c [new file with mode: 0644]
tools/xl/xl_sxp.c [new file with mode: 0644]

index 7182fe80680f8126c6c5b7c1d563050d7052d42d..557b38e1b284ee291c0da6ecf5c0168cdea15d7b 100644 (file)
@@ -190,7 +190,6 @@ tools/libxl/ssdt*
 tools/libxl/testenum
 tools/libxl/testenum.c
 tools/libxl/tmp.*
-tools/libxl/xl
 tools/misc/cpuperf/cpuperf-perfcntr
 tools/misc/cpuperf/cpuperf-xen
 tools/misc/xc_shadow
@@ -381,6 +380,7 @@ tools/firmware/etherboot/ipxe/
 tools/python/xen/lowlevel/xl/_pyxl_types.c
 tools/python/xen/lowlevel/xl/_pyxl_types.h
 tools/xenstore/xenstore-watch
+tools/xl/xl
 
 docs/txt/misc/*.txt
 docs/txt/man/*.txt
index e6c0cc594ab39ed6933fed5cc65d5571694421a0..68633a413d0b6819efe9f75b6cd77a758826be29 100644 (file)
@@ -31,6 +31,7 @@ endif
 
 SUBDIRS-y += xenpmd
 SUBDIRS-y += libxl
+SUBDIRS-y += xl
 SUBDIRS-y += helpers
 SUBDIRS-$(CONFIG_X86) += xenpaging
 SUBDIRS-$(CONFIG_X86) += debugger/gdbsx
index 0f642cc57ab2ec8ce1a178f521cf44ca558ad340..f00d9ef3555e6b1cd79ba3f0939e818ced24d999 100644 (file)
@@ -178,16 +178,9 @@ LIBXLU_OBJS = libxlu_cfg_y.o libxlu_cfg_l.o libxlu_cfg.o \
        libxlu_disk_l.o libxlu_disk.o libxlu_vif.o libxlu_pci.o
 $(LIBXLU_OBJS): CFLAGS += $(CFLAGS_libxenctrl) # For xentoollog.h
 
-CLIENTS = xl testidl libxl-save-helper
+$(TEST_PROG_OBJS) _libxl.api-for-check: CFLAGS += $(CFLAGS_libxentoollog)
 
-CFLAGS_XL += $(CFLAGS_libxenlight)
-CFLAGS_XL += -Wshadow
-
-XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o
-$(XL_OBJS) $(TEST_PROG_OBJS) _libxl.api-for-check: \
-            CFLAGS += $(CFLAGS_libxentoollog)
-$(XL_OBJS): CFLAGS += $(CFLAGS_XL)
-$(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
+CLIENTS = testidl libxl-save-helper
 
 libxl_dom.o: CFLAGS += -I$(XEN_ROOT)/tools  # include libacpi/x86.h
 libxl_x86_acpi.o: CFLAGS += -I$(XEN_ROOT)/tools
@@ -207,7 +200,7 @@ all: $(CLIENTS) $(TEST_PROGS) $(PKG_CONFIG) \
                libxenlight.so libxenlight.a libxlutil.so libxlutil.a \
        $(AUTOSRCS) $(AUTOINCS)
 
-$(LIBXL_OBJS) $(LIBXLU_OBJS) $(XL_OBJS) $(SAVE_HELPER_OBJS) \
+$(LIBXL_OBJS) $(LIBXLU_OBJS) $(SAVE_HELPER_OBJS) \
                $(LIBXL_TEST_OBJS) $(TEST_PROG_OBJS): \
        $(AUTOINCS) libxl.api-ok
 
@@ -249,7 +242,7 @@ libxl_internal_json.h: _libxl_types_internal_json.h
 xl.h: _paths.h
 
 $(LIBXL_OBJS) $(LIBXL_TEST_OBJS) $(LIBXLU_OBJS) \
-       $(XL_OBJS) $(TEST_PROG_OBJS) $(SAVE_HELPER_OBJS): libxl.h
+       $(TEST_PROG_OBJS) $(SAVE_HELPER_OBJS): libxl.h
 $(LIBXL_OBJS) $(LIBXL_TEST_OBJS): libxl_internal.h
 
 _libxl_type%.h _libxl_type%_json.h _libxl_type%_private.h _libxl_type%.c: libxl_type%.idl gentypes.py idl.py
@@ -288,9 +281,6 @@ libxlutil.so.$(XLUMAJOR).$(XLUMINOR): $(LIBXLU_OBJS) libxenlight.so
 libxlutil.a: $(LIBXLU_OBJS)
        $(AR) rcs libxlutil.a $^
 
-xl: $(XL_OBJS) libxlutil.so libxenlight.so
-       $(CC) $(LDFLAGS) -o $@ $(XL_OBJS) $(LDLIBS_libxlutil) $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) -lyajl $(APPEND_LDFLAGS)
-
 test_%: test_%.o test_common.o libxlutil.so libxenlight_test.so
        $(CC) $(LDFLAGS) -o $@ $^ $(filter-out %libxenlight.so, $(LDLIBS_libxenlight)) $(LDLIBS_libxentoollog) -lyajl $(APPEND_LDFLAGS)
 
@@ -306,13 +296,10 @@ $(PKG_CONFIG): % : %.in Makefile
 
 .PHONY: install
 install: all
-       $(INSTALL_DIR) $(DESTDIR)$(sbindir)
        $(INSTALL_DIR) $(DESTDIR)$(libdir)
        $(INSTALL_DIR) $(DESTDIR)$(includedir)
-       $(INSTALL_DIR) $(DESTDIR)$(BASH_COMPLETION_DIR)
        $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
        $(INSTALL_DIR) $(DESTDIR)$(PKG_INSTALLDIR)
-       $(INSTALL_PROG) xl $(DESTDIR)$(sbindir)
        $(INSTALL_PROG) libxl-save-helper $(DESTDIR)$(LIBEXEC_BIN)
        $(INSTALL_SHLIB) libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
        $(SYMLINK_SHLIB) libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenlight.so.$(MAJOR)
@@ -323,7 +310,6 @@ install: all
        $(SYMLINK_SHLIB) libxlutil.so.$(XLUMAJOR) $(DESTDIR)$(libdir)/libxlutil.so
        $(INSTALL_DATA) libxlutil.a $(DESTDIR)$(libdir)
        $(INSTALL_DATA) libxl.h libxl_event.h libxl_json.h _libxl_types.h _libxl_types_json.h _libxl_list.h libxl_utils.h libxl_uuid.h libxlutil.h $(DESTDIR)$(includedir)
-       $(INSTALL_DATA) bash-completion $(DESTDIR)$(BASH_COMPLETION_DIR)/xl.sh
        $(INSTALL_DATA) xenlight.pc $(DESTDIR)$(PKG_INSTALLDIR)
        $(INSTALL_DATA) xlutil.pc $(DESTDIR)$(PKG_INSTALLDIR)
 
diff --git a/tools/libxl/bash-completion b/tools/libxl/bash-completion
deleted file mode 100644 (file)
index b7cd6b3..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copy this file to /etc/bash_completion.d/xl.sh
-
-_xl()
-{
-       local IFS=$'\n,'
-
-       local cur opts xl
-       COMPREPLY=()
-       cur="${COMP_WORDS[COMP_CWORD]}"
-       xl=xl
-
-       if [[ $COMP_CWORD == 1 ]] ; then
-               opts=`${xl} help 2>/dev/null | sed '1,4d' | awk '/^ [^ ]/ {print $1}' | sed 's/$/ ,/g'` && COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
-               return 0
-       fi
-
-       return 0
-}
-
-complete -F _xl -o nospace -o default xl
diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c
deleted file mode 100644 (file)
index a272258..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright (C) 2009      Citrix Ltd.
- * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
- * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
- *
- * 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 <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <inttypes.h>
-#include <regex.h>
-
-#include "libxl.h"
-#include "libxl_utils.h"
-#include "libxlutil.h"
-#include "xl.h"
-
-xentoollog_logger_stdiostream *logger;
-int dryrun_only;
-int force_execution;
-int autoballoon = -1;
-char *blkdev_start;
-int run_hotplug_scripts = 1;
-char *lockfile;
-char *default_vifscript = NULL;
-char *default_bridge = NULL;
-char *default_gatewaydev = NULL;
-char *default_vifbackend = NULL;
-char *default_remus_netbufscript = NULL;
-char *default_colo_proxy_script = NULL;
-enum output_format default_output_format = OUTPUT_FORMAT_JSON;
-int claim_mode = 1;
-bool progress_use_cr = 0;
-
-xentoollog_level minmsglevel = minmsglevel_default;
-
-/* Get autoballoon option based on presence of dom0_mem Xen command
-   line option. */
-static int auto_autoballoon(void)
-{
-    const libxl_version_info *info;
-    regex_t regex;
-    int ret;
-
-    info = libxl_get_version_info(ctx);
-    if (!info)
-        return 1; /* default to on */
-
-    ret = regcomp(&regex,
-                  "(^| )dom0_mem=((|min:|max:)[0-9]+[bBkKmMgG]?,?)+($| )",
-                  REG_NOSUB | REG_EXTENDED);
-    if (ret)
-        return 1;
-
-    ret = regexec(&regex, info->commandline, 0, NULL, 0);
-    regfree(&regex);
-    return ret == REG_NOMATCH;
-}
-
-static void parse_global_config(const char *configfile,
-                              const char *configfile_data,
-                              int configfile_len)
-{
-    long l;
-    XLU_Config *config;
-    int e;
-    const char *buf;
-
-    config = xlu_cfg_init(stderr, configfile);
-    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);
-    }
-
-    if (!xlu_cfg_get_string(config, "autoballoon", &buf, 0)) {
-        if (!strcmp(buf, "on") || !strcmp(buf, "1"))
-            autoballoon = 1;
-        else if (!strcmp(buf, "off") || !strcmp(buf, "0"))
-            autoballoon = 0;
-        else if (!strcmp(buf, "auto"))
-            autoballoon = -1;
-        else
-            fprintf(stderr, "invalid autoballoon option");
-    }
-    if (autoballoon == -1)
-        autoballoon = auto_autoballoon();
-
-    if (!xlu_cfg_get_long (config, "run_hotplug_scripts", &l, 0))
-        run_hotplug_scripts = l;
-
-    if (!xlu_cfg_get_string (config, "lockfile", &buf, 0))
-        lockfile = strdup(buf);
-    else {
-        lockfile = strdup(XL_LOCK_FILE);
-    }
-
-    if (!lockfile) {
-        fprintf(stderr, "failed to allocate lockfile\n");
-        exit(1);
-    }
-
-    /*
-     * For global options that are related to a specific type of device
-     * we use the following nomenclature:
-     *
-     * <device type>.default.<option name>
-     *
-     * This allows us to keep the default options classified for the
-     * different device kinds.
-     */
-
-    if (!xlu_cfg_get_string (config, "vifscript", &buf, 0)) {
-        fprintf(stderr, "the global config option vifscript is deprecated, "
-                        "please switch to vif.default.script\n");
-        free(default_vifscript);
-        default_vifscript = strdup(buf);
-    }
-
-    if (!xlu_cfg_get_string (config, "vif.default.script", &buf, 0)) {
-        free(default_vifscript);
-        default_vifscript = strdup(buf);
-    }
-
-    if (!xlu_cfg_get_string (config, "defaultbridge", &buf, 0)) {
-        fprintf(stderr, "the global config option defaultbridge is deprecated, "
-                        "please switch to vif.default.bridge\n");
-        free(default_bridge);
-        default_bridge = strdup(buf);
-    }
-
-    if (!xlu_cfg_get_string (config, "vif.default.bridge", &buf, 0)) {
-        free(default_bridge);
-        default_bridge = strdup(buf);
-    }
-
-    if (!xlu_cfg_get_string (config, "vif.default.gatewaydev", &buf, 0))
-        default_gatewaydev = strdup(buf);
-
-    if (!xlu_cfg_get_string (config, "vif.default.backend", &buf, 0))
-        default_vifbackend = strdup(buf);
-
-    if (!xlu_cfg_get_string (config, "output_format", &buf, 0)) {
-        if (!strcmp(buf, "json"))
-            default_output_format = OUTPUT_FORMAT_JSON;
-        else if (!strcmp(buf, "sxp"))
-            default_output_format = OUTPUT_FORMAT_SXP;
-        else {
-            fprintf(stderr, "invalid default output format \"%s\"\n", buf);
-        }
-    }
-    if (!xlu_cfg_get_string (config, "blkdev_start", &buf, 0))
-        blkdev_start = strdup(buf);
-
-    if (!xlu_cfg_get_long (config, "claim_mode", &l, 0))
-        claim_mode = l;
-
-    xlu_cfg_replace_string (config, "remus.default.netbufscript",
-        &default_remus_netbufscript, 0);
-    xlu_cfg_replace_string (config, "colo.default.proxyscript",
-        &default_colo_proxy_script, 0);
-
-    xlu_cfg_destroy(config);
-}
-
-void postfork(void)
-{
-    libxl_postfork_child_noexec(ctx); /* in case we don't exit/exec */
-    ctx = 0;
-
-    xl_ctx_alloc();
-}
-
-pid_t xl_fork(xlchildnum child, const char *description) {
-    xlchild *ch = &children[child];
-    int i;
-
-    assert(!ch->pid);
-    ch->reaped = 0;
-    ch->description = description;
-
-    ch->pid = fork();
-    if (ch->pid == -1) {
-        perror("fork failed");
-        exit(-1);
-    }
-
-    if (!ch->pid) {
-        /* We are in the child now.  So all these children are not ours. */
-        for (i=0; i<child_max; i++)
-            children[i].pid = 0;
-    }
-
-    return ch->pid;
-}
-
-pid_t xl_waitpid(xlchildnum child, int *status, int flags)
-{
-    xlchild *ch = &children[child];
-    pid_t got = ch->pid;
-    assert(got);
-    if (ch->reaped) {
-        *status = ch->status;
-        ch->pid = 0;
-        return got;
-    }
-    for (;;) {
-        got = waitpid(ch->pid, status, flags);
-        if (got < 0 && errno == EINTR) continue;
-        if (got > 0) {
-            assert(got == ch->pid);
-            ch->pid = 0;
-        }
-        return got;
-    }
-}
-
-int xl_child_pid(xlchildnum child)
-{
-    xlchild *ch = &children[child];
-    return ch->pid;
-}
-
-void xl_report_child_exitstatus(xentoollog_level level,
-                                xlchildnum child, pid_t pid, int status)
-{
-    libxl_report_child_exitstatus(ctx, level, children[child].description,
-                                  pid, status);
-}
-
-static int xl_reaped_callback(pid_t got, int status, void *user)
-{
-    int i;
-    assert(got);
-    for (i=0; i<child_max; i++) {
-        xlchild *ch = &children[i];
-        if (ch->pid == got) {
-            ch->reaped = 1;
-            ch->status = status;
-            return 0;
-        }
-    }
-    return ERROR_UNKNOWN_CHILD;
-}
-
-static const libxl_childproc_hooks childproc_hooks = {
-    .chldowner = libxl_sigchld_owner_libxl,
-    .reaped_callback = xl_reaped_callback,
-};
-
-void xl_ctx_alloc(void) {
-    if (libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, (xentoollog_logger*)logger)) {
-        fprintf(stderr, "cannot init xl context\n");
-        exit(1);
-    }
-
-    libxl_childproc_setmode(ctx, &childproc_hooks, 0);
-}
-
-static void xl_ctx_free(void)
-{
-    if (ctx) {
-        libxl_ctx_free(ctx);
-        ctx = NULL;
-    }
-    if (logger) {
-        xtl_logger_destroy((xentoollog_logger*)logger);
-        logger = NULL;
-    }
-    if (lockfile) {
-        free(lockfile);
-        lockfile = NULL;
-    }
-}
-
-int main(int argc, char **argv)
-{
-    int opt = 0;
-    char *cmd = 0;
-    struct cmd_spec *cspec;
-    int ret;
-    void *config_data = 0;
-    int config_len = 0;
-
-    while ((opt = getopt(argc, argv, "+vftN")) >= 0) {
-        switch (opt) {
-        case 'v':
-            if (minmsglevel > 0) minmsglevel--;
-            break;
-        case 'N':
-            dryrun_only = 1;
-            break;
-        case 'f':
-            force_execution = 1;
-            break;
-        case 't':
-            progress_use_cr = 1;
-            break;
-        default:
-            fprintf(stderr, "unknown global option\n");
-            exit(EXIT_FAILURE);
-        }
-    }
-
-    cmd = argv[optind];
-
-    if (!cmd) {
-        help(NULL);
-        exit(EXIT_FAILURE);
-    }
-    opterr = 0;
-
-    logger = xtl_createlogger_stdiostream(stderr, minmsglevel,
-        (progress_use_cr ? XTL_STDIOSTREAM_PROGRESS_USE_CR : 0));
-    if (!logger) exit(EXIT_FAILURE);
-
-    atexit(xl_ctx_free);
-
-    xl_ctx_alloc();
-
-    ret = libxl_read_file_contents(ctx, XL_GLOBAL_CONFIG,
-            &config_data, &config_len);
-    if (ret)
-        fprintf(stderr, "Failed to read config file: %s: %s\n",
-                XL_GLOBAL_CONFIG, strerror(errno));
-    parse_global_config(XL_GLOBAL_CONFIG, config_data, config_len);
-    free(config_data);
-
-    /* Reset options for per-command use of getopt. */
-    argv += optind;
-    argc -= optind;
-    optind = 1;
-
-    cspec = cmdtable_lookup(cmd);
-    if (cspec) {
-        if (dryrun_only && !cspec->can_dryrun) {
-            fprintf(stderr, "command does not implement -N (dryrun) option\n");
-            ret = EXIT_FAILURE;
-            goto xit;
-        }
-        ret = cspec->cmd_impl(argc, argv);
-    } else if (!strcmp(cmd, "help")) {
-        help(argv[1]);
-        ret = EXIT_SUCCESS;
-    } else {
-        fprintf(stderr, "command not implemented\n");
-        ret = EXIT_FAILURE;
-    }
-
- xit:
-    return ret;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
deleted file mode 100644 (file)
index 0a8c813..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Author Yang Hongyang <yanghy@cn.fujitsu.com>
- *
- * 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.
- */
-
-#ifndef XL_H
-#define XL_H
-
-#include <assert.h>
-
-#include "_paths.h"
-#include "xentoollog.h"
-
-struct cmd_spec {
-    char *cmd_name;
-    int (*cmd_impl)(int argc, char **argv);
-    int can_dryrun;
-    int modifies;
-    char *cmd_desc;
-    char *cmd_usage;
-    char *cmd_option;
-};
-
-/*
- * The xl process should always return either EXIT_SUCCESS or
- * EXIT_FAILURE. main_* functions, implementing the various xl
- * commands, can be treated as main() as if they are returning
- * a process exit status and not a function return value.
- */
-
-int main_vcpulist(int argc, char **argv);
-int main_info(int argc, char **argv);
-int main_sharing(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_vncviewer(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_pciassignable_add(int argc, char **argv);
-int main_pciassignable_remove(int argc, char **argv);
-int main_pciassignable_list(int argc, char **argv);
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-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);
-#endif
-int main_dump_core(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_shutdown(int argc, char **argv);
-int main_reboot(int argc, char **argv);
-int main_list(int argc, char **argv);
-int main_vm_list(int argc, char **argv);
-int main_create(int argc, char **argv);
-int main_config_update(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_memmax(int argc, char **argv);
-int main_memset(int argc, char **argv);
-int main_sched_credit(int argc, char **argv);
-int main_sched_credit2(int argc, char **argv);
-int main_sched_rtds(int argc, char **argv);
-int main_domid(int argc, char **argv);
-int main_domname(int argc, char **argv);
-int main_rename(int argc, char **argv);
-int main_trigger(int argc, char **argv);
-int main_sysrq(int argc, char **argv);
-int main_debug_keys(int argc, char **argv);
-int main_dmesg(int argc, char **argv);
-int main_top(int argc, char **argv);
-int main_networkattach(int argc, char **argv);
-int main_networklist(int argc, char **argv);
-int main_networkdetach(int argc, char **argv);
-int main_channellist(int argc, char **argv);
-int main_blockattach(int argc, char **argv);
-int main_blocklist(int argc, char **argv);
-int main_blockdetach(int argc, char **argv);
-int main_vtpmattach(int argc, char **argv);
-int main_vtpmlist(int argc, char **argv);
-int main_vtpmdetach(int argc, char **argv);
-int main_usbctrl_attach(int argc, char **argv);
-int main_usbctrl_detach(int argc, char **argv);
-int main_usbdev_attach(int argc, char **argv);
-int main_usbdev_detach(int argc, char **argv);
-int main_usblist(int argc, char **argv);
-int main_uptime(int argc, char **argv);
-int main_claims(int argc, char **argv);
-int main_tmem_list(int argc, char **argv);
-int main_tmem_freeze(int argc, char **argv);
-int main_tmem_thaw(int argc, char **argv);
-int main_tmem_set(int argc, char **argv);
-int main_tmem_shared_auth(int argc, char **argv);
-int main_tmem_freeable(int argc, char **argv);
-int main_network2attach(int argc, char **argv);
-int main_network2list(int argc, char **argv);
-int main_network2detach(int argc, char **argv);
-int main_cpupoolcreate(int argc, char **argv);
-int main_cpupoollist(int argc, char **argv);
-int main_cpupooldestroy(int argc, char **argv);
-int main_cpupoolrename(int argc, char **argv);
-int main_cpupoolcpuadd(int argc, char **argv);
-int main_cpupoolcpuremove(int argc, char **argv);
-int main_cpupoolmigrate(int argc, char **argv);
-int main_cpupoolnumasplit(int argc, char **argv);
-int main_getenforce(int argc, char **argv);
-int main_setenforce(int argc, char **argv);
-int main_loadpolicy(int argc, char **argv);
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-int main_remus(int argc, char **argv);
-#endif
-int main_devd(int argc, char **argv);
-#ifdef LIBXL_HAVE_PSR_CMT
-int main_psr_hwinfo(int argc, char **argv);
-int main_psr_cmt_attach(int argc, char **argv);
-int main_psr_cmt_detach(int argc, char **argv);
-int main_psr_cmt_show(int argc, char **argv);
-#endif
-#ifdef LIBXL_HAVE_PSR_CAT
-int main_psr_cat_cbm_set(int argc, char **argv);
-int main_psr_cat_show(int argc, char **argv);
-#endif
-int main_qemu_monitor_command(int argc, char **argv);
-
-void help(const char *command);
-
-extern struct cmd_spec cmd_table[];
-extern int cmdtable_len;
-/* Look up a command in the table, allowing unambiguous truncation */
-struct cmd_spec *cmdtable_lookup(const char *s);
-
-extern libxl_ctx *ctx;
-extern xentoollog_logger_stdiostream *logger;
-
-void xl_ctx_alloc(void);
-
-/* child processes */
-
-typedef struct {
-    /* every struct like this must be in XLCHILD_LIST */
-    pid_t pid; /* 0: not in use */
-    int reaped; /* valid iff pid!=0 */
-    int status; /* valid iff reaped */
-    const char *description; /* valid iff pid!=0 */
-} xlchild;
-
-typedef enum {
-    child_console, child_waitdaemon, child_migration, child_vncviewer,
-    child_max
-} xlchildnum;
-
-extern xlchild children[child_max];
-
-pid_t xl_fork(xlchildnum, const char *description);
-    /* like fork, but prints and dies if it fails */
-void postfork(void); /* needed only if we aren't going to exec right away */
-
-/* Handles EINTR.  Clears out the xlchild so it can be reused. */
-pid_t xl_waitpid(xlchildnum, int *status, int flags);
-
-int xl_child_pid(xlchildnum); /* returns 0 if child struct is not in use */
-
-void xl_report_child_exitstatus(xentoollog_level level,
-                                xlchildnum child, pid_t pid, int status);
-    /* like libxl_report_child_exitstatus, but uses children[].description */
-
-int child_report(xlchildnum child);
-    /* waits and expects child to exit status 0.
-     * otherwise, logs and returns ERROR_FAIL */
-
-/* global options */
-extern int autoballoon;
-extern int run_hotplug_scripts;
-extern int dryrun_only;
-extern int claim_mode;
-extern bool progress_use_cr;
-extern xentoollog_level minmsglevel;
-#define minmsglevel_default XTL_PROGRESS
-extern char *lockfile;
-extern char *default_vifscript;
-extern char *default_bridge;
-extern char *default_gatewaydev;
-extern char *default_vifbackend;
-extern char *default_remus_netbufscript;
-extern char *default_colo_proxy_script;
-extern char *blkdev_start;
-
-enum output_format {
-    OUTPUT_FORMAT_JSON,
-    OUTPUT_FORMAT_SXP,
-};
-extern enum output_format default_output_format;
-
-typedef enum {
-    DOMAIN_RESTART_NONE = 0,     /* No domain restart */
-    DOMAIN_RESTART_NORMAL,       /* Domain should be restarted */
-    DOMAIN_RESTART_RENAME,       /* Domain should be renamed and restarted */
-    DOMAIN_RESTART_SOFT_RESET,   /* Soft reset should be performed */
-} domain_restart_type;
-
-extern void printf_info_sexp(int domid, libxl_domain_config *d_config, FILE *fh);
-
-#define XL_GLOBAL_CONFIG XEN_CONFIG_DIR "/xl.conf"
-#define XL_LOCK_FILE XEN_LOCK_DIR "/xl"
-
-#endif /* XL_H */
-
-/*
- * Local variables:
- * mode: C
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
deleted file mode 100644 (file)
index 0add5dc..0000000
+++ /dev/null
@@ -1,9642 +0,0 @@
-/*
- * Copyright (C) 2009      Citrix Ltd.
- * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
- * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
- *
- * 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 <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <time.h>
-#include <getopt.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/utsname.h> /* for utsname in xl info */
-#include <xentoollog.h>
-#include <ctype.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <xen/hvm/e820.h>
-
-#include "libxl.h"
-#include "libxl_utils.h"
-#include "libxl_json.h"
-#include "libxlutil.h"
-#include "xl.h"
-
-/* For calls which return an errno on failure */
-#define CHK_ERRNOVAL( call ) ({                                         \
-        int chk_errnoval = (call);                                      \
-        if (chk_errnoval < 0)                                           \
-            abort();                                                    \
-        else if (chk_errnoval > 0) {                                    \
-            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
-                    __FILE__,__LINE__, strerror(chk_errnoval), #call);  \
-            exit(EXIT_FAILURE);                                         \
-        }                                                               \
-    })
-
-/* For calls which return -1 and set errno on failure */
-#define CHK_SYSCALL( call ) ({                                          \
-        if ((call) == -1) {                                             \
-            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
-                    __FILE__,__LINE__, strerror(errno), #call);         \
-            exit(EXIT_FAILURE);                                         \
-        }                                                               \
-    })
-
-#define MUST( call ) ({                                                 \
-        int must_rc = (call);                                           \
-        if (must_rc < 0) {                                                  \
-            fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
-                    __FILE__,__LINE__, must_rc, #call);                 \
-            exit(EXIT_FAILURE);                                         \
-        }                                                               \
-    })
-
-#define STR_HAS_PREFIX( a, b )  \
-    ( strncmp(a, b, strlen(b)) == 0 )
-#define STR_SKIP_PREFIX( a, b ) \
-    ( STR_HAS_PREFIX(a, b) ? ((a) += strlen(b), 1) : 0 )
-
-
-int logfile = 2;
-
-/* every libxl action in xl uses this same libxl context */
-libxl_ctx *ctx;
-
-xlchild children[child_max];
-
-#define INVALID_DOMID ~0
-static const char *common_domname;
-static int fd_lock = -1;
-
-static const char savefileheader_magic[32]=
-    "Xen saved domain, xl format\n \0 \r";
-
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-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";
-#endif
-
-  /* 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
-   */
-
-#define XL_MANDATORY_FLAG_JSON (1U << 0) /* config data is in JSON format */
-#define XL_MANDATORY_FLAG_STREAMv2 (1U << 1) /* stream is v2 */
-#define XL_MANDATORY_FLAG_ALL  (XL_MANDATORY_FLAG_JSON |        \
-                                XL_MANDATORY_FLAG_STREAMv2)
-
-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 */
-};
-
-
-static const char *action_on_shutdown_names[] = {
-    [LIBXL_ACTION_ON_SHUTDOWN_DESTROY] = "destroy",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_RESTART] = "restart",
-    [LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME] = "rename-restart",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_PRESERVE] = "preserve",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY] = "coredump-destroy",
-    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART] = "coredump-restart",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET] = "soft-reset",
-};
-
-/* 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)
-
-struct domain_create {
-    int debug;
-    int daemonize;
-    int monitor; /* handle guest reboots etc */
-    int paused;
-    int dryrun;
-    int quiet;
-    int vnc;
-    int vncautopass;
-    int console_autoconnect;
-    int checkpointed_stream;
-    const char *config_file;
-    char *extra_config; /* extra config string */
-    const char *restore_file;
-    char *colo_proxy_script;
-    int migrate_fd; /* -1 means none */
-    int send_back_fd; /* -1 means none */
-    char **migration_domname_r; /* from malloc */
-};
-
-
-static uint32_t find_domain(const char *p) __attribute__((warn_unused_result));
-static uint32_t find_domain(const char *p)
-{
-    uint32_t domid;
-    int rc;
-
-    rc = libxl_domain_qualifier_to_domid(ctx, p, &domid);
-    if (rc) {
-        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
-        exit(EXIT_FAILURE);
-    }
-    common_domname = libxl_domid_to_name(ctx, domid);
-    return domid;
-}
-
-int child_report(xlchildnum child)
-{
-    int status;
-    pid_t got = xl_waitpid(child, &status, 0);
-    if (got < 0) {
-        fprintf(stderr, "xl: warning, failed to waitpid for %s: %s\n",
-                children[child].description, strerror(errno));
-        return ERROR_FAIL;
-    } else if (status) {
-        xl_report_child_exitstatus(XTL_ERROR, child, got, status);
-        return ERROR_FAIL;
-    } else {
-        return 0;
-    }
-}
-
-static void console_child_report(xlchildnum child)
-{
-    if (xl_child_pid(child))
-        child_report(child);
-}
-
-static int vncviewer(uint32_t domid, int autopass)
-{
-    libxl_vncviewer_exec(ctx, domid, autopass);
-    fprintf(stderr, "Unable to execute vncviewer\n");
-    return 1;
-}
-
-static void autoconnect_vncviewer(uint32_t domid, int autopass)
-{
-   console_child_report(child_vncviewer);
-
-    pid_t pid = xl_fork(child_vncviewer, "vncviewer child");
-    if (pid)
-        return;
-
-    postfork();
-
-    sleep(1);
-    vncviewer(domid, autopass);
-    _exit(EXIT_FAILURE);
-}
-
-static int acquire_lock(void)
-{
-    int rc;
-    struct flock fl;
-
-    /* lock already acquired */
-    if (fd_lock >= 0)
-        return ERROR_INVAL;
-
-    fl.l_type = F_WRLCK;
-    fl.l_whence = SEEK_SET;
-    fl.l_start = 0;
-    fl.l_len = 0;
-    fd_lock = open(lockfile, O_WRONLY|O_CREAT, S_IWUSR);
-    if (fd_lock < 0) {
-        fprintf(stderr, "cannot open the lockfile %s errno=%d\n", lockfile, errno);
-        return ERROR_FAIL;
-    }
-    if (fcntl(fd_lock, F_SETFD, FD_CLOEXEC) < 0) {
-        close(fd_lock);
-        fprintf(stderr, "cannot set cloexec to lockfile %s errno=%d\n", lockfile, errno);
-        return ERROR_FAIL;
-    }
-get_lock:
-    rc = fcntl(fd_lock, F_SETLKW, &fl);
-    if (rc < 0 && errno == EINTR)
-        goto get_lock;
-    if (rc < 0) {
-        fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
-        rc = ERROR_FAIL;
-    } else
-        rc = 0;
-    return rc;
-}
-
-static int release_lock(void)
-{
-    int rc;
-    struct flock fl;
-
-    /* lock not acquired */
-    if (fd_lock < 0)
-        return ERROR_INVAL;
-
-release_lock:
-    fl.l_type = F_UNLCK;
-    fl.l_whence = SEEK_SET;
-    fl.l_start = 0;
-    fl.l_len = 0;
-
-    rc = fcntl(fd_lock, F_SETLKW, &fl);
-    if (rc < 0 && errno == EINTR)
-        goto release_lock;
-    if (rc < 0) {
-        fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
-        rc = ERROR_FAIL;
-    } else
-        rc = 0;
-    close(fd_lock);
-    fd_lock = -1;
-
-    return 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 *xcalloc(size_t n, size_t sz) __attribute__((unused));
-static void *xcalloc(size_t n, size_t sz) {
-    void *r = calloc(n, sz);
-    if (!r) {
-        fprintf(stderr,"xl: Unable to calloc %zu bytes.\n", sz*n);
-        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 char *xstrdup(const char *x)
-{
-    char *r;
-    r = strdup(x);
-    if (!r) {
-        fprintf(stderr, "xl: Unable to strdup a string of length %zu.\n",
-                strlen(x));
-        exit(-ERROR_FAIL);
-    }
-    return r;
-}
-
-#define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
-    ({                                                                  \
-        typeof((count)) array_extend_old_count = (count);               \
-        (count)++;                                                      \
-        (array) = xrealloc((array), sizeof(*array) * (count));          \
-        (initfn)(&(array)[array_extend_old_count]);                     \
-        more;                                                           \
-        &(array)[array_extend_old_count];                               \
-    })
-
-#define ARRAY_EXTEND_INIT(array,count,initfn)                           \
-    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), ({                \
-        (array)[array_extend_old_count].devid = array_extend_old_count; \
-        }))
-
-#define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
-    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
-
-#define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
-
-static void dolog(const char *file, int line, const char *func, char *fmt, ...)
-     __attribute__((format(printf,4,5)));
-
-static void dolog(const char *file, int line, const char *func, char *fmt, ...)
-{
-    va_list ap;
-    char *s = NULL;
-    int rc;
-
-    va_start(ap, fmt);
-    rc = vasprintf(&s, fmt, ap);
-    va_end(ap);
-    if (rc >= 0)
-        /* we ignore write errors since we have no way to report them;
-         * the alternative would be to abort the whole program */
-        libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
-    free(s);
-}
-
-static void xvasprintf(char **strp, const char *fmt, va_list ap)
-    __attribute__((format(printf,2,0)));
-static void xvasprintf(char **strp, const char *fmt, va_list ap)
-{
-    int r = vasprintf(strp, fmt, ap);
-    if (r == -1) {
-        perror("asprintf failed");
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void xasprintf(char **strp, const char *fmt, ...)
-    __attribute__((format(printf,2,3)));
-static void xasprintf(char **strp, const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    xvasprintf(strp, fmt, ap);
-    va_end(ap);
-}
-
-static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
-                                            libxl_domain_config *d_config)
-{
-    yajl_gen_status s;
-
-    s = yajl_gen_map_open(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"domid",
-                        sizeof("domid")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    if (domid != -1)
-        s = yajl_gen_integer(hand, domid);
-    else
-        s = yajl_gen_null(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"config",
-                        sizeof("config")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    s = libxl_domain_config_gen_json(hand, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_map_close(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-out:
-    return s;
-}
-
-static void flush_stream(FILE *fh)
-{
-    const char *fh_name =
-        fh == stdout ? "stdout" :
-        fh == stderr ? "stderr" :
-        (abort(), (const char*)0);
-
-    if (ferror(fh) || fflush(fh)) {
-        perror(fh_name);
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void printf_info(enum output_format output_format,
-                        int domid,
-                        libxl_domain_config *d_config, FILE *fh)
-{
-    if (output_format == OUTPUT_FORMAT_SXP)
-        return printf_info_sexp(domid, d_config, fh);
-
-    const char *buf;
-    libxl_yajl_length len = 0;
-    yajl_gen_status s;
-    yajl_gen hand;
-
-    hand = libxl_yajl_gen_alloc(NULL);
-    if (!hand) {
-        fprintf(stderr, "unable to allocate JSON generator\n");
-        return;
-    }
-
-    s = printf_info_one_json(hand, domid, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    fputs(buf, fh);
-
-out:
-    yajl_gen_free(hand);
-
-    if (s != yajl_gen_status_ok)
-        fprintf(stderr,
-                "unable to format domain config as JSON (YAJL:%d)\n", s);
-
-    flush_stream(fh);
-}
-
-static int do_daemonize(char *name, const char *pidfile)
-{
-    char *fullname;
-    pid_t child1;
-    int nullfd, ret = 0;
-
-    child1 = xl_fork(child_waitdaemon, "domain monitoring daemonizing child");
-    if (child1) {
-        ret = child_report(child_waitdaemon);
-        if (ret) goto out;
-        ret = 1;
-        goto out;
-    }
-
-    postfork();
-
-    ret = libxl_create_logfile(ctx, name, &fullname);
-    if (ret) {
-        LOG("failed to open logfile %s: %s",fullname,strerror(errno));
-        exit(-1);
-    }
-
-    CHK_SYSCALL(logfile = open(fullname, O_WRONLY|O_CREAT|O_APPEND, 0644));
-    free(fullname);
-    assert(logfile >= 3);
-
-    CHK_SYSCALL(nullfd = open("/dev/null", O_RDONLY));
-    assert(nullfd >= 3);
-
-    dup2(nullfd, 0);
-    dup2(logfile, 1);
-    dup2(logfile, 2);
-
-    close(nullfd);
-
-    CHK_SYSCALL(daemon(0, 1));
-
-    if (pidfile) {
-        int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
-        char *pid = NULL;
-
-        if (fd == -1) {
-            perror("Unable to open pidfile");
-            exit(1);
-        }
-
-        if (asprintf(&pid, "%ld\n", (long)getpid()) == -1) {
-            perror("Formatting pid");
-            exit(1);
-        }
-
-        if (write(fd, pid, strlen(pid)) < 0) {
-            perror("Writing pid");
-            exit(1);
-        }
-
-        if (close(fd) < 0) {
-            perror("Closing pidfile");
-            exit(1);
-        }
-
-        free(pid);
-    }
-
-out:
-    return ret;
-}
-
-static int parse_action_on_shutdown(const char *buf, libxl_action_on_shutdown *a)
-{
-    int i;
-    const char *n;
-
-    for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
-        n = action_on_shutdown_names[i];
-
-        if (!n) continue;
-
-        if (strcmp(buf, n) == 0) {
-            *a = i;
-            return 1;
-        }
-    }
-    return 0;
-}
-
-#define DSTATE_INITIAL   0
-#define DSTATE_TAP       1
-#define DSTATE_PHYSPATH  2
-#define DSTATE_VIRTPATH  3
-#define DSTATE_VIRTTYPE  4
-#define DSTATE_RW        5
-#define DSTATE_TERMINAL  6
-
-static void parse_disk_config_multistring(XLU_Config **config,
-                                          int nspecs, const char *const *specs,
-                                          libxl_device_disk *disk)
-{
-    int e;
-
-    libxl_device_disk_init(disk);
-
-    if (!*config) {
-        *config = xlu_cfg_init(stderr, "command line");
-        if (!*config) { perror("xlu_cfg_init"); exit(-1); }
-    }
-
-    e = xlu_disk_parse(*config, nspecs, specs, disk);
-    if (e == EINVAL) exit(EXIT_FAILURE);
-    if (e) {
-        fprintf(stderr,"xlu_disk_parse failed: %s\n",strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void parse_disk_config(XLU_Config **config, const char *spec,
-                              libxl_device_disk *disk)
-{
-    parse_disk_config_multistring(config, 1, &spec, disk);
-}
-
-static void parse_vif_rate(XLU_Config **config, const char *rate,
-                           libxl_device_nic *nic)
-{
-    int e;
-
-    e = xlu_vif_parse_rate(*config, rate, nic);
-    if (e == EINVAL || e == EOVERFLOW) exit(EXIT_FAILURE);
-    if (e) {
-        fprintf(stderr,"xlu_vif_parse_rate failed: %s\n",strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void set_default_nic_values(libxl_device_nic *nic)
-{
-
-    if (default_vifscript) {
-        free(nic->script);
-        nic->script = strdup(default_vifscript);
-    }
-
-    if (default_bridge) {
-        free(nic->bridge);
-        nic->bridge = strdup(default_bridge);
-    }
-
-    if (default_gatewaydev) {
-        free(nic->gatewaydev);
-        nic->gatewaydev = strdup(default_gatewaydev);
-    }
-
-    if (default_vifbackend) {
-        free(nic->backend_domname);
-        nic->backend_domname = strdup(default_vifbackend);
-    }
-}
-
-static void split_string_into_string_list(const char *str,
-                                          const char *delim,
-                                          libxl_string_list *psl)
-{
-    char *s, *saveptr;
-    const char *p;
-    libxl_string_list sl;
-
-    int i = 0, nr = 0;
-
-    s = strdup(str);
-    if (s == NULL) {
-        fprintf(stderr, "unable to allocate memory to split string\n");
-        exit(-1);
-    }
-
-    /* Count number of entries */
-    p = strtok_r(s, delim, &saveptr);
-    do {
-        nr++;
-    } while ((p = strtok_r(NULL, delim, &saveptr)));
-
-    free(s);
-
-    s = strdup(str);
-
-    sl = malloc((nr+1) * sizeof (char *));
-    if (sl == NULL) {
-        fprintf(stderr, "unable to allocate memory to split string\n");
-        exit(-1);
-    }
-
-    p = strtok_r(s, delim, &saveptr);
-    do {
-        assert(i < nr);
-        sl[i] = strdup(p);
-        i++;
-    } while ((p = strtok_r(NULL, delim, &saveptr)));
-    sl[i] = NULL;
-
-    *psl = sl;
-
-    free(s);
-}
-
-/* NB: this follows the interface used by <ctype.h>. See 'man 3 ctype'
-   and look for CTYPE in libxl_internal.h */
-typedef int (*char_predicate_t)(const int c);
-
-static void trim(char_predicate_t predicate, const char *input, char **output)
-{
-    const char *first, *after;
-
-    for (first = input;
-         *first && predicate((unsigned char)first[0]);
-         first++)
-        ;
-
-    for (after = first + strlen(first);
-         after > first && predicate((unsigned char)after[-1]);
-         after--)
-        ;
-
-    size_t len_nonnull = after - first;
-    char *result = xmalloc(len_nonnull + 1);
-
-    memcpy(result, first, len_nonnull);
-    result[len_nonnull] = 0;
-
-    *output = result;
-}
-
-static int split_string_into_pair(const char *str,
-                                  const char *delim,
-                                  char **a,
-                                  char **b)
-{
-    char *s, *p, *saveptr, *aa = NULL, *bb = NULL;
-    int rc = 0;
-
-    s = xstrdup(str);
-
-    p = strtok_r(s, delim, &saveptr);
-    if (p == NULL) {
-        rc = ERROR_INVAL;
-        goto out;
-    }
-    aa = xstrdup(p);
-    p = strtok_r(NULL, delim, &saveptr);
-    if (p == NULL) {
-        rc = ERROR_INVAL;
-        goto out;
-    }
-    bb = xstrdup(p);
-
-    *a = aa;
-    aa = NULL;
-    *b = bb;
-    bb = NULL;
-out:
-    free(s);
-    free(aa);
-    free(bb);
-    return rc;
-}
-
-static int parse_range(const char *str, unsigned long *a, unsigned long *b)
-{
-    const char *nstr;
-    char *endptr;
-
-    *a = *b = strtoul(str, &endptr, 10);
-    if (endptr == str || *a == ULONG_MAX)
-        return 1;
-
-    if (*endptr == '-') {
-        nstr = endptr + 1;
-
-        *b = strtoul(nstr, &endptr, 10);
-        if (endptr == nstr || *b == ULONG_MAX || *b < *a)
-            return 1;
-    }
-
-    /* Valid value or range so far, but we also don't want junk after that */
-    if (*endptr != '\0')
-        return 1;
-
-    return 0;
-}
-
-/*
- * Add or removes a specific set of cpus (specified in str, either as
- * single cpus or as entire NUMA nodes) to/from cpumap.
- */
-static int update_cpumap_range(const char *str, libxl_bitmap *cpumap)
-{
-    unsigned long ida, idb;
-    libxl_bitmap node_cpumap;
-    bool is_not = false, is_nodes = false;
-    int rc = 0;
-
-    libxl_bitmap_init(&node_cpumap);
-
-    rc = libxl_node_bitmap_alloc(ctx, &node_cpumap, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
-        goto out;
-    }
-
-    /* Are we adding or removing cpus/nodes? */
-    if (STR_SKIP_PREFIX(str, "^")) {
-        is_not = true;
-    }
-
-    /* Are we dealing with cpus or full nodes? */
-    if (STR_SKIP_PREFIX(str, "node:") || STR_SKIP_PREFIX(str, "nodes:")) {
-        is_nodes = true;
-    }
-
-    if (strcmp(str, "all") == 0) {
-        /* We do not accept "^all" or "^nodes:all" */
-        if (is_not) {
-            fprintf(stderr, "Can't combine \"^\" and \"all\".\n");
-            rc = ERROR_INVAL;
-        } else
-            libxl_bitmap_set_any(cpumap);
-        goto out;
-    }
-
-    rc = parse_range(str, &ida, &idb);
-    if (rc) {
-        fprintf(stderr, "Invalid pcpu range: %s.\n", str);
-        goto out;
-    }
-
-    /* Add or remove the specified cpus in the range */
-    while (ida <= idb) {
-        if (is_nodes) {
-            /* Add/Remove all the cpus of a NUMA node */
-            int i;
-
-            rc = libxl_node_to_cpumap(ctx, ida, &node_cpumap);
-            if (rc) {
-                fprintf(stderr, "libxl_node_to_cpumap failed.\n");
-                goto out;
-            }
-
-            /* Add/Remove all the cpus in the node cpumap */
-            libxl_for_each_set_bit(i, node_cpumap) {
-                is_not ? libxl_bitmap_reset(cpumap, i) :
-                         libxl_bitmap_set(cpumap, i);
-            }
-        } else {
-            /* Add/Remove this cpu */
-            is_not ? libxl_bitmap_reset(cpumap, ida) :
-                     libxl_bitmap_set(cpumap, ida);
-        }
-        ida++;
-    }
-
- out:
-    libxl_bitmap_dispose(&node_cpumap);
-    return rc;
-}
-
-/*
- * Takes a string representing a set of cpus (specified either as
- * single cpus or as eintire NUMA nodes) and turns it into the
- * corresponding libxl_bitmap (in cpumap).
- */
-static int cpurange_parse(const char *cpu, libxl_bitmap *cpumap)
-{
-    char *ptr, *saveptr = NULL, *buf = xstrdup(cpu);
-    int rc = 0;
-
-    for (ptr = strtok_r(buf, ",", &saveptr); ptr;
-         ptr = strtok_r(NULL, ",", &saveptr)) {
-        rc = update_cpumap_range(ptr, cpumap);
-        if (rc)
-            break;
-    }
-    free(buf);
-
-    return rc;
-}
-
-static void parse_top_level_vnc_options(XLU_Config *config,
-                                        libxl_vnc_info *vnc)
-{
-    long l;
-
-    xlu_cfg_get_defbool(config, "vnc", &vnc->enable, 0);
-    xlu_cfg_replace_string (config, "vnclisten", &vnc->listen, 0);
-    xlu_cfg_replace_string (config, "vncpasswd", &vnc->passwd, 0);
-    if (!xlu_cfg_get_long (config, "vncdisplay", &l, 0))
-        vnc->display = l;
-    xlu_cfg_get_defbool(config, "vncunused", &vnc->findunused, 0);
-}
-
-static void parse_top_level_sdl_options(XLU_Config *config,
-                                        libxl_sdl_info *sdl)
-{
-    xlu_cfg_get_defbool(config, "sdl", &sdl->enable, 0);
-    xlu_cfg_get_defbool(config, "opengl", &sdl->opengl, 0);
-    xlu_cfg_replace_string (config, "display", &sdl->display, 0);
-    xlu_cfg_replace_string (config, "xauthority", &sdl->xauthority, 0);
-}
-
-static char *parse_cmdline(XLU_Config *config)
-{
-    char *cmdline = NULL;
-    const char *root = NULL, *extra = NULL, *buf = NULL;
-
-    xlu_cfg_get_string (config, "cmdline", &buf, 0);
-    xlu_cfg_get_string (config, "root", &root, 0);
-    xlu_cfg_get_string (config, "extra", &extra, 0);
-
-    if (buf) {
-        cmdline = strdup(buf);
-        if (root || extra)
-            fprintf(stderr, "Warning: ignoring root= and extra= "
-                    "in favour of cmdline=\n");
-    } else {
-        if (root && extra) {
-            xasprintf(&cmdline, "root=%s %s", root, extra);
-        } else if (root) {
-            xasprintf(&cmdline, "root=%s", root);
-        } else if (extra) {
-            cmdline = strdup(extra);
-        }
-    }
-
-    if ((buf || root || extra) && !cmdline) {
-        fprintf(stderr, "Failed to allocate memory for cmdline\n");
-        exit(EXIT_FAILURE);
-    }
-
-    return cmdline;
-}
-
-static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
-                                XLU_ConfigList *cpus, const char *buf,
-                                int num_cpus, bool is_hard)
-{
-    libxl_bitmap *vcpu_affinity_array;
-
-    /*
-     * If we are here, and buf is !NULL, we're dealing with a string. What
-     * we do in this case is parse it, and copy the result in _all_ (up to
-     * b_info->max_vcpus) the elements of the vcpu affinity array.
-     *
-     * If buf is NULL, we have a list, and what we do is putting in the
-     * i-eth element of the vcpu affinity array the result of the parsing
-     * of the i-eth entry of the list. If there are more vcpus than
-     * entries, it is fine to just not touch the last array elements.
-     */
-
-    /* Silently ignore values corresponding to non existing vcpus */
-    if (buf || num_cpus > b_info->max_vcpus)
-        num_cpus = b_info->max_vcpus;
-
-    if (is_hard) {
-        b_info->num_vcpu_hard_affinity = num_cpus;
-        b_info->vcpu_hard_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
-        vcpu_affinity_array = b_info->vcpu_hard_affinity;
-    } else {
-        b_info->num_vcpu_soft_affinity = num_cpus;
-        b_info->vcpu_soft_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
-        vcpu_affinity_array = b_info->vcpu_soft_affinity;
-    }
-
-    if (!buf) {
-        int j = 0;
-
-        while ((buf = xlu_cfg_get_listitem(cpus, j)) != NULL && j < num_cpus) {
-            libxl_bitmap_init(&vcpu_affinity_array[j]);
-            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[j], 0)) {
-                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", j);
-                exit(EXIT_FAILURE);
-            }
-
-            if (cpurange_parse(buf, &vcpu_affinity_array[j]))
-                exit(EXIT_FAILURE);
-
-            j++;
-        }
-
-        /* We have a list of cpumaps, disable automatic placement */
-        libxl_defbool_set(&b_info->numa_placement, false);
-    } else {
-        int i;
-
-        libxl_bitmap_init(&vcpu_affinity_array[0]);
-        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[0], 0)) {
-            fprintf(stderr, "Unable to allocate cpumap for vcpu 0\n");
-            exit(EXIT_FAILURE);
-        }
-
-        if (cpurange_parse(buf, &vcpu_affinity_array[0]))
-            exit(EXIT_FAILURE);
-
-        for (i = 1; i < b_info->max_vcpus; i++) {
-            libxl_bitmap_init(&vcpu_affinity_array[i]);
-            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[i], 0)) {
-                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", i);
-                exit(EXIT_FAILURE);
-            }
-            libxl_bitmap_copy(ctx, &vcpu_affinity_array[i],
-                              &vcpu_affinity_array[0]);
-        }
-
-        libxl_defbool_set(&b_info->numa_placement, false);
-    }
-}
-
-static unsigned long parse_ulong(const char *str)
-{
-    char *endptr;
-    unsigned long val;
-
-    val = strtoul(str, &endptr, 10);
-    if (endptr == str || val == ULONG_MAX) {
-        fprintf(stderr, "xl: failed to convert \"%s\" to number\n", str);
-        exit(EXIT_FAILURE);
-    }
-    return val;
-}
-
-static void replace_string(char **str, const char *val)
-{
-    free(*str);
-    *str = xstrdup(val);
-}
-
-static int match_option_size(const char *prefix, size_t len,
-        char *arg, char **argopt)
-{
-    int rc = strncmp(prefix, arg, len);
-    if (!rc) *argopt = arg+len;
-    return !rc;
-}
-#define MATCH_OPTION(prefix, arg, oparg) \
-    match_option_size((prefix "="), sizeof((prefix)), (arg), &(oparg))
-
-/* Parses network data and adds info into nic
- * Returns 1 if the input token does not match one of the keys
- * or parsed values are not correct. Successful parse returns 0 */
-static int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
-{
-    char *endptr, *oparg;
-    int i;
-    unsigned int val;
-
-    if (MATCH_OPTION("type", token, oparg)) {
-        if (!strcmp("vif", oparg)) {
-            nic->nictype = LIBXL_NIC_TYPE_VIF;
-        } else if (!strcmp("ioemu", oparg)) {
-            nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
-        } else {
-            fprintf(stderr, "Invalid parameter `type'.\n");
-            return 1;
-        }
-    } else if (MATCH_OPTION("mac", token, oparg)) {
-        for (i = 0; i < 6; i++) {
-            val = strtoul(oparg, &endptr, 16);
-            if ((oparg == endptr) || (val > 255)) {
-                fprintf(stderr, "Invalid parameter `mac'.\n");
-                return 1;
-            }
-            nic->mac[i] = val;
-            oparg = endptr + 1;
-        }
-    } else if (MATCH_OPTION("bridge", token, oparg)) {
-        replace_string(&nic->bridge, oparg);
-    } else if (MATCH_OPTION("netdev", token, oparg)) {
-        fprintf(stderr, "the netdev parameter is deprecated, "
-                        "please use gatewaydev instead\n");
-        replace_string(&nic->gatewaydev, oparg);
-    } else if (MATCH_OPTION("gatewaydev", token, oparg)) {
-        replace_string(&nic->gatewaydev, oparg);
-    } else if (MATCH_OPTION("ip", token, oparg)) {
-        replace_string(&nic->ip, oparg);
-    } else if (MATCH_OPTION("script", token, oparg)) {
-        replace_string(&nic->script, oparg);
-    } else if (MATCH_OPTION("backend", token, oparg)) {
-        replace_string(&nic->backend_domname, oparg);
-    } else if (MATCH_OPTION("vifname", token, oparg)) {
-        replace_string(&nic->ifname, oparg);
-    } else if (MATCH_OPTION("model", token, oparg)) {
-        replace_string(&nic->model, oparg);
-    } else if (MATCH_OPTION("rate", token, oparg)) {
-        parse_vif_rate(config, oparg, nic);
-    } else if (MATCH_OPTION("forwarddev", token, oparg)) {
-        replace_string(&nic->coloft_forwarddev, oparg);
-    } else if (MATCH_OPTION("accel", token, oparg)) {
-        fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
-    } else if (MATCH_OPTION("devid", token, oparg)) {
-        nic->devid = parse_ulong(oparg);
-    } else {
-        fprintf(stderr, "unrecognized argument `%s'\n", token);
-        return 1;
-    }
-    return 0;
-}
-
-static void parse_vnuma_config(const XLU_Config *config,
-                               libxl_domain_build_info *b_info)
-{
-    libxl_physinfo physinfo;
-    uint32_t nr_nodes;
-    XLU_ConfigList *vnuma;
-    int i, j, len, num_vnuma;
-    unsigned long max_vcpus = 0, max_memkb = 0;
-    /* Temporary storage for parsed vcpus information to avoid
-     * parsing config twice. This array has num_vnuma elements.
-     */
-    libxl_bitmap *vcpu_parsed;
-
-    libxl_physinfo_init(&physinfo);
-    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
-        libxl_physinfo_dispose(&physinfo);
-        fprintf(stderr, "libxl_get_physinfo failed\n");
-        exit(EXIT_FAILURE);
-    }
-
-    nr_nodes = physinfo.nr_nodes;
-    libxl_physinfo_dispose(&physinfo);
-
-    if (xlu_cfg_get_list(config, "vnuma", &vnuma, &num_vnuma, 1))
-        return;
-
-    if (!num_vnuma)
-        return;
-
-    b_info->num_vnuma_nodes = num_vnuma;
-    b_info->vnuma_nodes = xcalloc(num_vnuma, sizeof(libxl_vnode_info));
-    vcpu_parsed = xcalloc(num_vnuma, sizeof(libxl_bitmap));
-    for (i = 0; i < num_vnuma; i++) {
-        libxl_bitmap_init(&vcpu_parsed[i]);
-        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_parsed[i], b_info->max_vcpus)) {
-            fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
-            exit(EXIT_FAILURE);
-        }
-    }
-
-    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
-        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
-
-        libxl_vnode_info_init(p);
-        p->distances = xcalloc(b_info->num_vnuma_nodes,
-                               sizeof(*p->distances));
-        p->num_distances = b_info->num_vnuma_nodes;
-    }
-
-    for (i = 0; i < num_vnuma; i++) {
-        XLU_ConfigValue *vnode_spec, *conf_option;
-        XLU_ConfigList *vnode_config_list;
-        int conf_count;
-        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
-
-        vnode_spec = xlu_cfg_get_listitem2(vnuma, i);
-        assert(vnode_spec);
-
-        xlu_cfg_value_get_list(config, vnode_spec, &vnode_config_list, 0);
-        if (!vnode_config_list) {
-            fprintf(stderr, "xl: cannot get vnode config option list\n");
-            exit(EXIT_FAILURE);
-        }
-
-        for (conf_count = 0;
-             (conf_option =
-              xlu_cfg_get_listitem2(vnode_config_list, conf_count));
-             conf_count++) {
-
-            if (xlu_cfg_value_type(conf_option) == XLU_STRING) {
-                char *buf, *option_untrimmed, *value_untrimmed;
-                char *option, *value;
-                unsigned long val;
-
-                xlu_cfg_value_get_string(config, conf_option, &buf, 0);
-
-                if (!buf) continue;
-
-                if (split_string_into_pair(buf, "=",
-                                           &option_untrimmed,
-                                           &value_untrimmed)) {
-                    fprintf(stderr, "xl: failed to split \"%s\" into pair\n",
-                            buf);
-                    exit(EXIT_FAILURE);
-                }
-                trim(isspace, option_untrimmed, &option);
-                trim(isspace, value_untrimmed, &value);
-
-                if (!strcmp("pnode", option)) {
-                    val = parse_ulong(value);
-                    if (val >= nr_nodes) {
-                        fprintf(stderr,
-                                "xl: invalid pnode number: %lu\n", val);
-                        exit(EXIT_FAILURE);
-                    }
-                    p->pnode = val;
-                    libxl_defbool_set(&b_info->numa_placement, false);
-                } else if (!strcmp("size", option)) {
-                    val = parse_ulong(value);
-                    p->memkb = val << 10;
-                    max_memkb += p->memkb;
-                } else if (!strcmp("vcpus", option)) {
-                    libxl_string_list cpu_spec_list;
-                    unsigned long s, e;
-
-                    split_string_into_string_list(value, ",", &cpu_spec_list);
-                    len = libxl_string_list_length(&cpu_spec_list);
-
-                    for (j = 0; j < len; j++) {
-                        parse_range(cpu_spec_list[j], &s, &e);
-                        for (; s <= e; s++) {
-                            /*
-                             * Note that if we try to set a bit beyond
-                             * the size of bitmap, libxl_bitmap_set
-                             * has no effect. The resulted bitmap
-                             * doesn't reflect what user wants. The
-                             * fallout is dealt with later after
-                             * parsing.
-                             */
-                            libxl_bitmap_set(&vcpu_parsed[i], s);
-                            max_vcpus++;
-                        }
-                    }
-
-                    libxl_string_list_dispose(&cpu_spec_list);
-                } else if (!strcmp("vdistances", option)) {
-                    libxl_string_list vdist;
-
-                    split_string_into_string_list(value, ",", &vdist);
-                    len = libxl_string_list_length(&vdist);
-
-                    for (j = 0; j < len; j++) {
-                        val = parse_ulong(vdist[j]);
-                        p->distances[j] = val;
-                    }
-                    libxl_string_list_dispose(&vdist);
-                }
-                free(option);
-                free(value);
-                free(option_untrimmed);
-                free(value_untrimmed);
-            }
-        }
-    }
-
-    /* User has specified maxvcpus= */
-    if (b_info->max_vcpus != 0) {
-        if (b_info->max_vcpus != max_vcpus) {
-            fprintf(stderr, "xl: vnuma vcpus and maxvcpus= mismatch\n");
-            exit(EXIT_FAILURE);
-        }
-    } else {
-        int host_cpus = libxl_get_online_cpus(ctx);
-
-        if (host_cpus < 0) {
-            fprintf(stderr, "Failed to get online cpus\n");
-            exit(EXIT_FAILURE);
-        }
-
-        if (host_cpus < max_vcpus) {
-            fprintf(stderr, "xl: vnuma specifies more vcpus than pcpus, "\
-                    "use maxvcpus= to override this check.\n");
-            exit(EXIT_FAILURE);
-        }
-
-        b_info->max_vcpus = max_vcpus;
-    }
-
-    /* User has specified maxmem= */
-    if (b_info->max_memkb != LIBXL_MEMKB_DEFAULT &&
-        b_info->max_memkb != max_memkb) {
-        fprintf(stderr, "xl: maxmem and vnuma memory size mismatch\n");
-        exit(EXIT_FAILURE);
-    } else
-        b_info->max_memkb = max_memkb;
-
-    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
-        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
-
-        libxl_bitmap_copy_alloc(ctx, &p->vcpus, &vcpu_parsed[i]);
-        libxl_bitmap_dispose(&vcpu_parsed[i]);
-    }
-
-    free(vcpu_parsed);
-}
-
-/* Parses usbctrl data and adds info into usbctrl
- * Returns 1 if the input token does not match one of the keys
- * or parsed values are not correct. Successful parse returns 0 */
-static int parse_usbctrl_config(libxl_device_usbctrl *usbctrl, char *token)
-{
-    char *oparg;
-
-    if (MATCH_OPTION("type", token, oparg)) {
-        if (libxl_usbctrl_type_from_string(oparg, &usbctrl->type)) {
-            fprintf(stderr, "Invalid usb controller type '%s'\n", oparg);
-            return 1;
-        }
-    } else if (MATCH_OPTION("version", token, oparg)) {
-        usbctrl->version = atoi(oparg);
-    } else if (MATCH_OPTION("ports", token, oparg)) {
-        usbctrl->ports = atoi(oparg);
-    } else {
-        fprintf(stderr, "Unknown string `%s' in usbctrl spec\n", token);
-        return 1;
-    }
-
-    return 0;
-}
-
-/* Parses usbdev data and adds info into usbdev
- * Returns 1 if the input token does not match one of the keys
- * or parsed values are not correct. Successful parse returns 0 */
-static int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token)
-{
-    char *oparg;
-
-    if (MATCH_OPTION("type", token, oparg)) {
-        if (libxl_usbdev_type_from_string(oparg, &usbdev->type)) {
-            fprintf(stderr, "Invalid usb device type: %s\n", optarg);
-            return 1;
-        }
-    } else if (MATCH_OPTION("hostbus", token, oparg)) {
-        usbdev->u.hostdev.hostbus = strtoul(oparg, NULL, 0);
-    } else if (MATCH_OPTION("hostaddr", token, oparg)) {
-        usbdev->u.hostdev.hostaddr = strtoul(oparg, NULL, 0);
-    } else if (MATCH_OPTION("controller", token, oparg)) {
-        usbdev->ctrl = atoi(oparg);
-    } else if (MATCH_OPTION("port", token, oparg)) {
-        usbdev->port = atoi(oparg);
-    } else {
-        fprintf(stderr, "Unknown string `%s' in usbdev spec\n", token);
-        return 1;
-    }
-
-    return 0;
-}
-
-static void parse_config_data(const char *config_source,
-                              const char *config_data,
-                              int config_len,
-                              libxl_domain_config *d_config)
-{
-    const char *buf;
-    long l, vcpus = 0;
-    XLU_Config *config;
-    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
-                   *usbctrls, *usbdevs;
-    XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
-    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
-    int pci_power_mgmt = 0;
-    int pci_msitranslate = 0;
-    int pci_permissive = 0;
-    int pci_seize = 0;
-    int i, e;
-    char *kernel_basename;
-
-    libxl_domain_create_info *c_info = &d_config->c_info;
-    libxl_domain_build_info *b_info = &d_config->b_info;
-
-    config= xlu_cfg_init(stderr, config_source);
-    if (!config) {
-        fprintf(stderr, "Failed to allocate for configuration\n");
-        exit(1);
-    }
-
-    e= xlu_cfg_readdata(config, config_data, config_len);
-    if (e) {
-        fprintf(stderr, "Failed to parse config: %s\n", strerror(e));
-        exit(1);
-    }
-
-    if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0))
-        xlu_cfg_replace_string(config, "init_seclabel",
-                               &c_info->ssid_label, 0);
-
-    if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) {
-        if (c_info->ssid_label)
-            xlu_cfg_replace_string(config, "seclabel",
-                                   &b_info->exec_ssid_label, 0);
-        else
-            xlu_cfg_replace_string(config, "seclabel",
-                                   &c_info->ssid_label, 0);
-    }
-
-    libxl_defbool_set(&c_info->run_hotplug_scripts, run_hotplug_scripts);
-    c_info->type = LIBXL_DOMAIN_TYPE_PV;
-    if (!xlu_cfg_get_string (config, "builder", &buf, 0) &&
-        !strncmp(buf, "hvm", strlen(buf)))
-        c_info->type = LIBXL_DOMAIN_TYPE_HVM;
-
-    xlu_cfg_get_defbool(config, "pvh", &c_info->pvh, 0);
-    xlu_cfg_get_defbool(config, "hap", &c_info->hap, 0);
-
-    if (xlu_cfg_replace_string (config, "name", &c_info->name, 0)) {
-        fprintf(stderr, "Domain name must be specified.\n");
-        exit(1);
-    }
-
-    if (!xlu_cfg_get_string (config, "uuid", &buf, 0) ) {
-        if ( libxl_uuid_from_string(&c_info->uuid, buf) ) {
-            fprintf(stderr, "Failed to parse UUID: %s\n", buf);
-            exit(1);
-        }
-    }else{
-        libxl_uuid_generate(&c_info->uuid);
-    }
-
-    xlu_cfg_get_defbool(config, "oos", &c_info->oos, 0);
-
-    if (!xlu_cfg_get_string (config, "pool", &buf, 0))
-        xlu_cfg_replace_string(config, "pool", &c_info->pool_name, 0);
-
-    libxl_domain_build_info_init_type(b_info, c_info->type);
-    if (blkdev_start)
-        b_info->blkdev_start = strdup(blkdev_start);
-
-    /* the following is the actual config parsing with overriding
-     * values in the structures */
-    if (!xlu_cfg_get_long (config, "cpu_weight", &l, 0))
-        b_info->sched_params.weight = l;
-    if (!xlu_cfg_get_long (config, "cap", &l, 0))
-        b_info->sched_params.cap = l;
-    if (!xlu_cfg_get_long (config, "period", &l, 0))
-        b_info->sched_params.period = l;
-    if (!xlu_cfg_get_long (config, "slice", &l, 0))
-        b_info->sched_params.slice = l;
-    if (!xlu_cfg_get_long (config, "latency", &l, 0))
-        b_info->sched_params.latency = l;
-    if (!xlu_cfg_get_long (config, "extratime", &l, 0))
-        b_info->sched_params.extratime = l;
-
-    if (!xlu_cfg_get_long (config, "memory", &l, 0))
-        b_info->target_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long (config, "maxmem", &l, 0))
-        b_info->max_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long (config, "vcpus", &l, 0)) {
-        vcpus = l;
-        if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, l)) {
-            fprintf(stderr, "Unable to allocate cpumap\n");
-            exit(1);
-        }
-        libxl_bitmap_set_none(&b_info->avail_vcpus);
-        while (l-- > 0)
-            libxl_bitmap_set((&b_info->avail_vcpus), l);
-    }
-
-    if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
-        b_info->max_vcpus = l;
-
-    parse_vnuma_config(config, b_info);
-
-    /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
-     * they are not set by user specified config option or vnuma.
-     */
-    if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
-        b_info->max_memkb = b_info->target_memkb;
-    if (b_info->max_vcpus == 0)
-        b_info->max_vcpus = vcpus;
-
-    if (b_info->max_vcpus < vcpus) {
-        fprintf(stderr, "xl: maxvcpus < vcpus\n");
-        exit(1);
-    }
-
-    buf = NULL;
-    if (!xlu_cfg_get_list (config, "cpus", &cpus, &num_cpus, 1) ||
-        !xlu_cfg_get_string (config, "cpus", &buf, 0))
-        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, /* is_hard */ true);
-
-    buf = NULL;
-    if (!xlu_cfg_get_list (config, "cpus_soft", &cpus, &num_cpus, 1) ||
-        !xlu_cfg_get_string (config, "cpus_soft", &buf, 0))
-        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, false);
-
-    libxl_defbool_set(&b_info->claim_mode, claim_mode);
-
-    if (xlu_cfg_get_string (config, "on_poweroff", &buf, 0))
-        buf = "destroy";
-    if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
-        fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    if (xlu_cfg_get_string (config, "on_reboot", &buf, 0))
-        buf = "restart";
-    if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
-        fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    if (xlu_cfg_get_string (config, "on_watchdog", &buf, 0))
-        buf = "destroy";
-    if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
-        fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-
-    if (xlu_cfg_get_string (config, "on_crash", &buf, 0))
-        buf = "destroy";
-    if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
-        fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    if (xlu_cfg_get_string (config, "on_soft_reset", &buf, 0))
-        buf = "soft-reset";
-    if (!parse_action_on_shutdown(buf, &d_config->on_soft_reset)) {
-        fprintf(stderr, "Unknown on_soft_reset action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    /* libxl_get_required_shadow_memory() must be called after final values
-     * (default or specified) for vcpus and memory are set, because the
-     * calculation depends on those values. */
-    b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l, 0)
-        ? l * 1024
-        : libxl_get_required_shadow_memory(b_info->max_memkb,
-                                           b_info->max_vcpus);
-
-    xlu_cfg_get_defbool(config, "nomigrate", &b_info->disable_migrate, 0);
-
-    if (!xlu_cfg_get_long(config, "tsc_mode", &l, 1)) {
-        const char *s = libxl_tsc_mode_to_string(l);
-        fprintf(stderr, "WARNING: specifying \"tsc_mode\" as an integer is deprecated. "
-                "Please use the named parameter variant. %s%s%s\n",
-                s ? "e.g. tsc_mode=\"" : "",
-                s ? s : "",
-                s ? "\"" : "");
-
-        if (l < LIBXL_TSC_MODE_DEFAULT ||
-            l > LIBXL_TSC_MODE_NATIVE_PARAVIRT) {
-            fprintf(stderr, "ERROR: invalid value %ld for \"tsc_mode\"\n", l);
-            exit (1);
-        }
-        b_info->tsc_mode = l;
-    } else if (!xlu_cfg_get_string(config, "tsc_mode", &buf, 0)) {
-        fprintf(stderr, "got a tsc mode string: \"%s\"\n", buf);
-        if (libxl_tsc_mode_from_string(buf, &b_info->tsc_mode)) {
-            fprintf(stderr, "ERROR: invalid value \"%s\" for \"tsc_mode\"\n",
-                    buf);
-            exit (1);
-        }
-    }
-
-    if (!xlu_cfg_get_long(config, "rtc_timeoffset", &l, 0))
-        b_info->rtc_timeoffset = l;
-
-    if (!xlu_cfg_get_long(config, "vncviewer", &l, 0))
-        fprintf(stderr, "WARNING: ignoring \"vncviewer\" option. "
-                "Use \"-V\" option of \"xl create\" to automatically spawn vncviewer.\n");
-
-    xlu_cfg_get_defbool(config, "localtime", &b_info->localtime, 0);
-
-    if (!xlu_cfg_get_long (config, "videoram", &l, 0))
-        b_info->video_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long(config, "max_event_channels", &l, 0))
-        b_info->event_channels = l;
-
-    xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0);
-    xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0);
-    xlu_cfg_replace_string (config, "device_tree", &b_info->device_tree, 0);
-    b_info->cmdline = parse_cmdline(config);
-
-    xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);
-    xlu_cfg_get_defbool(config, "acpi", &b_info->acpi, 0);
-
-    switch(b_info->type) {
-    case LIBXL_DOMAIN_TYPE_HVM:
-        kernel_basename = libxl_basename(b_info->kernel);
-        if (!strcmp(kernel_basename, "hvmloader")) {
-            fprintf(stderr, "WARNING: you seem to be using \"kernel\" "
-                    "directive to override HVM guest firmware. Ignore "
-                    "that. Use \"firmware_override\" instead if you "
-                    "really want a non-default firmware\n");
-            b_info->kernel = NULL;
-        }
-        free(kernel_basename);
-
-        xlu_cfg_replace_string (config, "firmware_override",
-                                &b_info->u.hvm.firmware, 0);
-        xlu_cfg_replace_string (config, "bios_path_override",
-                                &b_info->u.hvm.system_firmware, 0);
-        if (!xlu_cfg_get_string(config, "bios", &buf, 0)) {
-            if (libxl_bios_type_from_string(buf, &b_info->u.hvm.bios)) {
-                fprintf(stderr, "ERROR: invalid value \"%s\" for \"bios\"\n",
-                    buf);
-                exit (1);
-            }
-        } else if (b_info->u.hvm.system_firmware)
-            fprintf(stderr, "WARNING: "
-                    "bios_path_override given without specific bios name\n");
-
-        xlu_cfg_get_defbool(config, "pae", &b_info->u.hvm.pae, 0);
-        xlu_cfg_get_defbool(config, "apic", &b_info->u.hvm.apic, 0);
-        xlu_cfg_get_defbool(config, "acpi_s3", &b_info->u.hvm.acpi_s3, 0);
-        xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
-        xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
-        xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
-        xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
-
-        switch (xlu_cfg_get_list(config, "viridian",
-                                 &viridian, &num_viridian, 1))
-        {
-        case 0: /* Success */
-            if (num_viridian) {
-                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
-                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
-                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_disable,
-                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
-            }
-            for (i = 0; i < num_viridian; i++) {
-                libxl_viridian_enlightenment v;
-
-                buf = xlu_cfg_get_listitem(viridian, i);
-                if (strcmp(buf, "all") == 0)
-                    libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
-                else if (strcmp(buf, "defaults") == 0)
-                    libxl_defbool_set(&b_info->u.hvm.viridian, true);
-                else {
-                    libxl_bitmap *s = &b_info->u.hvm.viridian_enable;
-                    libxl_bitmap *r = &b_info->u.hvm.viridian_disable;
-
-                    if (*buf == '!') {
-                        s = &b_info->u.hvm.viridian_disable;
-                        r = &b_info->u.hvm.viridian_enable;
-                        buf++;
-                    }
-
-                    e = libxl_viridian_enlightenment_from_string(buf, &v);
-                    if (e) {
-                        fprintf(stderr,
-                                "xl: unknown viridian enlightenment '%s'\n",
-                                buf);
-                        exit(-ERROR_FAIL);
-                    }
-
-                    libxl_bitmap_set(s, v);
-                    libxl_bitmap_reset(r, v);
-                }
-            }
-            break;
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 1);
-            break;
-        default:
-            fprintf(stderr,"xl: Unable to parse viridian enlightenments.\n");
-            exit(-ERROR_FAIL);
-        }
-
-        if (!xlu_cfg_get_long(config, "mmio_hole", &l, 0)) {
-            uint64_t mmio_hole_size;
-
-            b_info->u.hvm.mmio_hole_memkb = l * 1024;
-            mmio_hole_size = b_info->u.hvm.mmio_hole_memkb * 1024;
-            if (mmio_hole_size < HVM_BELOW_4G_MMIO_LENGTH ||
-                mmio_hole_size > HVM_BELOW_4G_MMIO_START) {
-                fprintf(stderr,
-                        "ERROR: invalid value %ld for \"mmio_hole\"\n", l);
-                exit (1);
-            }
-        }
-        if (!xlu_cfg_get_long(config, "timer_mode", &l, 1)) {
-            const char *s = libxl_timer_mode_to_string(l);
-            fprintf(stderr, "WARNING: specifying \"timer_mode\" as an integer is deprecated. "
-                    "Please use the named parameter variant. %s%s%s\n",
-                    s ? "e.g. timer_mode=\"" : "",
-                    s ? s : "",
-                    s ? "\"" : "");
-
-            if (l < LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS ||
-                l > LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING) {
-                fprintf(stderr, "ERROR: invalid value %ld for \"timer_mode\"\n", l);
-                exit (1);
-            }
-            b_info->u.hvm.timer_mode = l;
-        } else if (!xlu_cfg_get_string(config, "timer_mode", &buf, 0)) {
-            if (libxl_timer_mode_from_string(buf, &b_info->u.hvm.timer_mode)) {
-                fprintf(stderr, "ERROR: invalid value \"%s\" for \"timer_mode\"\n",
-                        buf);
-                exit (1);
-            }
-        }
-
-        xlu_cfg_get_defbool(config, "nestedhvm", &b_info->u.hvm.nested_hvm, 0);
-
-        xlu_cfg_get_defbool(config, "altp2mhvm", &b_info->u.hvm.altp2m, 0);
-
-        xlu_cfg_replace_string(config, "smbios_firmware",
-                               &b_info->u.hvm.smbios_firmware, 0);
-        xlu_cfg_replace_string(config, "acpi_firmware",
-                               &b_info->u.hvm.acpi_firmware, 0);
-
-        if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) {
-            if (!strcmp(buf, "generate")) {
-                e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);
-                if (e) {
-                    fprintf(stderr, "ERROR: failed to generate a VM Generation ID\n");
-                    exit(1);
-                }
-            } else if (!strcmp(buf, "none")) {
-                ;
-            } else {
-                    fprintf(stderr, "ERROR: \"ms_vm_genid\" option must be \"generate\" or \"none\"\n");
-                    exit(1);
-            }
-        }
-
-        if (!xlu_cfg_get_long (config, "rdm_mem_boundary", &l, 0))
-            b_info->u.hvm.rdm_mem_boundary_memkb = l * 1024;
-        break;
-    case LIBXL_DOMAIN_TYPE_PV:
-    {
-        xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader, 0);
-        switch (xlu_cfg_get_list_as_string_list(config, "bootloader_args",
-                                      &b_info->u.pv.bootloader_args, 1))
-        {
-
-        case 0: break; /* Success */
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            if (!xlu_cfg_get_string(config, "bootloader_args", &buf, 0)) {
-
-                fprintf(stderr, "WARNING: Specifying \"bootloader_args\""
-                        " as a string is deprecated. "
-                        "Please use a list of arguments.\n");
-                split_string_into_string_list(buf, " \t\n",
-                                              &b_info->u.pv.bootloader_args);
-            }
-            break;
-        default:
-            fprintf(stderr,"xl: Unable to parse bootloader_args.\n");
-            exit(-ERROR_FAIL);
-        }
-
-        if (!b_info->u.pv.bootloader && !b_info->kernel) {
-            fprintf(stderr, "Neither kernel nor bootloader specified\n");
-            exit(1);
-        }
-
-        break;
-    }
-    default:
-        abort();
-    }
-
-    if (!xlu_cfg_get_list(config, "ioports", &ioports, &num_ioports, 0)) {
-        b_info->num_ioports = num_ioports;
-        b_info->ioports = calloc(num_ioports, sizeof(*b_info->ioports));
-        if (b_info->ioports == NULL) {
-            fprintf(stderr, "unable to allocate memory for ioports\n");
-            exit(-1);
-        }
-
-        for (i = 0; i < num_ioports; i++) {
-            const char *buf2;
-            char *ep;
-            uint32_t start, end;
-            unsigned long ul;
-
-            buf = xlu_cfg_get_listitem (ioports, i);
-            if (!buf) {
-                fprintf(stderr,
-                        "xl: Unable to get element #%d in ioport list\n", i);
-                exit(1);
-            }
-            ul = strtoul(buf, &ep, 16);
-            if (ep == buf) {
-                fprintf(stderr, "xl: Invalid argument parsing ioport: %s\n",
-                        buf);
-                exit(1);
-            }
-            if (ul >= UINT32_MAX) {
-                fprintf(stderr, "xl: ioport %lx too big\n", ul);
-                exit(1);
-            }
-            start = end = ul;
-
-            if (*ep == '-') {
-                buf2 = ep + 1;
-                ul = strtoul(buf2, &ep, 16);
-                if (ep == buf2 || *ep != '\0' || start > end) {
-                    fprintf(stderr,
-                            "xl: Invalid argument parsing ioport: %s\n", buf);
-                    exit(1);
-                }
-                if (ul >= UINT32_MAX) {
-                    fprintf(stderr, "xl: ioport %lx too big\n", ul);
-                    exit(1);
-                }
-                end = ul;
-            } else if ( *ep != '\0' )
-                fprintf(stderr,
-                        "xl: Invalid argument parsing ioport: %s\n", buf);
-            b_info->ioports[i].first = start;
-            b_info->ioports[i].number = end - start + 1;
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "irqs", &irqs, &num_irqs, 0)) {
-        b_info->num_irqs = num_irqs;
-        b_info->irqs = calloc(num_irqs, sizeof(*b_info->irqs));
-        if (b_info->irqs == NULL) {
-            fprintf(stderr, "unable to allocate memory for ioports\n");
-            exit(-1);
-        }
-        for (i = 0; i < num_irqs; i++) {
-            char *ep;
-            unsigned long ul;
-            buf = xlu_cfg_get_listitem (irqs, i);
-            if (!buf) {
-                fprintf(stderr,
-                        "xl: Unable to get element %d in irq list\n", i);
-                exit(1);
-            }
-            ul = strtoul(buf, &ep, 10);
-            if (ep == buf || *ep != '\0') {
-                fprintf(stderr,
-                        "xl: Invalid argument parsing irq: %s\n", buf);
-                exit(1);
-            }
-            if (ul >= UINT32_MAX) {
-                fprintf(stderr, "xl: irq %lx too big\n", ul);
-                exit(1);
-            }
-            b_info->irqs[i] = ul;
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "iomem", &iomem, &num_iomem, 0)) {
-        int ret;
-        b_info->num_iomem = num_iomem;
-        b_info->iomem = calloc(num_iomem, sizeof(*b_info->iomem));
-        if (b_info->iomem == NULL) {
-            fprintf(stderr, "unable to allocate memory for iomem\n");
-            exit(-1);
-        }
-        for (i = 0; i < num_iomem; i++) {
-            int used;
-
-            buf = xlu_cfg_get_listitem (iomem, i);
-            if (!buf) {
-                fprintf(stderr,
-                        "xl: Unable to get element %d in iomem list\n", i);
-                exit(1);
-            }
-            libxl_iomem_range_init(&b_info->iomem[i]);
-            ret = sscanf(buf, "%" SCNx64",%" SCNx64"%n@%" SCNx64"%n",
-                         &b_info->iomem[i].start,
-                         &b_info->iomem[i].number, &used,
-                         &b_info->iomem[i].gfn, &used);
-            if (ret < 2 || buf[used] != '\0') {
-                fprintf(stderr,
-                        "xl: Invalid argument parsing iomem: %s\n", buf);
-                exit(1);
-            }
-        }
-    }
-
-
-
-    if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
-        d_config->num_disks = 0;
-        d_config->disks = NULL;
-        while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
-            libxl_device_disk *disk;
-            char *buf2 = strdup(buf);
-
-            disk = ARRAY_EXTEND_INIT_NODEVID(d_config->disks,
-                                             d_config->num_disks,
-                                             libxl_device_disk_init);
-            parse_disk_config(&config, buf2, disk);
-
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
-        d_config->num_vtpms = 0;
-        d_config->vtpms = NULL;
-        while ((buf = xlu_cfg_get_listitem (vtpms, d_config->num_vtpms)) != NULL) {
-            libxl_device_vtpm *vtpm;
-            char * buf2 = strdup(buf);
-            char *p, *p2;
-            bool got_backend = false;
-
-            vtpm = ARRAY_EXTEND_INIT(d_config->vtpms,
-                                     d_config->num_vtpms,
-                                     libxl_device_vtpm_init);
-
-            p = strtok(buf2, ",");
-            if(p) {
-               do {
-                  while(*p == ' ')
-                     ++p;
-                  if ((p2 = strchr(p, '=')) == NULL)
-                     break;
-                  *p2 = '\0';
-                  if (!strcmp(p, "backend")) {
-                     vtpm->backend_domname = strdup(p2 + 1);
-                     got_backend = true;
-                  } else if(!strcmp(p, "uuid")) {
-                     if( libxl_uuid_from_string(&vtpm->uuid, p2 + 1) ) {
-                        fprintf(stderr,
-                              "Failed to parse vtpm UUID: %s\n", p2 + 1);
-                        exit(1);
-                    }
-                  } else {
-                     fprintf(stderr, "Unknown string `%s' in vtpm spec\n", p);
-                     exit(1);
-                  }
-               } while ((p = strtok(NULL, ",")) != NULL);
-            }
-            if(!got_backend) {
-               fprintf(stderr, "vtpm spec missing required backend field!\n");
-               exit(1);
-            }
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
-        d_config->num_channels = 0;
-        d_config->channels = NULL;
-        while ((buf = xlu_cfg_get_listitem (channels,
-                d_config->num_channels)) != NULL) {
-            libxl_device_channel *chn;
-            libxl_string_list pairs;
-            char *path = NULL;
-            int len;
-
-            chn = ARRAY_EXTEND_INIT(d_config->channels, d_config->num_channels,
-                                   libxl_device_channel_init);
-
-            split_string_into_string_list(buf, ",", &pairs);
-            len = libxl_string_list_length(&pairs);
-            for (i = 0; i < len; i++) {
-                char *key, *key_untrimmed, *value, *value_untrimmed;
-                int rc;
-                rc = split_string_into_pair(pairs[i], "=",
-                                            &key_untrimmed,
-                                            &value_untrimmed);
-                if (rc != 0) {
-                    fprintf(stderr, "failed to parse channel configuration: %s",
-                            pairs[i]);
-                    exit(1);
-                }
-                trim(isspace, key_untrimmed, &key);
-                trim(isspace, value_untrimmed, &value);
-
-                if (!strcmp(key, "backend")) {
-                    replace_string(&chn->backend_domname, value);
-                } else if (!strcmp(key, "name")) {
-                    replace_string(&chn->name, value);
-                } else if (!strcmp(key, "path")) {
-                    replace_string(&path, value);
-                } else if (!strcmp(key, "connection")) {
-                    if (!strcmp(value, "pty")) {
-                        chn->connection = LIBXL_CHANNEL_CONNECTION_PTY;
-                    } else if (!strcmp(value, "socket")) {
-                        chn->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
-                    } else {
-                        fprintf(stderr, "unknown channel connection '%s'\n",
-                                value);
-                        exit(1);
-                    }
-                } else {
-                    fprintf(stderr, "unknown channel parameter '%s',"
-                                  " ignoring\n", key);
-                }
-                free(key);
-                free(key_untrimmed);
-                free(value);
-                free(value_untrimmed);
-            }
-            switch (chn->connection) {
-            case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
-                fprintf(stderr, "channel has unknown 'connection'\n");
-                exit(1);
-            case LIBXL_CHANNEL_CONNECTION_SOCKET:
-                if (!path) {
-                    fprintf(stderr, "channel connection 'socket' requires path=..\n");
-                    exit(1);
-                }
-                chn->u.socket.path = xstrdup(path);
-                break;
-            case LIBXL_CHANNEL_CONNECTION_PTY:
-                /* Nothing to do since PTY has no arguments */
-                break;
-            default:
-                fprintf(stderr, "unknown channel connection: %d",
-                        chn->connection);
-                exit(1);
-            }
-            libxl_string_list_dispose(&pairs);
-            free(path);
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
-        d_config->num_nics = 0;
-        d_config->nics = NULL;
-        while ((buf = xlu_cfg_get_listitem (nics, d_config->num_nics)) != NULL) {
-            libxl_device_nic *nic;
-            char *buf2 = strdup(buf);
-            char *p;
-
-            nic = ARRAY_EXTEND_INIT(d_config->nics,
-                                    d_config->num_nics,
-                                    libxl_device_nic_init);
-            set_default_nic_values(nic);
-
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_nic;
-            do {
-                while (*p == ' ')
-                    p++;
-                parse_nic_config(nic, &config, p);
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_nic:
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "vif2", NULL, 0, 0)) {
-        fprintf(stderr, "WARNING: vif2: netchannel2 is deprecated and not supported by xl\n");
-    }
-
-    d_config->num_vfbs = 0;
-    d_config->num_vkbs = 0;
-    d_config->vfbs = NULL;
-    d_config->vkbs = NULL;
-
-    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0, 0)) {
-        while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
-            libxl_device_vfb *vfb;
-            libxl_device_vkb *vkb;
-
-            char *buf2 = strdup(buf);
-            char *p, *p2;
-
-            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
-                                    libxl_device_vfb_init);
-
-            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
-                                    libxl_device_vkb_init);
-
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_vfb;
-            do {
-                while (*p == ' ')
-                    p++;
-                if ((p2 = strchr(p, '=')) == NULL)
-                    break;
-                *p2 = '\0';
-                if (!strcmp(p, "vnc")) {
-                    libxl_defbool_set(&vfb->vnc.enable, atoi(p2 + 1));
-                } else if (!strcmp(p, "vnclisten")) {
-                    free(vfb->vnc.listen);
-                    vfb->vnc.listen = strdup(p2 + 1);
-                } else if (!strcmp(p, "vncpasswd")) {
-                    free(vfb->vnc.passwd);
-                    vfb->vnc.passwd = strdup(p2 + 1);
-                } else if (!strcmp(p, "vncdisplay")) {
-                    vfb->vnc.display = atoi(p2 + 1);
-                } else if (!strcmp(p, "vncunused")) {
-                    libxl_defbool_set(&vfb->vnc.findunused, atoi(p2 + 1));
-                } else if (!strcmp(p, "keymap")) {
-                    free(vfb->keymap);
-                    vfb->keymap = strdup(p2 + 1);
-                } else if (!strcmp(p, "sdl")) {
-                    libxl_defbool_set(&vfb->sdl.enable, atoi(p2 + 1));
-                } else if (!strcmp(p, "opengl")) {
-                    libxl_defbool_set(&vfb->sdl.opengl, atoi(p2 + 1));
-                } else if (!strcmp(p, "display")) {
-                    free(vfb->sdl.display);
-                    vfb->sdl.display = strdup(p2 + 1);
-                } else if (!strcmp(p, "xauthority")) {
-                    free(vfb->sdl.xauthority);
-                    vfb->sdl.xauthority = strdup(p2 + 1);
-                }
-            } while ((p = strtok(NULL, ",")) != NULL);
-
-skip_vfb:
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l, 0))
-        pci_msitranslate = l;
-
-    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l, 0))
-        pci_power_mgmt = l;
-
-    if (!xlu_cfg_get_long (config, "pci_permissive", &l, 0))
-        pci_permissive = l;
-
-    if (!xlu_cfg_get_long (config, "pci_seize", &l, 0))
-        pci_seize = l;
-
-    /* To be reworked (automatically enabled) once the auto ballooning
-     * after guest starts is done (with PCI devices passed in). */
-    if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
-        xlu_cfg_get_defbool(config, "e820_host", &b_info->u.pv.e820_host, 0);
-    }
-
-    if (!xlu_cfg_get_string(config, "rdm", &buf, 0)) {
-        libxl_rdm_reserve rdm;
-        if (!xlu_rdm_parse(config, &rdm, buf)) {
-            b_info->u.hvm.rdm.strategy = rdm.strategy;
-            b_info->u.hvm.rdm.policy = rdm.policy;
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
-        d_config->num_pcidevs = 0;
-        d_config->pcidevs = NULL;
-        for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
-            libxl_device_pci *pcidev;
-
-            pcidev = ARRAY_EXTEND_INIT_NODEVID(d_config->pcidevs,
-                                               d_config->num_pcidevs,
-                                               libxl_device_pci_init);
-            pcidev->msitranslate = pci_msitranslate;
-            pcidev->power_mgmt = pci_power_mgmt;
-            pcidev->permissive = pci_permissive;
-            pcidev->seize = pci_seize;
-            /*
-             * Like other pci option, the per-device policy always follows
-             * the global policy by default.
-             */
-            pcidev->rdm_policy = b_info->u.hvm.rdm.policy;
-            e = xlu_pci_parse_bdf(config, pcidev, buf);
-            if (e) {
-                fprintf(stderr,
-                        "unable to parse PCI BDF `%s' for passthrough\n",
-                        buf);
-                exit(-e);
-            }
-        }
-        if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV)
-            libxl_defbool_set(&b_info->u.pv.e820_host, true);
-    }
-
-    if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) {
-        d_config->num_dtdevs = 0;
-        d_config->dtdevs = NULL;
-        for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) {
-            libxl_device_dtdev *dtdev;
-
-            dtdev = ARRAY_EXTEND_INIT_NODEVID(d_config->dtdevs,
-                                              d_config->num_dtdevs,
-                                              libxl_device_dtdev_init);
-
-            dtdev->path = strdup(buf);
-            if (dtdev->path == NULL) {
-                fprintf(stderr, "unable to duplicate string for dtdevs\n");
-                exit(-1);
-            }
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "usbctrl", &usbctrls, 0, 0)) {
-        d_config->num_usbctrls = 0;
-        d_config->usbctrls = NULL;
-        while ((buf = xlu_cfg_get_listitem(usbctrls, d_config->num_usbctrls))
-               != NULL) {
-            libxl_device_usbctrl *usbctrl;
-            char *buf2 = strdup(buf);
-            char *p;
-
-            usbctrl = ARRAY_EXTEND_INIT(d_config->usbctrls,
-                                        d_config->num_usbctrls,
-                                        libxl_device_usbctrl_init);
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_usbctrl;
-            do {
-                while (*p == ' ')
-                    p++;
-                if (parse_usbctrl_config(usbctrl, p))
-                    exit(1);
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_usbctrl:
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "usbdev", &usbdevs, 0, 0)) {
-        d_config->num_usbdevs = 0;
-        d_config->usbdevs = NULL;
-        while ((buf = xlu_cfg_get_listitem(usbdevs, d_config->num_usbdevs))
-               != NULL) {
-            libxl_device_usbdev *usbdev;
-            char *buf2 = strdup(buf);
-            char *p;
-
-            usbdev = ARRAY_EXTEND_INIT_NODEVID(d_config->usbdevs,
-                                               d_config->num_usbdevs,
-                                               libxl_device_usbdev_init);
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_usbdev;
-            do {
-                while (*p == ' ')
-                    p++;
-                if (parse_usbdev_config(usbdev, p))
-                    exit(1);
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_usbdev:
-            free(buf2);
-        }
-    }
-
-    switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
-    case 0:
-        {
-            const char *errstr;
-
-            for (i = 0; (buf = xlu_cfg_get_listitem(cpuids, i)) != NULL; i++) {
-                e = libxl_cpuid_parse_config_xend(&b_info->cpuid, buf);
-                switch (e) {
-                case 0: continue;
-                case 1:
-                    errstr = "illegal leaf number";
-                    break;
-                case 2:
-                    errstr = "illegal subleaf number";
-                    break;
-                case 3:
-                    errstr = "missing colon";
-                    break;
-                case 4:
-                    errstr = "invalid register name (must be e[abcd]x)";
-                    break;
-                case 5:
-                    errstr = "policy string must be exactly 32 characters long";
-                    break;
-                default:
-                    errstr = "unknown error";
-                    break;
-                }
-                fprintf(stderr, "while parsing CPUID line: \"%s\":\n", buf);
-                fprintf(stderr, "  error #%i: %s\n", e, errstr);
-            }
-        }
-        break;
-    case EINVAL:    /* config option is not a list, parse as a string */
-        if (!xlu_cfg_get_string(config, "cpuid", &buf, 0)) {
-            char *buf2, *p, *strtok_ptr = NULL;
-            const char *errstr;
-
-            buf2 = strdup(buf);
-            p = strtok_r(buf2, ",", &strtok_ptr);
-            if (p == NULL) {
-                free(buf2);
-                break;
-            }
-            if (strcmp(p, "host")) {
-                fprintf(stderr, "while parsing CPUID string: \"%s\":\n", buf);
-                fprintf(stderr, "  error: first word must be \"host\"\n");
-                free(buf2);
-                break;
-            }
-            for (p = strtok_r(NULL, ",", &strtok_ptr); p != NULL;
-                 p = strtok_r(NULL, ",", &strtok_ptr)) {
-                e = libxl_cpuid_parse_config(&b_info->cpuid, p);
-                switch (e) {
-                case 0: continue;
-                case 1:
-                    errstr = "missing \"=\" in key=value";
-                    break;
-                case 2:
-                    errstr = "unknown CPUID flag name";
-                    break;
-                case 3:
-                    errstr = "illegal CPUID value (must be: [0|1|x|k|s])";
-                    break;
-                default:
-                    errstr = "unknown error";
-                    break;
-                }
-                fprintf(stderr, "while parsing CPUID flag: \"%s\":\n", p);
-                fprintf(stderr, "  error #%i: %s\n", e, errstr);
-            }
-            free(buf2);
-        }
-        break;
-    default:
-        break;
-    }
-
-    /* parse device model arguments, this works for pv, hvm and stubdom */
-    if (!xlu_cfg_get_string (config, "device_model", &buf, 0)) {
-        fprintf(stderr,
-                "WARNING: ignoring device_model directive.\n"
-                "WARNING: Use \"device_model_override\" instead if you"
-                " really want a non-default device_model\n");
-        if (strstr(buf, "stubdom-dm")) {
-            if (c_info->type == LIBXL_DOMAIN_TYPE_HVM)
-                fprintf(stderr, "WARNING: Or use"
-                        " \"device_model_stubdomain_override\" if you "
-                        " want to enable stubdomains\n");
-            else
-                fprintf(stderr, "WARNING: ignoring"
-                        " \"device_model_stubdomain_override\" directive"
-                        " for pv guest\n");
-        }
-    }
-
-
-    xlu_cfg_replace_string (config, "device_model_override",
-                            &b_info->device_model, 0);
-    if (!xlu_cfg_get_string (config, "device_model_version", &buf, 0)) {
-        if (!strcmp(buf, "qemu-xen-traditional")) {
-            b_info->device_model_version
-                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
-        } else if (!strcmp(buf, "qemu-xen")) {
-            b_info->device_model_version
-                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
-        } else if (!strcmp(buf, "none")) {
-            b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_NONE;
-        } else {
-            fprintf(stderr,
-                    "Unknown device_model_version \"%s\" specified\n", buf);
-            exit(1);
-        }
-    } else if (b_info->device_model)
-        fprintf(stderr, "WARNING: device model override given without specific DM version\n");
-    xlu_cfg_get_defbool (config, "device_model_stubdomain_override",
-                         &b_info->device_model_stubdomain, 0);
-
-    if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel",
-                             &buf, 0))
-        xlu_cfg_replace_string(config, "device_model_stubdomain_seclabel",
-                               &b_info->device_model_ssid_label, 0);
-
-    xlu_cfg_replace_string(config, "device_model_user",
-                           &b_info->device_model_user, 0);
-
-#define parse_extra_args(type)                                            \
-    e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \
-                                    &b_info->extra##type, 0);            \
-    if (e && e != ESRCH) {                                                \
-        fprintf(stderr,"xl: Unable to parse device_model_args"#type".\n");\
-        exit(-ERROR_FAIL);                                                \
-    }
-
-    /* parse extra args for qemu, common to both pv, hvm */
-    parse_extra_args();
-
-    /* parse extra args dedicated to pv */
-    parse_extra_args(_pv);
-
-    /* parse extra args dedicated to hvm */
-    parse_extra_args(_hvm);
-
-#undef parse_extra_args
-
-    /* If we've already got vfb=[] for PV guest then ignore top level
-     * VNC config. */
-    if (c_info->type == LIBXL_DOMAIN_TYPE_PV && !d_config->num_vfbs) {
-        long vnc_enabled = 0;
-
-        if (!xlu_cfg_get_long (config, "vnc", &l, 0))
-            vnc_enabled = l;
-
-        if (vnc_enabled) {
-            libxl_device_vfb *vfb;
-            libxl_device_vkb *vkb;
-
-            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
-                                    libxl_device_vfb_init);
-
-            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
-                                    libxl_device_vkb_init);
-
-            parse_top_level_vnc_options(config, &vfb->vnc);
-            parse_top_level_sdl_options(config, &vfb->sdl);
-            xlu_cfg_replace_string (config, "keymap", &vfb->keymap, 0);
-        }
-    } else {
-        parse_top_level_vnc_options(config, &b_info->u.hvm.vnc);
-        parse_top_level_sdl_options(config, &b_info->u.hvm.sdl);
-    }
-
-    if (c_info->type == LIBXL_DOMAIN_TYPE_HVM) {
-        if (!xlu_cfg_get_string (config, "vga", &buf, 0)) {
-            if (!strcmp(buf, "stdvga")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
-            } else if (!strcmp(buf, "cirrus")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
-            } else if (!strcmp(buf, "none")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE;
-            } else if (!strcmp(buf, "qxl")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL;
-            } else {
-                fprintf(stderr, "Unknown vga \"%s\" specified\n", buf);
-                exit(1);
-            }
-        } else if (!xlu_cfg_get_long(config, "stdvga", &l, 0))
-            b_info->u.hvm.vga.kind = l ? LIBXL_VGA_INTERFACE_TYPE_STD :
-                                         LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
-
-        if (!xlu_cfg_get_string(config, "hdtype", &buf, 0) &&
-            libxl_hdtype_from_string(buf, &b_info->u.hvm.hdtype)) {
-                fprintf(stderr, "ERROR: invalid value \"%s\" for \"hdtype\"\n",
-                    buf);
-                exit (1);
-        }
-
-        xlu_cfg_replace_string (config, "keymap", &b_info->u.hvm.keymap, 0);
-        xlu_cfg_get_defbool (config, "spice", &b_info->u.hvm.spice.enable, 0);
-        if (!xlu_cfg_get_long (config, "spiceport", &l, 0))
-            b_info->u.hvm.spice.port = l;
-        if (!xlu_cfg_get_long (config, "spicetls_port", &l, 0))
-            b_info->u.hvm.spice.tls_port = l;
-        xlu_cfg_replace_string (config, "spicehost",
-                                &b_info->u.hvm.spice.host, 0);
-        xlu_cfg_get_defbool(config, "spicedisable_ticketing",
-                            &b_info->u.hvm.spice.disable_ticketing, 0);
-        xlu_cfg_replace_string (config, "spicepasswd",
-                                &b_info->u.hvm.spice.passwd, 0);
-        xlu_cfg_get_defbool(config, "spiceagent_mouse",
-                            &b_info->u.hvm.spice.agent_mouse, 0);
-        xlu_cfg_get_defbool(config, "spicevdagent",
-                            &b_info->u.hvm.spice.vdagent, 0);
-        xlu_cfg_get_defbool(config, "spice_clipboard_sharing",
-                            &b_info->u.hvm.spice.clipboard_sharing, 0);
-        if (!xlu_cfg_get_long (config, "spiceusbredirection", &l, 0))
-            b_info->u.hvm.spice.usbredirection = l;
-        xlu_cfg_replace_string (config, "spice_image_compression",
-                                &b_info->u.hvm.spice.image_compression, 0);
-        xlu_cfg_replace_string (config, "spice_streaming_video",
-                                &b_info->u.hvm.spice.streaming_video, 0);
-        xlu_cfg_get_defbool(config, "nographic", &b_info->u.hvm.nographic, 0);
-        if (!xlu_cfg_get_long(config, "gfx_passthru", &l, 1)) {
-            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, l);
-        } else if (!xlu_cfg_get_string(config, "gfx_passthru", &buf, 0)) {
-            if (libxl_gfx_passthru_kind_from_string(buf,
-                                        &b_info->u.hvm.gfx_passthru_kind)) {
-                fprintf(stderr,
-                        "ERROR: invalid value \"%s\" for \"gfx_passthru\"\n",
-                        buf);
-                exit (1);
-            }
-            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, true);
-        }
-        switch (xlu_cfg_get_list_as_string_list(config, "serial",
-                                                &b_info->u.hvm.serial_list,
-                                                1))
-        {
-
-        case 0: break; /* Success */
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            /* If it's not a valid list, try reading it as an atom,
-             * falling through to an error if it fails */
-            if (!xlu_cfg_replace_string(config, "serial",
-                                        &b_info->u.hvm.serial, 0))
-                break;
-            /* FALLTHRU */
-        default:
-            fprintf(stderr,"xl: Unable to parse serial.\n");
-            exit(-ERROR_FAIL);
-        }
-        xlu_cfg_replace_string (config, "boot", &b_info->u.hvm.boot, 0);
-        xlu_cfg_get_defbool(config, "usb", &b_info->u.hvm.usb, 0);
-        if (!xlu_cfg_get_long (config, "usbversion", &l, 0))
-            b_info->u.hvm.usbversion = l;
-        switch (xlu_cfg_get_list_as_string_list(config, "usbdevice",
-                                                &b_info->u.hvm.usbdevice_list,
-                                                1))
-        {
-
-        case 0: break; /* Success */
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            /* If it's not a valid list, try reading it as an atom,
-             * falling through to an error if it fails */
-            if (!xlu_cfg_replace_string(config, "usbdevice",
-                                        &b_info->u.hvm.usbdevice, 0))
-                break;
-            /* FALLTHRU */
-        default:
-            fprintf(stderr,"xl: Unable to parse usbdevice.\n");
-            exit(-ERROR_FAIL);
-        }
-        xlu_cfg_replace_string (config, "soundhw", &b_info->u.hvm.soundhw, 0);
-        xlu_cfg_get_defbool(config, "xen_platform_pci",
-                            &b_info->u.hvm.xen_platform_pci, 0);
-
-        if(b_info->u.hvm.vnc.listen
-           && b_info->u.hvm.vnc.display
-           && strchr(b_info->u.hvm.vnc.listen, ':') != NULL) {
-            fprintf(stderr,
-                    "ERROR: Display specified both in vnclisten"
-                    " and vncdisplay!\n");
-            exit (1);
-
-        }
-
-        if (!xlu_cfg_get_string (config, "vendor_device", &buf, 0)) {
-            libxl_vendor_device d;
-
-            e = libxl_vendor_device_from_string(buf, &d);
-            if (e) {
-                fprintf(stderr,
-                        "xl: unknown vendor_device '%s'\n",
-                        buf);
-                exit(-ERROR_FAIL);
-            }
-
-            b_info->u.hvm.vendor_device = d;
-        }
-    }
-
-    if (!xlu_cfg_get_string (config, "gic_version", &buf, 1)) {
-        e = libxl_gic_version_from_string(buf, &b_info->arch_arm.gic_version);
-        if (e) {
-            fprintf(stderr,
-                    "Unknown gic_version \"%s\" specified\n", buf);
-            exit(-ERROR_FAIL);
-        }
-     }
-
-    xlu_cfg_destroy(config);
-}
-
-static void reload_domain_config(uint32_t domid,
-                                 libxl_domain_config *d_config)
-{
-    int rc;
-    uint8_t *t_data;
-    int ret, t_len;
-    libxl_domain_config d_config_new;
-
-    /* In case user has used "config-update" to store a new config
-     * file.
-     */
-    ret = libxl_userdata_retrieve(ctx, domid, "xl", &t_data, &t_len);
-    if (ret && errno != ENOENT) {
-        LOG("\"xl\" configuration found but failed to load\n");
-    }
-    if (t_len > 0) {
-        LOG("\"xl\" configuration found, using it\n");
-        libxl_domain_config_dispose(d_config);
-        libxl_domain_config_init(d_config);
-        parse_config_data("<updated>", (const char *)t_data,
-                          t_len, d_config);
-        free(t_data);
-        libxl_userdata_unlink(ctx, domid, "xl");
-        return;
-    }
-
-    libxl_domain_config_init(&d_config_new);
-    rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config_new);
-    if (rc) {
-        LOG("failed to retrieve guest configuration (rc=%d). "
-            "reusing old configuration", rc);
-        libxl_domain_config_dispose(&d_config_new);
-    } else {
-        libxl_domain_config_dispose(d_config);
-        /* Steal allocations */
-        memcpy(d_config, &d_config_new, sizeof(libxl_domain_config));
-    }
-}
-
-/* Can update r_domid if domain is destroyed */
-static domain_restart_type handle_domain_death(uint32_t *r_domid,
-                                               libxl_event *event,
-                                               libxl_domain_config *d_config)
-{
-    domain_restart_type restart = DOMAIN_RESTART_NONE;
-    libxl_action_on_shutdown action;
-
-    switch (event->u.domain_shutdown.shutdown_reason) {
-    case LIBXL_SHUTDOWN_REASON_POWEROFF:
-        action = d_config->on_poweroff;
-        break;
-    case LIBXL_SHUTDOWN_REASON_REBOOT:
-        action = d_config->on_reboot;
-        break;
-    case LIBXL_SHUTDOWN_REASON_SUSPEND:
-        LOG("Domain has suspended.");
-        return 0;
-    case LIBXL_SHUTDOWN_REASON_CRASH:
-        action = d_config->on_crash;
-        break;
-    case LIBXL_SHUTDOWN_REASON_WATCHDOG:
-        action = d_config->on_watchdog;
-        break;
-    case LIBXL_SHUTDOWN_REASON_SOFT_RESET:
-        action = d_config->on_soft_reset;
-        break;
-    default:
-        LOG("Unknown shutdown reason code %d. Destroying domain.",
-            event->u.domain_shutdown.shutdown_reason);
-        action = LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
-    }
-
-    LOG("Action for shutdown reason code %d is %s",
-        event->u.domain_shutdown.shutdown_reason,
-        action_on_shutdown_names[action]);
-
-    if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY || action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART) {
-        char *corefile;
-        int rc;
-
-        xasprintf(&corefile, XEN_DUMP_DIR "/%s", d_config->c_info.name);
-        LOG("dumping core to %s", corefile);
-        rc = libxl_domain_core_dump(ctx, *r_domid, corefile, NULL);
-        if (rc) LOG("core dump failed (rc=%d).", rc);
-        free(corefile);
-        /* No point crying over spilled milk, continue on failure. */
-
-        if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY)
-            action = LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
-        else
-            action = LIBXL_ACTION_ON_SHUTDOWN_RESTART;
-    }
-
-    switch (action) {
-    case LIBXL_ACTION_ON_SHUTDOWN_PRESERVE:
-        break;
-
-    case LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME:
-        reload_domain_config(*r_domid, d_config);
-        restart = DOMAIN_RESTART_RENAME;
-        break;
-
-    case LIBXL_ACTION_ON_SHUTDOWN_RESTART:
-        reload_domain_config(*r_domid, d_config);
-        restart = DOMAIN_RESTART_NORMAL;
-        /* fall-through */
-    case LIBXL_ACTION_ON_SHUTDOWN_DESTROY:
-        LOG("Domain %d needs to be cleaned up: destroying the domain",
-            *r_domid);
-        libxl_domain_destroy(ctx, *r_domid, 0);
-        *r_domid = INVALID_DOMID;
-        break;
-
-    case LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET:
-        reload_domain_config(*r_domid, d_config);
-        restart = DOMAIN_RESTART_SOFT_RESET;
-        break;
-
-    case LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY:
-    case LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART:
-        /* Already handled these above. */
-        abort();
-    }
-
-    return restart;
-}
-
-/* Preserve a copy of a domain under a new name. Updates *r_domid */
-static int preserve_domain(uint32_t *r_domid, libxl_event *event,
-                           libxl_domain_config *d_config)
-{
-    time_t now;
-    struct tm tm;
-    char strtime[24];
-
-    libxl_uuid new_uuid;
-
-    int rc;
-
-    now = time(NULL);
-    if (now == ((time_t) -1)) {
-        LOG("Failed to get current time for domain rename");
-        return 0;
-    }
-
-    tzset();
-    if (gmtime_r(&now, &tm) == NULL) {
-        LOG("Failed to convert time to UTC");
-        return 0;
-    }
-
-    if (!strftime(&strtime[0], sizeof(strtime), "-%Y%m%dT%H%MZ", &tm)) {
-        LOG("Failed to format time as a string");
-        return 0;
-    }
-
-    libxl_uuid_generate(&new_uuid);
-
-    LOG("Preserving domain %u %s with suffix%s",
-        *r_domid, d_config->c_info.name, strtime);
-    rc = libxl_domain_preserve(ctx, *r_domid, &d_config->c_info,
-                               strtime, new_uuid);
-
-    /*
-     * Although the domain still exists it is no longer the one we are
-     * concerned with.
-     */
-    *r_domid = INVALID_DOMID;
-
-    return rc == 0 ? 1 : 0;
-}
-
-/*
- * Returns false if memory can't be freed, but also if we encounter errors.
- * Returns true in case there is already, or we manage to free it, enough
- * memory, but also if autoballoon is false.
- */
-static bool freemem(uint32_t domid, libxl_domain_build_info *b_info)
-{
-    int rc, retries = 3;
-    uint64_t need_memkb, free_memkb;
-
-    if (!autoballoon)
-        return true;
-
-    rc = libxl_domain_need_memory(ctx, b_info, &need_memkb);
-    if (rc < 0)
-        return false;
-
-    do {
-        rc = libxl_get_free_memory(ctx, &free_memkb);
-        if (rc < 0)
-            return false;
-
-        if (free_memkb >= need_memkb)
-            return true;
-
-        rc = libxl_set_memory_target(ctx, 0, free_memkb - need_memkb, 1, 0);
-        if (rc < 0)
-            return false;
-
-        /* wait until dom0 reaches its target, as long as we are making
-         * progress */
-        rc = libxl_wait_for_memory_target(ctx, 0, 10);
-        if (rc < 0)
-            return false;
-
-        retries--;
-    } while (retries > 0);
-
-    return false;
-}
-
-static void autoconnect_console(libxl_ctx *ctx_ignored,
-                                libxl_event *ev, void *priv)
-{
-    uint32_t bldomid = ev->domid;
-    int notify_fd = *(int*)priv; /* write end of the notification pipe */
-
-    libxl_event_free(ctx, ev);
-
-    console_child_report(child_console);
-
-    pid_t pid = xl_fork(child_console, "console child");
-    if (pid)
-        return;
-
-    postfork();
-
-    sleep(1);
-    libxl_primary_console_exec(ctx, bldomid, notify_fd);
-    /* Do not return. xl continued in child process */
-    perror("xl: unable to exec console client");
-    _exit(1);
-}
-
-static int domain_wait_event(uint32_t domid, libxl_event **event_r)
-{
-    int ret;
-    for (;;) {
-        ret = libxl_event_wait(ctx, event_r, LIBXL_EVENTMASK_ALL, 0,0);
-        if (ret) {
-            LOG("Domain %u, failed to get event, quitting (rc=%d)", domid, ret);
-            return ret;
-        }
-        if ((*event_r)->domid != domid) {
-            char *evstr = libxl_event_to_json(ctx, *event_r);
-            LOG("INTERNAL PROBLEM - ignoring unexpected event for"
-                " domain %d (expected %d): event=%s",
-                (*event_r)->domid, domid, evstr);
-            free(evstr);
-            libxl_event_free(ctx, *event_r);
-            continue;
-        }
-        return ret;
-    }
-}
-
-static void evdisable_disk_ejects(libxl_evgen_disk_eject **diskws,
-                                 int num_disks)
-{
-    int i;
-
-    for (i = 0; i < num_disks; i++) {
-        if (diskws[i])
-            libxl_evdisable_disk_eject(ctx, diskws[i]);
-        diskws[i] = NULL;
-    }
-}
-
-static int create_domain(struct domain_create *dom_info)
-{
-    uint32_t domid = INVALID_DOMID;
-
-    libxl_domain_config d_config;
-
-    int debug = dom_info->debug;
-    int daemonize = dom_info->daemonize;
-    int monitor = dom_info->monitor;
-    int paused = dom_info->paused;
-    int vncautopass = dom_info->vncautopass;
-    const char *config_file = dom_info->config_file;
-    const char *extra_config = dom_info->extra_config;
-    const char *restore_file = dom_info->restore_file;
-    const char *config_source = NULL;
-    const char *restore_source = NULL;
-    int migrate_fd = dom_info->migrate_fd;
-    bool config_in_json;
-
-    int i;
-    int need_daemon = daemonize;
-    int ret, rc;
-    libxl_evgen_domain_death *deathw = NULL;
-    libxl_evgen_disk_eject **diskws = NULL; /* one per disk */
-    unsigned int num_diskws = 0;
-    void *config_data = 0;
-    int config_len = 0;
-    int restore_fd = -1;
-    int restore_fd_to_close = -1;
-    int send_back_fd = -1;
-    const libxl_asyncprogress_how *autoconnect_console_how;
-    int notify_pipe[2] = { -1, -1 };
-    struct save_file_header hdr;
-    uint32_t domid_soft_reset = INVALID_DOMID;
-
-    int restoring = (restore_file || (migrate_fd >= 0));
-
-    libxl_domain_config_init(&d_config);
-
-    if (restoring) {
-        uint8_t *optdata_begin = 0;
-        const uint8_t *optdata_here = 0;
-        union { uint32_t u32; char b[4]; } u32buf;
-        uint32_t badflags;
-
-        if (migrate_fd >= 0) {
-            restore_source = "<incoming migration stream>";
-            restore_fd = migrate_fd;
-            send_back_fd = dom_info->send_back_fd;
-        } else {
-            restore_source = restore_file;
-            restore_fd = open(restore_file, O_RDONLY);
-            if (restore_fd == -1) {
-                fprintf(stderr, "Can't open restore file: %s\n", strerror(errno));
-                return ERROR_INVAL;
-            }
-            restore_fd_to_close = restore_fd;
-            rc = libxl_fd_set_cloexec(ctx, restore_fd, 1);
-            if (rc) return rc;
-        }
-
-        CHK_ERRNOVAL(libxl_read_exactly(
-                         ctx, restore_fd, &hdr, sizeof(hdr),
-                         restore_source, "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_source, hdr.mandatory_flags, hdr.optional_flags,
-                hdr.optional_data_len);
-
-        badflags = hdr.mandatory_flags & ~XL_MANDATORY_FLAG_ALL;
-        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_ERRNOVAL(libxl_read_exactly(
-                             ctx, restore_fd, optdata_begin,
-                             hdr.optional_data_len, restore_source,
-                             "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%s\n",
-                    !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON)
-                    ? " in JSON format" : "");
-            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;
-        /* /dev/null represents special case (read config. from command line) */
-        if (!strcmp(config_file, "/dev/null")) {
-            config_len = 0;
-        } else {
-            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; }
-        }
-        if (!restoring && extra_config && strlen(extra_config)) {
-            if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
-                fprintf(stderr, "Failed to attach extra configuration\n");
-                return ERROR_FAIL;
-            }
-            /* allocate space for the extra config plus two EOLs plus \0 */
-            config_data = xrealloc(config_data, config_len
-                + strlen(extra_config) + 2 + 1);
-            config_len += sprintf(config_data + config_len, "\n%s\n",
-                extra_config);
-        }
-        config_source=config_file;
-        config_in_json = false;
-    } else {
-        if (!config_data) {
-            fprintf(stderr, "Config file not specified and"
-                    " none in save file\n");
-            return ERROR_INVAL;
-        }
-        config_source = "<saved>";
-        config_in_json = !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON);
-    }
-
-    if (!dom_info->quiet)
-        fprintf(stderr, "Parsing config from %s\n", config_source);
-
-    if (config_in_json) {
-        libxl_domain_config_from_json(ctx, &d_config,
-                                      (const char *)config_data);
-    } else {
-        parse_config_data(config_source, config_data, config_len, &d_config);
-    }
-
-    if (migrate_fd >= 0) {
-        if (d_config.c_info.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 = d_config.c_info.name;
-            d_config.c_info.name = 0; /* steals allocation from config */
-
-            xasprintf(&d_config.c_info.name, "%s--incoming", common_domname);
-            *dom_info->migration_domname_r = strdup(d_config.c_info.name);
-        }
-    }
-
-    if (debug || dom_info->dryrun) {
-        FILE *cfg_print_fh = (debug && !dom_info->dryrun) ? stderr : stdout;
-        if (default_output_format == OUTPUT_FORMAT_SXP) {
-            printf_info_sexp(-1, &d_config, cfg_print_fh);
-        } else {
-            char *json = libxl_domain_config_to_json(ctx, &d_config);
-            if (!json) {
-                fprintf(stderr,
-                        "Failed to convert domain configuration to JSON\n");
-                exit(1);
-            }
-            fputs(json, cfg_print_fh);
-            free(json);
-            flush_stream(cfg_print_fh);
-        }
-    }
-
-
-    ret = 0;
-    if (dom_info->dryrun)
-        goto out;
-
-start:
-    assert(domid == INVALID_DOMID);
-
-    rc = acquire_lock();
-    if (rc < 0)
-        goto error_out;
-
-    if (domid_soft_reset == INVALID_DOMID) {
-        if (!freemem(domid, &d_config.b_info)) {
-            fprintf(stderr, "failed to free memory for the domain\n");
-            ret = ERROR_FAIL;
-            goto error_out;
-        }
-    }
-
-    libxl_asyncprogress_how autoconnect_console_how_buf;
-    if ( dom_info->console_autoconnect ) {
-        if (libxl_pipe(ctx, notify_pipe)) {
-            ret = ERROR_FAIL;
-            goto error_out;
-        }
-        autoconnect_console_how_buf.callback = autoconnect_console;
-        autoconnect_console_how_buf.for_callback = &notify_pipe[1];
-        autoconnect_console_how = &autoconnect_console_how_buf;
-    }else{
-        autoconnect_console_how = 0;
-    }
-
-    if ( restoring ) {
-        libxl_domain_restore_params params;
-
-        libxl_domain_restore_params_init(&params);
-
-        params.checkpointed_stream = dom_info->checkpointed_stream;
-        params.stream_version =
-            (hdr.mandatory_flags & XL_MANDATORY_FLAG_STREAMv2) ? 2 : 1;
-        params.colo_proxy_script = dom_info->colo_proxy_script;
-
-        ret = libxl_domain_create_restore(ctx, &d_config,
-                                          &domid, restore_fd,
-                                          send_back_fd, &params,
-                                          0, autoconnect_console_how);
-
-        libxl_domain_restore_params_dispose(&params);
-
-        /*
-         * On subsequent reboot etc we should create the domain, not
-         * restore/migrate-receive it again.
-         */
-        restoring = 0;
-    } else if (domid_soft_reset != INVALID_DOMID) {
-        /* Do soft reset. */
-        ret = libxl_domain_soft_reset(ctx, &d_config, domid_soft_reset,
-                                      0, autoconnect_console_how);
-        domid = domid_soft_reset;
-        domid_soft_reset = INVALID_DOMID;
-    } else {
-        ret = libxl_domain_create_new(ctx, &d_config, &domid,
-                                      0, autoconnect_console_how);
-    }
-    if ( ret )
-        goto error_out;
-
-    release_lock();
-
-    if (restore_fd_to_close >= 0) {
-        if (close(restore_fd_to_close))
-            fprintf(stderr, "Failed to close restoring file, fd %d, errno %d\n",
-                    restore_fd_to_close, errno);
-        restore_fd_to_close = -1;
-    }
-
-    if (autoconnect_console_how) {
-        char buf[1];
-        int r;
-
-        /* Try to get notification from xenconsole. Just move on if
-         * error occurs -- it's only minor annoyance if console
-         * doesn't show up.
-         */
-        do {
-            r = read(notify_pipe[0], buf, 1);
-        } while (r == -1 && errno == EINTR);
-
-        if (r == -1)
-            fprintf(stderr,
-                    "Failed to get notification from xenconsole: %s\n",
-                    strerror(errno));
-        else if (r == 0)
-            fprintf(stderr, "Got EOF from xenconsole notification fd\n");
-        else if (r == 1 && buf[0] != 0x00)
-            fprintf(stderr, "Got unexpected response from xenconsole: %#x\n",
-                    buf[0]);
-
-        close(notify_pipe[0]);
-        close(notify_pipe[1]);
-        notify_pipe[0] = notify_pipe[1] = -1;
-    }
-
-    if (!paused)
-        libxl_domain_unpause(ctx, domid);
-
-    ret = domid; /* caller gets success in parent */
-    if (!daemonize && !monitor)
-        goto out;
-
-    if (dom_info->vnc)
-        autoconnect_vncviewer(domid, vncautopass);
-
-    if (need_daemon) {
-        char *name;
-
-        xasprintf(&name, "xl-%s", d_config.c_info.name);
-        ret = do_daemonize(name, NULL);
-        free(name);
-        if (ret) {
-            ret = (ret == 1) ? domid : ret;
-            goto out;
-        }
-        need_daemon = 0;
-    }
-    LOG("Waiting for domain %s (domid %u) to die [pid %ld]",
-        d_config.c_info.name, domid, (long)getpid());
-
-    ret = libxl_evenable_domain_death(ctx, domid, 0, &deathw);
-    if (ret) goto out;
-
-    if (!diskws) {
-        diskws = xmalloc(sizeof(*diskws) * d_config.num_disks);
-        for (i = 0; i < d_config.num_disks; i++)
-            diskws[i] = NULL;
-        num_diskws = d_config.num_disks;
-    }
-    for (i = 0; i < num_diskws; i++) {
-        if (d_config.disks[i].removable) {
-            ret = libxl_evenable_disk_eject(ctx, domid, d_config.disks[i].vdev,
-                                            0, &diskws[i]);
-            if (ret) goto out;
-        }
-    }
-    while (1) {
-        libxl_event *event;
-        ret = domain_wait_event(domid, &event);
-        if (ret) goto out;
-
-        switch (event->type) {
-
-        case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
-            LOG("Domain %u has shut down, reason code %d 0x%x", domid,
-                event->u.domain_shutdown.shutdown_reason,
-                event->u.domain_shutdown.shutdown_reason);
-            switch (handle_domain_death(&domid, event, &d_config)) {
-            case DOMAIN_RESTART_SOFT_RESET:
-                domid_soft_reset = domid;
-                domid = INVALID_DOMID;
-                /* fall through */
-            case DOMAIN_RESTART_RENAME:
-                if (domid_soft_reset == INVALID_DOMID &&
-                    !preserve_domain(&domid, event, &d_config)) {
-                    libxl_event_free(ctx, event);
-                    /* If we fail then exit leaving the old domain in place. */
-                    ret = -1;
-                    goto out;
-                }
-
-                /* Otherwise fall through and restart. */
-            case DOMAIN_RESTART_NORMAL:
-                libxl_event_free(ctx, event);
-                libxl_evdisable_domain_death(ctx, deathw);
-                deathw = NULL;
-                evdisable_disk_ejects(diskws, num_diskws);
-                free(diskws);
-                diskws = NULL;
-                num_diskws = 0;
-                /* discard any other events which may have been generated */
-                while (!(ret = libxl_event_check(ctx, &event,
-                                                 LIBXL_EVENTMASK_ALL, 0,0))) {
-                    libxl_event_free(ctx, event);
-                }
-                if (ret != ERROR_NOT_READY) {
-                    LOG("warning, libxl_event_check (cleanup) failed (rc=%d)",
-                        ret);
-                }
-
-                /*
-                 * Do not attempt to reconnect if we come round again due to a
-                 * guest reboot -- the stdin/out will be disconnected by then.
-                 */
-                dom_info->console_autoconnect = 0;
-
-                /* Some settings only make sense on first boot. */
-                paused = 0;
-                if (common_domname
-                    && strcmp(d_config.c_info.name, common_domname)) {
-                    d_config.c_info.name = strdup(common_domname);
-                }
-
-                /*
-                 * XXX FIXME: If this sleep is not there then domain
-                 * re-creation fails sometimes.
-                 */
-                LOG("Done. Rebooting now");
-                sleep(2);
-                goto start;
-
-            case DOMAIN_RESTART_NONE:
-                LOG("Done. Exiting now");
-                libxl_event_free(ctx, event);
-                ret = 0;
-                goto out;
-
-            default:
-                abort();
-            }
-
-        case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
-            LOG("Domain %u has been destroyed.", domid);
-            libxl_event_free(ctx, event);
-            ret = 0;
-            goto out;
-
-        case LIBXL_EVENT_TYPE_DISK_EJECT:
-            /* XXX what is this for? */
-            libxl_cdrom_insert(ctx, domid, &event->u.disk_eject.disk, NULL);
-            break;
-
-        default:;
-            char *evstr = libxl_event_to_json(ctx, event);
-            LOG("warning, got unexpected event type %d, event=%s",
-                event->type, evstr);
-            free(evstr);
-        }
-
-        libxl_event_free(ctx, event);
-    }
-
-error_out:
-    release_lock();
-    if (libxl_domid_valid_guest(domid)) {
-        libxl_domain_destroy(ctx, domid, 0);
-        domid = INVALID_DOMID;
-    }
-
-out:
-    if (restore_fd_to_close >= 0) {
-        if (close(restore_fd_to_close))
-            fprintf(stderr, "Failed to close restoring file, fd %d, errno %d\n",
-                    restore_fd_to_close, errno);
-        restore_fd_to_close = -1;
-    }
-
-    if (logfile != 2)
-        close(logfile);
-
-    libxl_domain_config_dispose(&d_config);
-
-    free(config_data);
-
-    console_child_report(child_console);
-
-    if (deathw)
-        libxl_evdisable_domain_death(ctx, deathw);
-    if (diskws) {
-        evdisable_disk_ejects(diskws, d_config.num_disks);
-        free(diskws);
-    }
-
-    /*
-     * If we have daemonized then do not return to the caller -- this has
-     * already happened in the parent.
-     */
-    if ( daemonize && !need_daemon )
-        exit(ret);
-
-    return ret;
-}
-
-void help(const char *command)
-{
-    int i;
-    struct cmd_spec *cmd;
-
-    if (!command || !strcmp(command, "help")) {
-        printf("Usage xl [-vfN] <subcommand> [args]\n\n");
-        printf("xl full list of subcommands:\n\n");
-        for (i = 0; i < cmdtable_len; i++) {
-            printf(" %-19s ", cmd_table[i].cmd_name);
-            if (strlen(cmd_table[i].cmd_name) > 19)
-                printf("\n %-19s ", "");
-            printf("%s\n", cmd_table[i].cmd_desc);
-        }
-    } else {
-        cmd = cmdtable_lookup(command);
-        if (cmd) {
-            printf("Usage: xl [-v%s%s] %s %s\n\n%s.\n\n",
-                   cmd->modifies ? "f" : "",
-                   cmd->can_dryrun ? "N" : "",
-                   cmd->cmd_name,
-                   cmd->cmd_usage,
-                   cmd->cmd_desc);
-            if (cmd->cmd_option)
-                printf("Options:\n\n%s\n", cmd->cmd_option);
-        }
-        else {
-            printf("command \"%s\" not implemented\n", command);
-        }
-    }
-}
-
-/* Returns -1 on failure; the amount of memory on success. */
-static int64_t parse_mem_size_kb(const char *mem)
-{
-    char *endptr;
-    int64_t kbytes;
-
-    kbytes = strtoll(mem, &endptr, 10);
-
-    if (strlen(endptr) > 1)
-        return -1;
-
-    switch (tolower((uint8_t)*endptr)) {
-    case 't':
-        kbytes <<= 10;
-        /* fallthrough */
-    case 'g':
-        kbytes <<= 10;
-        /* fallthrough */
-    case '\0':
-    case 'm':
-        kbytes <<= 10;
-        /* fallthrough */
-    case 'k':
-        break;
-    case 'b':
-        kbytes >>= 10;
-        break;
-    default:
-        return -1;
-    }
-
-    return kbytes;
-}
-
-/* Must be last in list */
-#define COMMON_LONG_OPTS {"help", 0, 0, 'h'}, \
-                         {0, 0, 0, 0}
-
-/*
- * Callers should use SWITCH_FOREACH_OPT in preference to calling this
- * directly.
- */
-static int def_getopt(int argc, char * const argv[],
-                      const char *optstring,
-                      const struct option *longopts,
-                      const char* helpstr, int reqargs)
-{
-    int opt;
-    const struct option def_options[] = {
-        COMMON_LONG_OPTS
-    };
-
-    if (!longopts)
-        longopts = def_options;
-
-    opterr = 0;
-    while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) == '?') {
-        if (optopt == 'h') {
-            help(helpstr);
-            exit(0);
-        }
-        fprintf(stderr, "option `%c' not supported.\n", optopt);
-        exit(2);
-    }
-    if (opt == 'h') {
-        help(helpstr);
-        exit(0);
-    }
-    if (opt != -1)
-        return opt;
-
-    if (argc - optind <= reqargs - 1) {
-        fprintf(stderr, "'xl %s' requires at least %d argument%s.\n\n",
-                helpstr, reqargs, reqargs > 1 ? "s" : "");
-        help(helpstr);
-        exit(2);
-    }
-    return -1;
-}
-
-/*
- * Wraps def_getopt into a convenient loop+switch to process all
- * arguments. This macro is intended to be called from main_XXX().
- *
- *   SWITCH_FOREACH_OPT(int *opt, "OPTS",
- *                      const struct option *longopts,
- *                      const char *commandname,
- *                      int num_opts_req) { ...
- *
- * opt:               pointer to an int variable, holds the current option
- *                    during processing.
- * OPTS:              short options, as per getopt_long(3)'s optstring argument.
- *                    do not include "h"; will be provided automatically
- * longopts:          long options, as per getopt_long(3)'s longopts argument.
- *                    May be null.
- * commandname:       name of this command, for usage string.
- * num_required_opts: number of non-option command line parameters
- *                    which are required.
- *
- * In addition the calling context is expected to contain variables
- * "argc" and "argv" in the conventional C-style:
- *   main(int argc, char **argv)
- * manner.
- *
- * Callers should treat SWITCH_FOREACH_OPT as they would a switch
- * statement over the value of `opt`. Each option given in `opts` (or
- * `lopts`) should be handled by a case statement as if it were inside
- * a switch statement.
- *
- * In addition to the options provided in opts the macro will handle
- * the "help" option and enforce a minimum number of non-option
- * command line pearameters as follows:
- *  -- if the user passes a -h or --help option. help will be printed,
- *     and the macro will cause the process to exit with code 0.
- *  -- if the user does not provided `num_required_opts` non-option
- *     arguments, the macro will cause the process to exit with code 2.
- *
- * Example:
- *
- * int main_foo(int argc, char **argv) {
- *     int opt;
- *
- *     SWITCH_FOREACH_OPT(opt, "blah", NULL, "foo", 0) {
- *      case 'b':
- *          ... handle b option...
- *          break;
- *      case 'l':
- *          ... handle l option ...
- *          break;
- *      case etc etc...
- *      }
- *      ... do something useful with the options ...
- * }
- */
-#define SWITCH_FOREACH_OPT(opt, opts, longopts,                         \
-                           commandname, num_required_opts)              \
-    while (((opt) = def_getopt(argc, argv, "h" opts, (longopts),          \
-                                (commandname), (num_required_opts))) != -1) \
-        switch (opt)
-
-static int set_memory_max(uint32_t domid, const char *mem)
-{
-    int64_t memorykb;
-
-    memorykb = parse_mem_size_kb(mem);
-    if (memorykb == -1) {
-        fprintf(stderr, "invalid memory size: %s\n", mem);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_domain_setmaxmem(ctx, domid, memorykb)) {
-        fprintf(stderr, "cannot set domid %u static max memory to : %s\n", domid, mem);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_memmax(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0;
-    char *mem;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "mem-max", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    mem = argv[optind + 1];
-
-    return set_memory_max(domid, mem);
-}
-
-static int set_memory_target(uint32_t domid, const char *mem)
-{
-    int64_t memorykb;
-
-    memorykb = parse_mem_size_kb(mem);
-    if (memorykb == -1)  {
-        fprintf(stderr, "invalid memory size: %s\n", mem);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_set_memory_target(ctx, domid, memorykb, 0, /* enforce */ 1)) {
-        fprintf(stderr, "cannot set domid %u dynamic max memory to : %s\n", domid, mem);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_memset(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0;
-    const char *mem;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "mem-set", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    mem = argv[optind + 1];
-
-    return set_memory_target(domid, mem);
-}
-
-static int cd_insert(uint32_t domid, const char *virtdev, char *phys)
-{
-    libxl_device_disk disk;
-    char *buf = NULL;
-    XLU_Config *config = 0;
-    struct stat b;
-    int r;
-
-    xasprintf(&buf, "vdev=%s,access=r,devtype=cdrom,target=%s",
-              virtdev, phys ? phys : "");
-
-    parse_disk_config(&config, buf, &disk);
-
-    /* ATM the existence of the backing file is not checked for qdisk
-     * in libxl_cdrom_insert() because RAW is used for remote
-     * protocols as well as plain files.  This will ideally be changed
-     * for 4.4, but this work-around fixes the problem of "cd-insert"
-     * returning success for non-existent files. */
-    if (disk.format != LIBXL_DISK_FORMAT_EMPTY
-        && stat(disk.pdev_path, &b)) {
-        fprintf(stderr, "Cannot stat file: %s\n",
-                disk.pdev_path);
-        r = 1;
-        goto out;
-    }
-
-    if (libxl_cdrom_insert(ctx, domid, &disk, NULL)) {
-        r = 1;
-        goto out;
-    }
-
-    r = 0;
-
-out:
-    libxl_device_disk_dispose(&disk);
-    free(buf);
-
-    return r;
-}
-
-int main_cd_eject(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0;
-    const char *virtdev;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cd-eject", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    virtdev = argv[optind + 1];
-
-    if (cd_insert(domid, virtdev, NULL))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_cd_insert(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0;
-    const char *virtdev;
-    char *file = NULL; /* modified by cd_insert tokenising it */
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cd-insert", 3) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    virtdev = argv[optind + 1];
-    file = argv[optind + 2];
-
-    if (cd_insert(domid, virtdev, file))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_usbctrl_attach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc = 0;
-    libxl_device_usbctrl usbctrl;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-attach", 1) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind++]);
-
-    libxl_device_usbctrl_init(&usbctrl);
-
-    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
-        if (parse_usbctrl_config(&usbctrl, *argv))
-            return 1;
-    }
-
-    rc = libxl_device_usbctrl_add(ctx, domid, &usbctrl, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_usbctrl_add failed.\n");
-        rc = 1;
-    }
-
-    libxl_device_usbctrl_dispose(&usbctrl);
-    return rc;
-}
-
-int main_usbctrl_detach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, devid, rc;
-    libxl_device_usbctrl usbctrl;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-detach", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    devid = atoi(argv[optind+1]);
-
-    libxl_device_usbctrl_init(&usbctrl);
-    if (libxl_devid_to_device_usbctrl(ctx, domid, devid, &usbctrl)) {
-        fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-        return 1;
-    }
-
-    rc = libxl_device_usbctrl_remove(ctx, domid, &usbctrl, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_usbctrl_remove failed.\n");
-        rc = 1;
-    }
-
-    libxl_device_usbctrl_dispose(&usbctrl);
-    return rc;
-
-}
-
-int main_usbdev_attach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc;
-    libxl_device_usbdev usbdev;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-attach", 2) {
-        /* No options */
-    }
-
-    libxl_device_usbdev_init(&usbdev);
-
-    domid = find_domain(argv[optind++]);
-
-    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
-        if (parse_usbdev_config(&usbdev, *argv))
-            return 1;
-    }
-
-    rc = libxl_device_usbdev_add(ctx, domid, &usbdev, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_usbdev_add failed.\n");
-        rc = 1;
-    }
-
-    libxl_device_usbdev_dispose(&usbdev);
-    return rc;
-}
-
-int main_usbdev_detach(int argc, char **argv)
-{
-    uint32_t domid;
-    int ctrl, port;
-    int opt, rc = 1;
-    libxl_device_usbdev usbdev;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-detach", 3) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    ctrl = atoi(argv[optind+1]);
-    port = atoi(argv[optind+2]);
-
-    if (argc - optind > 3) {
-        fprintf(stderr, "Invalid arguments.\n");
-        return 1;
-    }
-
-    libxl_device_usbdev_init(&usbdev);
-    if (libxl_ctrlport_to_device_usbdev(ctx, domid, ctrl, port, &usbdev)) {
-        fprintf(stderr, "Unknown device at controller %d port %d.\n",
-                ctrl, port);
-        return 1;
-    }
-
-    rc = libxl_device_usbdev_remove(ctx, domid, &usbdev, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_usbdev_remove failed.\n");
-        rc = 1;
-    }
-
-    libxl_device_usbdev_dispose(&usbdev);
-    return rc;
-}
-
-int main_usblist(int argc, char **argv)
-{
-    uint32_t domid;
-    libxl_device_usbctrl *usbctrls;
-    libxl_usbctrlinfo usbctrlinfo;
-    int numctrl, i, j, opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-list", 1) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind++]);
-
-    if (argc > optind) {
-        fprintf(stderr, "Invalid arguments.\n");
-        exit(-1);
-    }
-
-    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
-    if (!usbctrls) {
-        return 0;
-    }
-
-    for (i = 0; i < numctrl; ++i) {
-        printf("%-6s %-12s %-3s %-5s %-7s %-5s\n",
-                "Devid", "Type", "BE", "state", "usb-ver", "ports");
-
-        libxl_usbctrlinfo_init(&usbctrlinfo);
-
-        if (!libxl_device_usbctrl_getinfo(ctx, domid,
-                                &usbctrls[i], &usbctrlinfo)) {
-            printf("%-6d %-12s %-3d %-5d %-7d %-5d\n",
-                    usbctrlinfo.devid,
-                    libxl_usbctrl_type_to_string(usbctrlinfo.type),
-                    usbctrlinfo.backend_id, usbctrlinfo.state,
-                    usbctrlinfo.version, usbctrlinfo.ports);
-
-            for (j = 1; j <= usbctrlinfo.ports; j++) {
-                libxl_device_usbdev usbdev;
-
-                libxl_device_usbdev_init(&usbdev);
-
-                printf("  Port %d:", j);
-
-                if (!libxl_ctrlport_to_device_usbdev(ctx, domid,
-                                                     usbctrlinfo.devid,
-                                                     j, &usbdev)) {
-                    printf(" Bus %03x Device %03x\n",
-                           usbdev.u.hostdev.hostbus,
-                           usbdev.u.hostdev.hostaddr);
-                } else {
-                    printf("\n");
-                }
-
-                libxl_device_usbdev_dispose(&usbdev);
-            }
-        }
-
-        libxl_usbctrlinfo_dispose(&usbctrlinfo);
-    }
-
-    libxl_device_usbctrl_list_free(usbctrls, numctrl);
-    return 0;
-}
-
-int main_console(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0, num = 0;
-    libxl_console_type type = 0;
-
-    SWITCH_FOREACH_OPT(opt, "n:t:", NULL, "console", 1) {
-    case 't':
-        if (!strcmp(optarg, "pv"))
-            type = LIBXL_CONSOLE_TYPE_PV;
-        else if (!strcmp(optarg, "serial"))
-            type = LIBXL_CONSOLE_TYPE_SERIAL;
-        else {
-            fprintf(stderr, "console type supported are: pv, serial\n");
-            return EXIT_FAILURE;
-        }
-        break;
-    case 'n':
-        num = atoi(optarg);
-        break;
-    }
-
-    domid = find_domain(argv[optind]);
-    if (!type)
-        libxl_primary_console_exec(ctx, domid, -1);
-    else
-        libxl_console_exec(ctx, domid, num, type, -1);
-    fprintf(stderr, "Unable to attach console\n");
-    return EXIT_FAILURE;
-}
-
-int main_vncviewer(int argc, char **argv)
-{
-    static const struct option opts[] = {
-        {"autopass", 0, 0, 'a'},
-        {"vncviewer-autopass", 0, 0, 'a'},
-        COMMON_LONG_OPTS
-    };
-    uint32_t domid;
-    int opt, autopass = 0;
-
-    SWITCH_FOREACH_OPT(opt, "a", opts, "vncviewer", 1) {
-    case 'a':
-        autopass = 1;
-        break;
-    }
-
-    domid = find_domain(argv[optind]);
-
-    if (vncviewer(domid, autopass))
-        return EXIT_FAILURE;
-    return EXIT_SUCCESS;
-}
-
-static void pcilist(uint32_t domid)
-{
-    libxl_device_pci *pcidevs;
-    int num, i;
-
-    pcidevs = libxl_device_pci_list(ctx, domid, &num);
-    if (pcidevs == NULL)
-        return;
-    printf("Vdev Device\n");
-    for (i = 0; i < num; i++) {
-        printf("%02x.%01x %04x:%02x:%02x.%01x\n",
-               (pcidevs[i].vdevfn >> 3) & 0x1f, pcidevs[i].vdevfn & 0x7,
-               pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
-        libxl_device_pci_dispose(&pcidevs[i]);
-    }
-    free(pcidevs);
-}
-
-int main_pcilist(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-list", 1) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-
-    pcilist(domid);
-    return 0;
-}
-
-static int pcidetach(uint32_t domid, const char *bdf, int force)
-{
-    libxl_device_pci pcidev;
-    XLU_Config *config;
-    int r = 0;
-
-    libxl_device_pci_init(&pcidev);
-
-    config = xlu_cfg_init(stderr, "command line");
-    if (!config) { perror("xlu_cfg_inig"); exit(-1); }
-
-    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
-        fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
-        exit(2);
-    }
-    if (force) {
-        if (libxl_device_pci_destroy(ctx, domid, &pcidev, 0))
-            r = 1;
-    } else {
-        if (libxl_device_pci_remove(ctx, domid, &pcidev, 0))
-            r = 1;
-    }
-
-    libxl_device_pci_dispose(&pcidev);
-    xlu_cfg_destroy(config);
-
-    return r;
-}
-
-int main_pcidetach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    int force = 0;
-    const char *bdf = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "f", NULL, "pci-detach", 2) {
-    case 'f':
-        force = 1;
-        break;
-    }
-
-    domid = find_domain(argv[optind]);
-    bdf = argv[optind + 1];
-
-    if (pcidetach(domid, bdf, force))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-static int pciattach(uint32_t domid, const char *bdf, const char *vs)
-{
-    libxl_device_pci pcidev;
-    XLU_Config *config;
-    int r = 0;
-
-    libxl_device_pci_init(&pcidev);
-
-    config = xlu_cfg_init(stderr, "command line");
-    if (!config) { perror("xlu_cfg_inig"); exit(-1); }
-
-    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
-        fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
-        exit(2);
-    }
-
-    if (libxl_device_pci_add(ctx, domid, &pcidev, 0))
-        r = 1;
-
-    libxl_device_pci_dispose(&pcidev);
-    xlu_cfg_destroy(config);
-
-    return r;
-}
-
-int main_pciattach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    const char *bdf = NULL, *vs = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-attach", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    bdf = argv[optind + 1];
-
-    if (optind + 1 < argc)
-        vs = argv[optind + 2];
-
-    if (pciattach(domid, bdf, vs))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-static void pciassignable_list(void)
-{
-    libxl_device_pci *pcidevs;
-    int num, i;
-
-    pcidevs = libxl_device_pci_assignable_list(ctx, &num);
-
-    if ( pcidevs == NULL )
-        return;
-    for (i = 0; i < num; i++) {
-        printf("%04x:%02x:%02x.%01x\n",
-               pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
-        libxl_device_pci_dispose(&pcidevs[i]);
-    }
-    free(pcidevs);
-}
-
-int main_pciassignable_list(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-list", 0) {
-        /* No options */
-    }
-
-    pciassignable_list();
-    return 0;
-}
-
-static int pciassignable_add(const char *bdf, int rebind)
-{
-    libxl_device_pci pcidev;
-    XLU_Config *config;
-    int r = 0;
-
-    libxl_device_pci_init(&pcidev);
-
-    config = xlu_cfg_init(stderr, "command line");
-    if (!config) { perror("xlu_cfg_init"); exit(-1); }
-
-    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
-        fprintf(stderr, "pci-assignable-add: malformed BDF specification \"%s\"\n", bdf);
-        exit(2);
-    }
-
-    if (libxl_device_pci_assignable_add(ctx, &pcidev, rebind))
-        r = 1;
-
-    libxl_device_pci_dispose(&pcidev);
-    xlu_cfg_destroy(config);
-
-    return r;
-}
-
-int main_pciassignable_add(int argc, char **argv)
-{
-    int opt;
-    const char *bdf = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-add", 1) {
-        /* No options */
-    }
-
-    bdf = argv[optind];
-
-    if (pciassignable_add(bdf, 1))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-static int pciassignable_remove(const char *bdf, int rebind)
-{
-    libxl_device_pci pcidev;
-    XLU_Config *config;
-    int r = 0;
-
-    libxl_device_pci_init(&pcidev);
-
-    config = xlu_cfg_init(stderr, "command line");
-    if (!config) { perror("xlu_cfg_init"); exit(-1); }
-
-    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
-        fprintf(stderr, "pci-assignable-remove: malformed BDF specification \"%s\"\n", bdf);
-        exit(2);
-    }
-
-    if (libxl_device_pci_assignable_remove(ctx, &pcidev, rebind))
-        r = 1;
-
-    libxl_device_pci_dispose(&pcidev);
-    xlu_cfg_destroy(config);
-
-    return r;
-}
-
-int main_pciassignable_remove(int argc, char **argv)
-{
-    int opt;
-    const char *bdf = NULL;
-    int rebind = 0;
-
-    SWITCH_FOREACH_OPT(opt, "r", NULL, "pci-assignable-remove", 1) {
-    case 'r':
-        rebind=1;
-        break;
-    }
-
-    bdf = argv[optind];
-
-    if (pciassignable_remove(bdf, rebind))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-static void pause_domain(uint32_t domid)
-{
-    libxl_domain_pause(ctx, domid);
-}
-
-static void unpause_domain(uint32_t domid)
-{
-    libxl_domain_unpause(ctx, domid);
-}
-
-static void destroy_domain(uint32_t domid, int force)
-{
-    int rc;
-
-    if (domid == 0 && !force) {
-        fprintf(stderr, "Not destroying domain 0; use -f to force.\n"
-                        "This can only be done when using a disaggregated "
-                        "hardware domain and toolstack.\n\n");
-        exit(EXIT_FAILURE);
-    }
-    rc = libxl_domain_destroy(ctx, domid, 0);
-    if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n",rc); exit(EXIT_FAILURE); }
-}
-
-static void wait_for_domain_deaths(libxl_evgen_domain_death **deathws, int nr)
-{
-    int rc, count = 0;
-    LOG("Waiting for %d domains", nr);
-    while(1 && count < nr) {
-        libxl_event *event;
-        rc = libxl_event_wait(ctx, &event, LIBXL_EVENTMASK_ALL, 0,0);
-        if (rc) {
-            LOG("Failed to get event, quitting (rc=%d)", rc);
-            exit(EXIT_FAILURE);
-        }
-
-        switch (event->type) {
-        case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
-            LOG("Domain %d has been destroyed", event->domid);
-            libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
-            count++;
-            break;
-        case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
-            LOG("Domain %d has been shut down, reason code %d",
-                event->domid, event->u.domain_shutdown.shutdown_reason);
-            libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
-            count++;
-            break;
-        default:
-            LOG("Unexpected event type %d", event->type);
-            break;
-        }
-        libxl_event_free(ctx, event);
-    }
-}
-
-static void shutdown_domain(uint32_t domid,
-                            libxl_evgen_domain_death **deathw,
-                            libxl_ev_user for_user,
-                            int fallback_trigger)
-{
-    int rc;
-
-    fprintf(stderr, "Shutting down domain %u\n", domid);
-    rc=libxl_domain_shutdown(ctx, domid);
-    if (rc == ERROR_NOPARAVIRT) {
-        if (fallback_trigger) {
-            fprintf(stderr, "PV control interface not available:"
-                    " sending ACPI power button event.\n");
-            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_POWER, 0);
-        } else {
-            fprintf(stderr, "PV control interface not available:"
-                    " external graceful shutdown not possible.\n");
-            fprintf(stderr, "Use \"-F\" to fallback to ACPI power event.\n");
-        }
-    }
-
-    if (rc) {
-        fprintf(stderr,"shutdown failed (rc=%d)\n",rc);exit(EXIT_FAILURE);
-    }
-
-    if (deathw) {
-        rc = libxl_evenable_domain_death(ctx, domid, for_user, deathw);
-        if (rc) {
-            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
-            exit(EXIT_FAILURE);
-        }
-    }
-}
-
-static void reboot_domain(uint32_t domid, libxl_evgen_domain_death **deathw,
-                          libxl_ev_user for_user, int fallback_trigger)
-{
-    int rc;
-
-    fprintf(stderr, "Rebooting domain %u\n", domid);
-    rc=libxl_domain_reboot(ctx, domid);
-    if (rc == ERROR_NOPARAVIRT) {
-        if (fallback_trigger) {
-            fprintf(stderr, "PV control interface not available:"
-                    " sending ACPI reset button event.\n");
-            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_RESET, 0);
-        } else {
-            fprintf(stderr, "PV control interface not available:"
-                    " external graceful reboot not possible.\n");
-            fprintf(stderr, "Use \"-F\" to fallback to ACPI reset event.\n");
-        }
-    }
-    if (rc) {
-        fprintf(stderr,"reboot failed (rc=%d)\n",rc);exit(EXIT_FAILURE);
-    }
-
-    if (deathw) {
-        rc = libxl_evenable_domain_death(ctx, domid, for_user, deathw);
-        if (rc) {
-            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
-            exit(EXIT_FAILURE);
-        }
-    }
-}
-
-static void list_domains_details(const libxl_dominfo *info, int nb_domain)
-{
-    libxl_domain_config d_config;
-
-    int i, rc;
-
-    yajl_gen hand = NULL;
-    yajl_gen_status s;
-    const char *buf;
-    libxl_yajl_length yajl_len = 0;
-
-    if (default_output_format == OUTPUT_FORMAT_JSON) {
-        hand = libxl_yajl_gen_alloc(NULL);
-        if (!hand) {
-            fprintf(stderr, "unable to allocate JSON generator\n");
-            return;
-        }
-
-        s = yajl_gen_array_open(hand);
-        if (s != yajl_gen_status_ok)
-            goto out;
-    } else
-        s = yajl_gen_status_ok;
-
-    for (i = 0; i < nb_domain; i++) {
-        libxl_domain_config_init(&d_config);
-        rc = libxl_retrieve_domain_configuration(ctx, info[i].domid, &d_config);
-        if (rc)
-            continue;
-        if (default_output_format == OUTPUT_FORMAT_JSON)
-            s = printf_info_one_json(hand, info[i].domid, &d_config);
-        else
-            printf_info_sexp(info[i].domid, &d_config, stdout);
-        libxl_domain_config_dispose(&d_config);
-        if (s != yajl_gen_status_ok)
-            goto out;
-    }
-
-    if (default_output_format == OUTPUT_FORMAT_JSON) {
-        s = yajl_gen_array_close(hand);
-        if (s != yajl_gen_status_ok)
-            goto out;
-
-        s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &yajl_len);
-        if (s != yajl_gen_status_ok)
-            goto out;
-
-        puts(buf);
-    }
-
-out:
-    if (default_output_format == OUTPUT_FORMAT_JSON) {
-        yajl_gen_free(hand);
-        if (s != yajl_gen_status_ok)
-            fprintf(stderr,
-                    "unable to format domain config as JSON (YAJL:%d)\n", s);
-    }
-}
-
-static void print_bitmap(uint8_t *map, int maplen, FILE *stream)
-{
-    int i;
-    uint8_t pmap = 0, bitmask = 0;
-    int firstset = 0, state = 0;
-
-    for (i = 0; i < maplen; i++) {
-        if (i % 8 == 0) {
-            pmap = *map++;
-            bitmask = 1;
-        } else bitmask <<= 1;
-
-        switch (state) {
-        case 0:
-        case 2:
-            if ((pmap & bitmask) != 0) {
-                firstset = i;
-                state++;
-            }
-            continue;
-        case 1:
-        case 3:
-            if ((pmap & bitmask) == 0) {
-                fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
-                if (i - 1 > firstset)
-                    fprintf(stream, "-%d", i - 1);
-                state = 2;
-            }
-            continue;
-        }
-    }
-    switch (state) {
-        case 0:
-            fprintf(stream, "none");
-            break;
-        case 2:
-            break;
-        case 1:
-            if (firstset == 0) {
-                fprintf(stream, "all");
-                break;
-            }
-        case 3:
-            fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
-            if (i - 1 > firstset)
-                fprintf(stream, "-%d", i - 1);
-            break;
-    }
-}
-
-static void list_domains(bool verbose, bool context, bool claim, bool numa,
-                         bool cpupool, const libxl_dominfo *info, int nb_domain)
-{
-    int i;
-    static const char shutdown_reason_letters[]= "-rscwS";
-    libxl_bitmap nodemap;
-    libxl_physinfo physinfo;
-
-    libxl_bitmap_init(&nodemap);
-    libxl_physinfo_init(&physinfo);
-
-    printf("Name                                        ID   Mem VCPUs\tState\tTime(s)");
-    if (verbose) printf("   UUID                            Reason-Code\tSecurity Label");
-    if (context && !verbose) printf("   Security Label");
-    if (claim) printf("  Claimed");
-    if (cpupool) printf("         Cpupool");
-    if (numa) {
-        if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
-            fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
-            exit(EXIT_FAILURE);
-        }
-        if (libxl_get_physinfo(ctx, &physinfo) != 0) {
-            fprintf(stderr, "libxl_physinfo failed.\n");
-            libxl_bitmap_dispose(&nodemap);
-            exit(EXIT_FAILURE);
-        }
-
-        printf(" NODE Affinity");
-    }
-    printf("\n");
-    for (i = 0; i < nb_domain; i++) {
-        char *domname;
-        libxl_shutdown_reason shutdown_reason;
-        domname = libxl_domid_to_name(ctx, info[i].domid);
-        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
-        printf("%-40s %5d %5lu %5d     %c%c%c%c%c%c  %8.1f",
-                domname,
-                info[i].domid,
-                (unsigned long) ((info[i].current_memkb +
-                    info[i].outstanding_memkb)/ 1024),
-                info[i].vcpu_online,
-                info[i].running ? 'r' : '-',
-                info[i].blocked ? 'b' : '-',
-                info[i].paused ? 'p' : '-',
-                info[i].shutdown ? 's' : '-',
-                (shutdown_reason >= 0 &&
-                 shutdown_reason < sizeof(shutdown_reason_letters)-1
-                 ? shutdown_reason_letters[shutdown_reason] : '?'),
-                info[i].dying ? 'd' : '-',
-                ((float)info[i].cpu_time / 1e9));
-        free(domname);
-        if (verbose) {
-            printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
-            if (info[i].shutdown) printf(" %8x", shutdown_reason);
-            else printf(" %8s", "-");
-        }
-        if (claim)
-            printf(" %5lu", (unsigned long)info[i].outstanding_memkb / 1024);
-        if (verbose || context)
-            printf(" %16s", info[i].ssid_label ? : "-");
-        if (cpupool) {
-            char *poolname = libxl_cpupoolid_to_name(ctx, info[i].cpupool);
-            printf("%16s", poolname);
-            free(poolname);
-        }
-        if (numa) {
-            libxl_domain_get_nodeaffinity(ctx, info[i].domid, &nodemap);
-
-            putchar(' ');
-            print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
-        }
-        putchar('\n');
-    }
-
-    libxl_bitmap_dispose(&nodemap);
-    libxl_physinfo_dispose(&physinfo);
-}
-
-static void list_vm(void)
-{
-    libxl_vminfo *info;
-    char *domname;
-    int nb_vm, i;
-
-    info = libxl_list_vm(ctx, &nb_vm);
-
-    if (!info) {
-        fprintf(stderr, "libxl_list_vm failed.\n");
-        exit(EXIT_FAILURE);
-    }
-    printf("UUID                                  ID    name\n");
-    for (i = 0; i < nb_vm; i++) {
-        domname = libxl_domid_to_name(ctx, info[i].domid);
-        printf(LIBXL_UUID_FMT "  %d    %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
-            info[i].domid, domname);
-        free(domname);
-    }
-    libxl_vminfo_list_free(info, nb_vm);
-}
-
-static void core_dump_domain(uint32_t domid, const char *filename)
-{
-    int rc;
-
-    rc=libxl_domain_core_dump(ctx, domid, filename, NULL);
-    if (rc) { fprintf(stderr,"core dump failed (rc=%d)\n",rc);exit(EXIT_FAILURE); }
-}
-
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-static void save_domain_core_begin(uint32_t domid,
-                                   const char *override_config_file,
-                                   uint8_t **config_data_r,
-                                   int *config_len_r)
-{
-    int rc;
-    libxl_domain_config d_config;
-    char *config_c = 0;
-
-    /* configuration file in optional data: */
-
-    libxl_domain_config_init(&d_config);
-
-    if (override_config_file) {
-        void *config_v = 0;
-        rc = libxl_read_file_contents(ctx, override_config_file,
-                                      &config_v, config_len_r);
-        if (rc) {
-            fprintf(stderr, "unable to read overridden config file\n");
-            exit(EXIT_FAILURE);
-        }
-        parse_config_data(override_config_file, config_v, *config_len_r,
-                          &d_config);
-        free(config_v);
-    } else {
-        rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config);
-        if (rc) {
-            fprintf(stderr, "unable to retrieve domain configuration\n");
-            exit(EXIT_FAILURE);
-        }
-    }
-
-    config_c = libxl_domain_config_to_json(ctx, &d_config);
-    if (!config_c) {
-        fprintf(stderr, "unable to convert config file to JSON\n");
-        exit(EXIT_FAILURE);
-    }
-    *config_data_r = (uint8_t *)config_c;
-    *config_len_r = strlen(config_c) + 1; /* including trailing '\0' */
-
-    libxl_domain_config_dispose(&d_config);
-}
-
-static void save_domain_core_writeconfig(int fd, const char *source,
-                                  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;
-    hdr.mandatory_flags = XL_MANDATORY_FLAG_STREAMv2;
-
-    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);
-    if (config_len)
-        hdr.mandatory_flags |= XL_MANDATORY_FLAG_JSON;
-
-    /* that's the optional data */
-
-    CHK_ERRNOVAL(libxl_write_exactly(
-                     ctx, fd, &hdr, sizeof(hdr), source, "header"));
-    CHK_ERRNOVAL(libxl_write_exactly(
-                     ctx, fd, optdata_begin, hdr.optional_data_len,
-                     source, "header"));
-
-    free(optdata_begin);
-
-    fprintf(stderr, "Saving to %s new xl format (info"
-            " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
-            source, hdr.mandatory_flags, hdr.optional_flags,
-            hdr.optional_data_len);
-}
-
-static int save_domain(uint32_t domid, const char *filename, int checkpoint,
-                            int leavepaused, const char *override_config_file)
-{
-    int fd;
-    uint8_t *config_data;
-    int config_len;
-
-    save_domain_core_begin(domid, 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(EXIT_FAILURE);
-    }
-
-    save_domain_core_writeconfig(fd, filename, config_data, config_len);
-
-    int rc = libxl_domain_suspend(ctx, domid, fd, 0, NULL);
-    close(fd);
-
-    if (rc < 0) {
-        fprintf(stderr, "Failed to save domain, resuming domain\n");
-        libxl_domain_resume(ctx, domid, 1, 0);
-    }
-    else if (leavepaused || checkpoint) {
-        if (leavepaused)
-            libxl_domain_pause(ctx, domid);
-        libxl_domain_resume(ctx, domid, 1, 0);
-    }
-    else
-        libxl_domain_destroy(ctx, domid, 0);
-
-    exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
-}
-
-static pid_t create_migration_child(const char *rune, int *send_fd,
-                                        int *recv_fd)
-{
-    int sendpipe[2], recvpipe[2];
-    pid_t child;
-
-    if (!rune || !send_fd || !recv_fd)
-        return -1;
-
-    MUST( libxl_pipe(ctx, sendpipe) );
-    MUST( libxl_pipe(ctx, recvpipe) );
-
-    child = xl_fork(child_migration, "migration transport process");
-
-    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(EXIT_FAILURE);
-    }
-
-    close(sendpipe[0]);
-    close(recvpipe[1]);
-    *send_fd = sendpipe[1];
-    *recv_fd = recvpipe[0];
-
-    /* if receiver dies, we get an error and can clean up
-       rather than just dying */
-    signal(SIGPIPE, SIG_IGN);
-
-    return child;
-}
-
-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 1;
-
-    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 1;
-    }
-    return 0;
-}
-
-static void migration_child_report(int recv_fd) {
-    pid_t child;
-    int status, sr;
-    struct timeval now, waituntil, timeout;
-    static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
-
-    if (!xl_child_pid(child_migration)) return;
-
-    CHK_SYSCALL(gettimeofday(&waituntil, 0));
-    waituntil.tv_sec += 2;
-
-    for (;;) {
-        pid_t migration_child = xl_child_pid(child_migration);
-        child = xl_waitpid(child_migration, &status, WNOHANG);
-
-        if (child == migration_child) {
-            if (status)
-                xl_report_child_exitstatus(XTL_INFO, child_migration,
-                                           migration_child, status);
-            break;
-        }
-        if (child == -1) {
-            fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
-                    (long)migration_child, strerror(errno));
-            break;
-        }
-        assert(child == 0);
-
-        CHK_SYSCALL(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;
-            }
-        }
-    }
-}
-
-static void migrate_do_preamble(int send_fd, int recv_fd, pid_t child,
-                                uint8_t *config_data, int config_len,
-                                const char *rune)
-{
-    int rc = 0;
-
-    if (send_fd < 0 || recv_fd < 0) {
-        fprintf(stderr, "migrate_do_preamble: invalid file descriptors\n");
-        exit(EXIT_FAILURE);
-    }
-
-    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
-                                   sizeof(migrate_receiver_banner)-1,
-                                   "banner", rune);
-    if (rc) {
-        close(send_fd);
-        migration_child_report(recv_fd);
-        exit(EXIT_FAILURE);
-    }
-
-    save_domain_core_writeconfig(send_fd, "migration stream",
-                                 config_data, config_len);
-
-}
-
-static void migrate_domain(uint32_t domid, const char *rune, int debug,
-                           const char *override_config_file)
-{
-    pid_t child = -1;
-    int rc;
-    int send_fd = -1, recv_fd = -1;
-    char *away_domname;
-    char rc_buf;
-    uint8_t *config_data;
-    int config_len, flags = LIBXL_SUSPEND_LIVE;
-
-    save_domain_core_begin(domid, override_config_file,
-                           &config_data, &config_len);
-
-    if (!config_len) {
-        fprintf(stderr, "No config file stored for running domain and "
-                "none supplied - cannot migrate.\n");
-        exit(EXIT_FAILURE);
-    }
-
-    child = create_migration_child(rune, &send_fd, &recv_fd);
-
-    migrate_do_preamble(send_fd, recv_fd, child, config_data, config_len,
-                        rune);
-
-    xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
-
-    if (debug)
-        flags |= LIBXL_SUSPEND_DEBUG;
-    rc = libxl_domain_suspend(ctx, domid, send_fd, flags, NULL);
-    if (rc) {
-        fprintf(stderr, "migration sender: libxl_domain_suspend failed"
-                " (rc=%d)\n", rc);
-        if (rc == ERROR_GUEST_TIMEDOUT)
-            goto failed_suspend;
-        else
-            goto failed_resume;
-    }
-
-    //fprintf(stderr, "migration sender: Transfer complete.\n");
-    // Should only be printed when debugging as it's a bit messy with
-    // progress indication.
-
-    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
-                                   sizeof(migrate_receiver_ready),
-                                   "ready message", rune);
-    if (rc) goto failed_resume;
-
-    xtl_stdiostream_adjust_flags(logger, 0, XTL_STDIOSTREAM_HIDE_PROGRESS);
-
-    /* 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) {
-        xasprintf(&away_domname, "%s--migratedaway", common_domname);
-        rc = libxl_domain_rename(ctx, domid, common_domname, away_domname);
-        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);
-        }
-        rc = libxl_domain_resume(ctx, domid, 1, 0);
-        if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
-
-        fprintf(stderr, "Migration failed due to problems at target.\n");
-        exit(EXIT_FAILURE);
-    }
-
-    fprintf(stderr, "migration sender: Target reports successful startup.\n");
-    libxl_domain_destroy(ctx, domid, 0); /* bang! */
-    fprintf(stderr, "Migration successful.\n");
-    exit(EXIT_SUCCESS);
-
- failed_suspend:
-    close(send_fd);
-    migration_child_report(recv_fd);
-    fprintf(stderr, "Migration failed, failed to suspend at sender.\n");
-    exit(EXIT_FAILURE);
-
- failed_resume:
-    close(send_fd);
-    migration_child_report(recv_fd);
-    fprintf(stderr, "Migration failed, resuming at sender.\n");
-    libxl_domain_resume(ctx, domid, 1, 0);
-    exit(EXIT_FAILURE);
-
- 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(recv_fd);
-    exit(EXIT_FAILURE);
-}
-
-static void migrate_receive(int debug, int daemonize, int monitor,
-                            int pause_after_migration,
-                            int send_fd, int recv_fd,
-                            libxl_checkpointed_stream checkpointed,
-                            char *colo_proxy_script)
-{
-    uint32_t domid;
-    int rc, rc2;
-    char rc_buf;
-    char *migration_domname;
-    struct domain_create dom_info;
-
-    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_ERRNOVAL(libxl_write_exactly(
-                     ctx, send_fd, migrate_receiver_banner,
-                     sizeof(migrate_receiver_banner)-1,
-                     "migration ack stream", "banner") );
-
-    memset(&dom_info, 0, sizeof(dom_info));
-    dom_info.debug = debug;
-    dom_info.daemonize = daemonize;
-    dom_info.monitor = monitor;
-    dom_info.paused = 1;
-    dom_info.migrate_fd = recv_fd;
-    dom_info.send_back_fd = send_fd;
-    dom_info.migration_domname_r = &migration_domname;
-    dom_info.checkpointed_stream = checkpointed;
-    dom_info.colo_proxy_script = colo_proxy_script;
-
-    rc = create_domain(&dom_info);
-    if (rc < 0) {
-        fprintf(stderr, "migration target: Domain creation failed"
-                " (code %d).\n", rc);
-        exit(EXIT_FAILURE);
-    }
-
-    domid = rc;
-
-    switch (checkpointed) {
-    case LIBXL_CHECKPOINTED_STREAM_REMUS:
-    case LIBXL_CHECKPOINTED_STREAM_COLO:
-    {
-        const char *ha = checkpointed == LIBXL_CHECKPOINTED_STREAM_COLO ?
-                         "COLO" : "Remus";
-        /* If we are here, it means that the sender (primary) has crashed.
-         * TODO: Split-Brain Check.
-         */
-        fprintf(stderr, "migration target: %s Failover for domain %u\n",
-                ha, domid);
-
-        /*
-         * If domain renaming fails, lets just continue (as we need the domain
-         * to be up & dom names may not matter much, as long as its reachable
-         * over network).
-         *
-         * If domain unpausing fails, destroy domain ? Or is it better to have
-         * a consistent copy of the domain (memory, cpu state, disk)
-         * on atleast one physical host ? Right now, lets just leave the domain
-         * as is and let the Administrator decide (or troubleshoot).
-         */
-        if (migration_domname) {
-            rc = libxl_domain_rename(ctx, domid, migration_domname,
-                                     common_domname);
-            if (rc)
-                fprintf(stderr, "migration target (%s): "
-                        "Failed to rename domain from %s to %s:%d\n",
-                        ha, migration_domname, common_domname, rc);
-        }
-
-        if (checkpointed == LIBXL_CHECKPOINTED_STREAM_COLO)
-            /* The guest is running after failover in COLO mode */
-            exit(rc ? -ERROR_FAIL: 0);
-
-        rc = libxl_domain_unpause(ctx, domid);
-        if (rc)
-            fprintf(stderr, "migration target (%s): "
-                    "Failed to unpause domain %s (id: %u):%d\n",
-                    ha, common_domname, domid, rc);
-
-        exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
-    }
-    default:
-        /* do nothing */
-        break;
-    }
-
-    fprintf(stderr, "migration target: Transfer complete,"
-            " requesting permission to start domain.\n");
-
-    rc = libxl_write_exactly(ctx, send_fd,
-                             migrate_receiver_ready,
-                             sizeof(migrate_receiver_ready),
-                             "migration ack stream", "ready message");
-    if (rc) exit(EXIT_FAILURE);
-
-    rc = migrate_read_fixedmessage(recv_fd, 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);
-        if (rc) goto perhaps_destroy_notify_rc;
-    }
-
-    if (!pause_after_migration) {
-        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, send_fd,
-                              migrate_report, sizeof(migrate_report),
-                              "migration ack stream",
-                              "success/failure report");
-    if (rc2) exit(EXIT_FAILURE);
-
-    rc_buf = -rc;
-    assert(!!rc_buf == !!rc);
-    rc2 = libxl_write_exactly(ctx, send_fd, &rc_buf, 1,
-                              "migration ack stream",
-                              "success/failure code");
-    if (rc2) exit(EXIT_FAILURE);
-
-    if (rc) {
-        fprintf(stderr, "migration target: Failure, destroying our copy.\n");
-
-        rc2 = libxl_domain_destroy(ctx, domid, 0);
-        if (rc2) {
-            fprintf(stderr, "migration target: Failed to destroy our copy"
-                    " (code %d).\n", rc2);
-            exit(EXIT_FAILURE);
-        }
-
-        fprintf(stderr, "migration target: Cleanup OK, granting sender"
-                " permission to resume.\n");
-
-        rc2 = libxl_write_exactly(ctx, send_fd,
-                                  migrate_permission_to_go,
-                                  sizeof(migrate_permission_to_go),
-                                  "migration ack stream",
-                                  "permission to sender to have domain back");
-        if (rc2) exit(EXIT_FAILURE);
-    }
-
-    exit(EXIT_SUCCESS);
-}
-
-int main_restore(int argc, char **argv)
-{
-    const char *checkpoint_file = NULL;
-    const char *config_file = NULL;
-    struct domain_create dom_info;
-    int paused = 0, debug = 0, daemonize = 1, monitor = 1,
-        console_autoconnect = 0, vnc = 0, vncautopass = 0;
-    int opt, rc;
-    static struct option opts[] = {
-        {"vncviewer", 0, 0, 'V'},
-        {"vncviewer-autopass", 0, 0, 'A'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "FcpdeVA", opts, "restore", 1) {
-    case 'c':
-        console_autoconnect = 1;
-        break;
-    case 'p':
-        paused = 1;
-        break;
-    case 'd':
-        debug = 1;
-        break;
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'e':
-        daemonize = 0;
-        monitor = 0;
-        break;
-    case 'V':
-        vnc = 1;
-        break;
-    case 'A':
-        vnc = vncautopass = 1;
-        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");
-        return EXIT_FAILURE;
-    }
-
-    memset(&dom_info, 0, sizeof(dom_info));
-    dom_info.debug = debug;
-    dom_info.daemonize = daemonize;
-    dom_info.monitor = monitor;
-    dom_info.paused = paused;
-    dom_info.config_file = config_file;
-    dom_info.restore_file = checkpoint_file;
-    dom_info.migrate_fd = -1;
-    dom_info.send_back_fd = -1;
-    dom_info.vnc = vnc;
-    dom_info.vncautopass = vncautopass;
-    dom_info.console_autoconnect = console_autoconnect;
-
-    rc = create_domain(&dom_info);
-    if (rc < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_migrate_receive(int argc, char **argv)
-{
-    int debug = 0, daemonize = 1, monitor = 1, pause_after_migration = 0;
-    libxl_checkpointed_stream checkpointed = LIBXL_CHECKPOINTED_STREAM_NONE;
-    int opt;
-    char *script = NULL;
-    static struct option opts[] = {
-        {"colo", 0, 0, 0x100},
-        /* It is a shame that the management code for disk is not here. */
-        {"coloft-script", 1, 0, 0x200},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "Fedrp", opts, "migrate-receive", 0) {
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'e':
-        daemonize = 0;
-        monitor = 0;
-        break;
-    case 'd':
-        debug = 1;
-        break;
-    case 'r':
-        checkpointed = LIBXL_CHECKPOINTED_STREAM_REMUS;
-        break;
-    case 0x100:
-        checkpointed = LIBXL_CHECKPOINTED_STREAM_COLO;
-        break;
-    case 0x200:
-        script = optarg;
-        break;
-    case 'p':
-        pause_after_migration = 1;
-        break;
-    }
-
-    if (argc-optind != 0) {
-        help("migrate-receive");
-        return EXIT_FAILURE;
-    }
-    migrate_receive(debug, daemonize, monitor, pause_after_migration,
-                    STDOUT_FILENO, STDIN_FILENO,
-                    checkpointed, script);
-
-    return EXIT_SUCCESS;
-}
-
-int main_save(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *filename;
-    const char *config_filename = NULL;
-    int checkpoint = 0;
-    int leavepaused = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "cp", NULL, "save", 2) {
-    case 'c':
-        checkpoint = 1;
-        break;
-    case 'p':
-        leavepaused = 1;
-        break;
-    }
-
-    if (argc-optind > 3) {
-        help("save");
-        return EXIT_FAILURE;
-    }
-
-    domid = find_domain(argv[optind]);
-    filename = argv[optind + 1];
-    if ( argc - optind >= 3 )
-        config_filename = argv[optind + 2];
-
-    save_domain(domid, filename, checkpoint, leavepaused, config_filename);
-    return EXIT_SUCCESS;
-}
-
-int main_migrate(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *config_filename = NULL;
-    const char *ssh_command = "ssh";
-    char *rune = NULL;
-    char *host;
-    int opt, daemonize = 1, monitor = 1, debug = 0, pause_after_migration = 0;
-    static struct option opts[] = {
-        {"debug", 0, 0, 0x100},
-        {"live", 0, 0, 0x200},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "FC:s:ep", opts, "migrate", 2) {
-    case 'C':
-        config_filename = optarg;
-        break;
-    case 's':
-        ssh_command = optarg;
-        break;
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'e':
-        daemonize = 0;
-        monitor = 0;
-        break;
-    case 'p':
-        pause_after_migration = 1;
-        break;
-    case 0x100: /* --debug */
-        debug = 1;
-        break;
-    case 0x200: /* --live */
-        /* ignored for compatibility with xm */
-        break;
-    }
-
-    domid = find_domain(argv[optind]);
-    host = argv[optind + 1];
-
-    bool pass_tty_arg = progress_use_cr || (isatty(2) > 0);
-
-    if (!ssh_command[0]) {
-        rune= host;
-    } else {
-        char verbose_buf[minmsglevel_default+3];
-        int verbose_len;
-        verbose_buf[0] = ' ';
-        verbose_buf[1] = '-';
-        memset(verbose_buf+2, 'v', minmsglevel_default);
-        verbose_buf[sizeof(verbose_buf)-1] = 0;
-        if (minmsglevel == minmsglevel_default) {
-            verbose_len = 0;
-        } else {
-            verbose_len = (minmsglevel_default - minmsglevel) + 2;
-        }
-        xasprintf(&rune, "exec %s %s xl%s%.*s migrate-receive%s%s%s",
-                  ssh_command, host,
-                  pass_tty_arg ? " -t" : "",
-                  verbose_len, verbose_buf,
-                  daemonize ? "" : " -e",
-                  debug ? " -d" : "",
-                  pause_after_migration ? " -p" : "");
-    }
-
-    migrate_domain(domid, rune, debug, config_filename);
-    return EXIT_SUCCESS;
-}
-#endif
-
-int main_dump_core(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "dump-core", 2) {
-        /* No options */
-    }
-
-    core_dump_domain(find_domain(argv[optind]), argv[optind + 1]);
-    return EXIT_SUCCESS;
-}
-
-int main_pause(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pause", 1) {
-        /* No options */
-    }
-
-    pause_domain(find_domain(argv[optind]));
-
-    return EXIT_SUCCESS;
-}
-
-int main_unpause(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "unpause", 1) {
-        /* No options */
-    }
-
-    unpause_domain(find_domain(argv[optind]));
-
-    return EXIT_SUCCESS;
-}
-
-int main_destroy(int argc, char **argv)
-{
-    int opt;
-    int force = 0;
-
-    SWITCH_FOREACH_OPT(opt, "f", NULL, "destroy", 1) {
-    case 'f':
-        force = 1;
-        break;
-    }
-
-    destroy_domain(find_domain(argv[optind]), force);
-    return EXIT_SUCCESS;
-}
-
-static int main_shutdown_or_reboot(int do_reboot, int argc, char **argv)
-{
-    const char *what = do_reboot ? "reboot" : "shutdown";
-    void (*fn)(uint32_t domid,
-               libxl_evgen_domain_death **, libxl_ev_user, int) =
-        do_reboot ? &reboot_domain : &shutdown_domain;
-    int opt, i, nb_domain;
-    int wait_for_it = 0, all = 0, nrdeathws = 0;
-    int fallback_trigger = 0;
-    static struct option opts[] = {
-        {"all", 0, 0, 'a'},
-        {"wait", 0, 0, 'w'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "awF", opts, what, 0) {
-    case 'a':
-        all = 1;
-        break;
-    case 'w':
-        wait_for_it = 1;
-        break;
-    case 'F':
-        fallback_trigger = 1;
-        break;
-    }
-
-    if (!argv[optind] && !all) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        return EXIT_FAILURE;
-    }
-
-    if (all) {
-        libxl_dominfo *dominfo;
-        libxl_evgen_domain_death **deathws = NULL;
-        if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            return EXIT_FAILURE;
-        }
-
-        if (wait_for_it)
-            deathws = calloc(nb_domain, sizeof(*deathws));
-
-        for (i = 0; i<nb_domain; i++) {
-            if (dominfo[i].domid == 0 || dominfo[i].never_stop)
-                continue;
-            fn(dominfo[i].domid, deathws ? &deathws[i] : NULL, i,
-               fallback_trigger);
-            nrdeathws++;
-        }
-
-        if (deathws) {
-            wait_for_domain_deaths(deathws, nrdeathws);
-            free(deathws);
-        }
-
-        libxl_dominfo_list_free(dominfo, nb_domain);
-    } else {
-        libxl_evgen_domain_death *deathw = NULL;
-        uint32_t domid = find_domain(argv[optind]);
-
-        fn(domid, wait_for_it ? &deathw : NULL, 0, fallback_trigger);
-
-        if (wait_for_it)
-            wait_for_domain_deaths(&deathw, 1);
-    }
-
-
-    return EXIT_SUCCESS;
-}
-
-int main_shutdown(int argc, char **argv)
-{
-    return main_shutdown_or_reboot(0, argc, argv);
-}
-
-int main_reboot(int argc, char **argv)
-{
-    return main_shutdown_or_reboot(1, argc, argv);
-}
-
-int main_list(int argc, char **argv)
-{
-    int opt;
-    bool verbose = false;
-    bool context = false;
-    bool details = false;
-    bool cpupool = false;
-    bool numa = false;
-    static struct option opts[] = {
-        {"long", 0, 0, 'l'},
-        {"verbose", 0, 0, 'v'},
-        {"context", 0, 0, 'Z'},
-        {"cpupool", 0, 0, 'c'},
-        {"numa", 0, 0, 'n'},
-        COMMON_LONG_OPTS
-    };
-
-    libxl_dominfo info_buf;
-    libxl_dominfo *info, *info_free=0;
-    int nb_domain, rc;
-
-    SWITCH_FOREACH_OPT(opt, "lvhZcn", opts, "list", 0) {
-    case 'l':
-        details = true;
-        break;
-    case 'v':
-        verbose = true;
-        break;
-    case 'Z':
-        context = true;
-        break;
-    case 'c':
-        cpupool = true;
-        break;
-    case 'n':
-        numa = true;
-        break;
-    }
-
-    libxl_dominfo_init(&info_buf);
-
-    if (optind >= argc) {
-        info = libxl_list_domain(ctx, &nb_domain);
-        if (!info) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            return EXIT_FAILURE;
-        }
-        info_free = info;
-    } else if (optind == argc-1) {
-        uint32_t domid = find_domain(argv[optind]);
-        rc = libxl_domain_info(ctx, &info_buf, domid);
-        if (rc == ERROR_DOMAIN_NOTFOUND) {
-            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
-                argv[optind]);
-            return EXIT_FAILURE;
-        }
-        if (rc) {
-            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
-            return EXIT_FAILURE;
-        }
-        info = &info_buf;
-        nb_domain = 1;
-    } else {
-        help("list");
-        return EXIT_FAILURE;
-    }
-
-    if (details)
-        list_domains_details(info, nb_domain);
-    else
-        list_domains(verbose, context, false /* claim */, numa, cpupool,
-                     info, nb_domain);
-
-    if (info_free)
-        libxl_dominfo_list_free(info, nb_domain);
-
-    libxl_dominfo_dispose(&info_buf);
-
-    return EXIT_SUCCESS;
-}
-
-int main_vm_list(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vm-list", 0) {
-        /* No options */
-    }
-
-    list_vm();
-    return EXIT_SUCCESS;
-}
-
-static void string_realloc_append(char **accumulate, const char *more)
-{
-    /* Appends more to accumulate.  Accumulate is either NULL, or
-     * points (always) to a malloc'd nul-terminated string. */
-
-    size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
-    size_t morelen = strlen(more) + 1/*nul*/;
-    if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
-        fprintf(stderr,"Additional config data far too large\n");
-        exit(-ERROR_FAIL);
-    }
-
-    *accumulate = xrealloc(*accumulate, oldlen + morelen);
-    memcpy(*accumulate + oldlen, more, morelen);
-}
-
-int main_create(int argc, char **argv)
-{
-    const char *filename = NULL;
-    struct domain_create dom_info;
-    int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
-        quiet = 0, monitor = 1, vnc = 0, vncautopass = 0;
-    int opt, rc;
-    static struct option opts[] = {
-        {"dryrun", 0, 0, 'n'},
-        {"quiet", 0, 0, 'q'},
-        {"defconfig", 1, 0, 'f'},
-        {"vncviewer", 0, 0, 'V'},
-        {"vncviewer-autopass", 0, 0, 'A'},
-        COMMON_LONG_OPTS
-    };
-
-    dom_info.extra_config = NULL;
-
-    if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
-        filename = argv[1];
-        argc--; argv++;
-    }
-
-    SWITCH_FOREACH_OPT(opt, "Fnqf:pcdeVA", opts, "create", 0) {
-    case 'f':
-        filename = optarg;
-        break;
-    case 'p':
-        paused = 1;
-        break;
-    case 'c':
-        console_autoconnect = 1;
-        break;
-    case 'd':
-        debug = 1;
-        break;
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'e':
-        daemonize = 0;
-        monitor = 0;
-        break;
-    case 'n':
-        dryrun_only = 1;
-        break;
-    case 'q':
-        quiet = 1;
-        break;
-    case 'V':
-        vnc = 1;
-        break;
-    case 'A':
-        vnc = vncautopass = 1;
-        break;
-    }
-
-    memset(&dom_info, 0, sizeof(dom_info));
-
-    for (; optind < argc; optind++) {
-        if (strchr(argv[optind], '=') != NULL) {
-            string_realloc_append(&dom_info.extra_config, argv[optind]);
-            string_realloc_append(&dom_info.extra_config, "\n");
-        } else if (!filename) {
-            filename = argv[optind];
-        } else {
-            help("create");
-            free(dom_info.extra_config);
-            return 2;
-        }
-    }
-
-    dom_info.debug = debug;
-    dom_info.daemonize = daemonize;
-    dom_info.monitor = monitor;
-    dom_info.paused = paused;
-    dom_info.dryrun = dryrun_only;
-    dom_info.quiet = quiet;
-    dom_info.config_file = filename;
-    dom_info.migrate_fd = -1;
-    dom_info.send_back_fd = -1;
-    dom_info.vnc = vnc;
-    dom_info.vncautopass = vncautopass;
-    dom_info.console_autoconnect = console_autoconnect;
-
-    rc = create_domain(&dom_info);
-    if (rc < 0) {
-        free(dom_info.extra_config);
-        return -rc;
-    }
-
-    free(dom_info.extra_config);
-    return 0;
-}
-
-int main_config_update(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *filename = NULL;
-    char *extra_config = NULL;
-    void *config_data = 0;
-    int config_len = 0;
-    libxl_domain_config d_config;
-    int opt, rc;
-    int debug = 0;
-    static struct option opts[] = {
-        {"defconfig", 1, 0, 'f'},
-        COMMON_LONG_OPTS
-    };
-
-    if (argc < 2) {
-        fprintf(stderr, "xl config-update requires a domain argument\n");
-        help("config-update");
-        exit(1);
-    }
-
-    fprintf(stderr, "WARNING: xl now has better capability to manage domain configuration, "
-            "avoid using this command when possible\n");
-
-    domid = find_domain(argv[1]);
-    argc--; argv++;
-
-    if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
-        filename = argv[1];
-        argc--; argv++;
-    }
-
-    SWITCH_FOREACH_OPT(opt, "dqf:", opts, "config_update", 0) {
-    case 'd':
-        debug = 1;
-        break;
-    case 'f':
-        filename = optarg;
-        break;
-    }
-
-    for (; optind < argc; optind++) {
-        if (strchr(argv[optind], '=') != NULL) {
-            string_realloc_append(&extra_config, argv[optind]);
-            string_realloc_append(&extra_config, "\n");
-        } else if (!filename) {
-            filename = argv[optind];
-        } else {
-            help("create");
-            free(extra_config);
-            return 2;
-        }
-    }
-    if (filename) {
-        free(config_data);  config_data = 0;
-        rc = libxl_read_file_contents(ctx, filename,
-                                      &config_data, &config_len);
-        if (rc) { fprintf(stderr, "Failed to read config file: %s: %s\n",
-                           filename, strerror(errno));
-                  free(extra_config); return ERROR_FAIL; }
-        if (extra_config && strlen(extra_config)) {
-            if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
-                fprintf(stderr, "Failed to attach extra configuration\n");
-                exit(1);
-            }
-            /* allocate space for the extra config plus two EOLs plus \0 */
-            config_data = realloc(config_data, config_len
-                + strlen(extra_config) + 2 + 1);
-            if (!config_data) {
-                fprintf(stderr, "Failed to realloc config_data\n");
-                exit(1);
-            }
-            config_len += sprintf(config_data + config_len, "\n%s\n",
-                extra_config);
-        }
-    } else {
-        fprintf(stderr, "Config file not specified\n");
-        exit(1);
-    }
-
-    libxl_domain_config_init(&d_config);
-
-    parse_config_data(filename, config_data, config_len, &d_config);
-
-    if (debug || dryrun_only)
-        printf_info(default_output_format, -1, &d_config, stdout);
-
-    if (!dryrun_only) {
-        fprintf(stderr, "setting dom%u configuration\n", domid);
-        rc = libxl_userdata_store(ctx, domid, "xl",
-                                   config_data, config_len);
-        if (rc) {
-            fprintf(stderr, "failed to update configuration\n");
-            exit(1);
-        }
-    }
-
-    libxl_domain_config_dispose(&d_config);
-
-    free(config_data);
-    free(extra_config);
-    return 0;
-}
-
-static void button_press(uint32_t domid, const char *b)
-{
-    libxl_trigger trigger;
-
-    if (!strcmp(b, "power")) {
-        trigger = LIBXL_TRIGGER_POWER;
-    } else if (!strcmp(b, "sleep")) {
-        trigger = LIBXL_TRIGGER_SLEEP;
-    } else {
-        fprintf(stderr, "%s is an invalid button identifier\n", b);
-        exit(EXIT_FAILURE);
-    }
-
-    libxl_send_trigger(ctx, domid, trigger, 0);
-}
-
-int main_button_press(int argc, char **argv)
-{
-    int opt;
-
-    fprintf(stderr, "WARNING: \"button-press\" is deprecated. "
-            "Please use \"trigger\"\n");
-
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "button-press", 2) {
-        /* No options */
-    }
-
-    button_press(find_domain(argv[optind]), argv[optind + 1]);
-
-    return 0;
-}
-
-static void print_vcpuinfo(uint32_t tdomid,
-                           const libxl_vcpuinfo *vcpuinfo,
-                           uint32_t nr_cpus)
-{
-    char *domname;
-
-    /*      NAME  ID  VCPU */
-    domname = libxl_domid_to_name(ctx, tdomid);
-    printf("%-32s %5u %5u",
-           domname, tdomid, vcpuinfo->vcpuid);
-    free(domname);
-    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 HARD AND SOFT AFFINITY */
-    print_bitmap(vcpuinfo->cpumap.map, nr_cpus, stdout);
-    printf(" / ");
-    print_bitmap(vcpuinfo->cpumap_soft.map, nr_cpus, stdout);
-    printf("\n");
-}
-
-static void print_domain_vcpuinfo(uint32_t domid, uint32_t nr_cpus)
-{
-    libxl_vcpuinfo *vcpuinfo;
-    int i, nb_vcpu, nrcpus;
-
-    vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nrcpus);
-
-    if (!vcpuinfo)
-        return;
-
-    for (i = 0; i < nb_vcpu; i++) {
-        print_vcpuinfo(domid, &vcpuinfo[i], nr_cpus);
-    }
-
-    libxl_vcpuinfo_list_free(vcpuinfo, nb_vcpu);
-}
-
-static void vcpulist(int argc, char **argv)
-{
-    libxl_dominfo *dominfo;
-    libxl_physinfo physinfo;
-    int i, nb_domain;
-
-    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)",
-           "Affinity (Hard / Soft)");
-    if (!argc) {
-        if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            goto vcpulist_out;
-        }
-
-        for (i = 0; i<nb_domain; i++)
-            print_domain_vcpuinfo(dominfo[i].domid, physinfo.nr_cpus);
-
-        libxl_dominfo_list_free(dominfo, nb_domain);
-    } else {
-        for (; argc > 0; ++argv, --argc) {
-            uint32_t domid = find_domain(*argv);
-            print_domain_vcpuinfo(domid, physinfo.nr_cpus);
-        }
-    }
-  vcpulist_out:
-    libxl_physinfo_dispose(&physinfo);
-}
-
-int main_vcpulist(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vcpu-list", 0) {
-        /* No options */
-    }
-
-    vcpulist(argc - optind, argv + optind);
-    return EXIT_SUCCESS;
-}
-
-int main_vcpupin(int argc, char **argv)
-{
-    static struct option opts[] = {
-        {"force", 0, 0, 'f'},
-        COMMON_LONG_OPTS
-    };
-    libxl_vcpuinfo *vcpuinfo;
-    libxl_bitmap cpumap_hard, cpumap_soft;;
-    libxl_bitmap *soft = &cpumap_soft, *hard = &cpumap_hard;
-    uint32_t domid;
-    /*
-     * int would be enough for vcpuid, but we don't want to
-     * mess aroung range checking the return value of strtol().
-     */
-    long vcpuid;
-    const char *vcpu, *hard_str, *soft_str;
-    char *endptr;
-    int opt, nb_cpu, nb_vcpu, rc = EXIT_FAILURE;
-    bool force = false;
-
-    libxl_bitmap_init(&cpumap_hard);
-    libxl_bitmap_init(&cpumap_soft);
-
-    SWITCH_FOREACH_OPT(opt, "f", opts, "vcpu-pin", 3) {
-    case 'f':
-        force = true;
-        break;
-    default:
-        break;
-    }
-
-    domid = find_domain(argv[optind]);
-    vcpu = argv[optind+1];
-    hard_str = argv[optind+2];
-    soft_str = (argc > optind+3) ? argv[optind+3] : NULL;
-
-    /* Figure out with which vCPU we are dealing with */
-    vcpuid = strtol(vcpu, &endptr, 10);
-    if (vcpu == endptr || vcpuid < 0) {
-        if (strcmp(vcpu, "all")) {
-            fprintf(stderr, "Error: Invalid argument %s as VCPU.\n", vcpu);
-            goto out;
-        }
-        if (force) {
-            fprintf(stderr, "Error: --force and 'all' as VCPU not allowed.\n");
-            goto out;
-        }
-        vcpuid = -1;
-    }
-
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap_hard, 0) ||
-        libxl_cpu_bitmap_alloc(ctx, &cpumap_soft, 0))
-        goto out;
-
-    /*
-     * Syntax is: xl vcpu-pin <domid> <vcpu> <hard> <soft>
-     * We want to handle all the following cases ('-' means
-     * "leave it alone"):
-     *  xl vcpu-pin 0 3 3,4
-     *  xl vcpu-pin 0 3 3,4 -
-     *  xl vcpu-pin 0 3 - 6-9
-     *  xl vcpu-pin 0 3 3,4 6-9
-     */
-
-    /*
-     * Hard affinity is always present. However, if it's "-", all we need
-     * is passing a NULL pointer to the libxl_set_vcpuaffinity() call below.
-     */
-    if (!strcmp(hard_str, "-"))
-        hard = NULL;
-    else if (cpurange_parse(hard_str, hard))
-        goto out;
-    /*
-     * Soft affinity is handled similarly. Only difference: we also want
-     * to pass NULL to libxl_set_vcpuaffinity() if it is not specified.
-     */
-    if (argc <= optind+3 || !strcmp(soft_str, "-"))
-        soft = NULL;
-    else if (cpurange_parse(soft_str, soft))
-        goto out;
-
-    if (dryrun_only) {
-        nb_cpu = libxl_get_online_cpus(ctx);
-        if (nb_cpu < 0) {
-            fprintf(stderr, "libxl_get_online_cpus failed.\n");
-            goto out;
-        }
-
-        fprintf(stdout, "cpumap: ");
-        if (hard)
-            print_bitmap(hard->map, nb_cpu, stdout);
-        else
-            fprintf(stdout, "-");
-        if (soft) {
-            fprintf(stdout, " ");
-            print_bitmap(soft->map, nb_cpu, stdout);
-        }
-        fprintf(stdout, "\n");
-
-        if (ferror(stdout) || fflush(stdout)) {
-            perror("stdout");
-            exit(EXIT_FAILURE);
-        }
-
-        rc = EXIT_SUCCESS;
-        goto out;
-    }
-
-    if (force) {
-        if (libxl_set_vcpuaffinity_force(ctx, domid, vcpuid, hard, soft)) {
-            fprintf(stderr, "Could not set affinity for vcpu `%ld'.\n",
-                    vcpuid);
-            goto out;
-        }
-    }
-    else if (vcpuid != -1) {
-        if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, hard, soft)) {
-            fprintf(stderr, "Could not set affinity for vcpu `%ld'.\n",
-                    vcpuid);
-            goto out;
-        }
-    } else {
-        if (!(vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nb_cpu))) {
-            fprintf(stderr, "libxl_list_vcpu failed.\n");
-            goto out;
-        }
-        if (libxl_set_vcpuaffinity_all(ctx, domid, nb_vcpu, hard, soft))
-            fprintf(stderr, "Could not set affinity.\n");
-        libxl_vcpuinfo_list_free(vcpuinfo, nb_vcpu);
-    }
-
-    rc = EXIT_SUCCESS;
- out:
-    libxl_bitmap_dispose(&cpumap_soft);
-    libxl_bitmap_dispose(&cpumap_hard);
-    return rc;
-}
-
-static int vcpuset(uint32_t domid, const char* nr_vcpus, int check_host)
-{
-    char *endptr;
-    unsigned int max_vcpus, i;
-    libxl_bitmap cpumap;
-    int rc;
-
-    libxl_bitmap_init(&cpumap);
-    max_vcpus = strtoul(nr_vcpus, &endptr, 10);
-    if (nr_vcpus == endptr) {
-        fprintf(stderr, "Error: Invalid argument.\n");
-        return 1;
-    }
-
-    /*
-     * Maximum amount of vCPUS the guest is allowed to set is limited
-     * by the host's amount of pCPUs.
-     */
-    if (check_host) {
-        unsigned int online_vcpus, host_cpu = libxl_get_max_cpus(ctx);
-        libxl_dominfo dominfo;
-
-        if (libxl_domain_info(ctx, &dominfo, domid))
-            return 1;
-
-        online_vcpus = dominfo.vcpu_online;
-        libxl_dominfo_dispose(&dominfo);
-
-        if (max_vcpus > online_vcpus && max_vcpus > host_cpu) {
-            fprintf(stderr, "You are overcommmitting! You have %d physical" \
-                    " CPUs and want %d vCPUs! Aborting, use --ignore-host to" \
-                    " continue\n", host_cpu, max_vcpus);
-            return 1;
-        }
-    }
-    rc = libxl_cpu_bitmap_alloc(ctx, &cpumap, max_vcpus);
-    if (rc) {
-        fprintf(stderr, "libxl_cpu_bitmap_alloc failed, rc: %d\n", rc);
-        return 1;
-    }
-    for (i = 0; i < max_vcpus; i++)
-        libxl_bitmap_set(&cpumap, i);
-
-    rc = libxl_set_vcpuonline(ctx, domid, &cpumap);
-    if (rc == ERROR_DOMAIN_NOTFOUND)
-        fprintf(stderr, "Domain %u does not exist.\n", domid);
-    else if (rc)
-        fprintf(stderr, "libxl_set_vcpuonline failed domid=%u max_vcpus=%d," \
-                " rc: %d\n", domid, max_vcpus, rc);
-
-    libxl_bitmap_dispose(&cpumap);
-    return rc ? 1 : 0;
-}
-
-int main_vcpuset(int argc, char **argv)
-{
-    static struct option opts[] = {
-        {"ignore-host", 0, 0, 'i'},
-        COMMON_LONG_OPTS
-    };
-    int opt, check_host = 1;
-
-    SWITCH_FOREACH_OPT(opt, "i", opts, "vcpu-set", 2) {
-    case 'i':
-        check_host = 0;
-        break;
-    default:
-        break;
-    }
-
-    if (vcpuset(find_domain(argv[optind]), argv[optind + 1], check_host))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-/* Possibly select a specific piece of `xl info` to print. */
-static const char *info_name;
-static int maybe_printf(const char *fmt, ...) __attribute__((format(printf,1,2)));
-static int maybe_printf(const char *fmt, ...)
-{
-    va_list ap;
-    char *str;
-    int count = 0;
-
-    va_start(ap, fmt);
-    if (vasprintf(&str, fmt, ap) != -1) {
-        if (info_name) {
-            char *s;
-
-            if (!strncmp(str, info_name, strlen(info_name)) &&
-                (s = strchr(str, ':')) && s[1] == ' ')
-                count = fputs(&s[2], stdout);
-        } else
-            count = fputs(str, stdout);
-
-        free(str);
-    }
-    va_end(ap);
-
-    return count;
-}
-
-static void output_xeninfo(void)
-{
-    const libxl_version_info *info;
-    libxl_scheduler sched;
-    int rc;
-
-    if (!(info = libxl_get_version_info(ctx))) {
-        fprintf(stderr, "libxl_get_version_info failed.\n");
-        return;
-    }
-
-    rc = libxl_get_scheduler(ctx);
-    if (rc < 0) {
-        fprintf(stderr, "get_scheduler sysctl failed.\n");
-        return;
-    }
-    sched = rc;
-
-    maybe_printf("xen_major              : %d\n", info->xen_version_major);
-    maybe_printf("xen_minor              : %d\n", info->xen_version_minor);
-    maybe_printf("xen_extra              : %s\n", info->xen_version_extra);
-    maybe_printf("xen_version            : %d.%d%s\n", info->xen_version_major,
-           info->xen_version_minor, info->xen_version_extra);
-    maybe_printf("xen_caps               : %s\n", info->capabilities);
-    maybe_printf("xen_scheduler          : %s\n", libxl_scheduler_to_string(sched));
-    maybe_printf("xen_pagesize           : %u\n", info->pagesize);
-    maybe_printf("platform_params        : virt_start=0x%"PRIx64"\n", info->virt_start);
-    maybe_printf("xen_changeset          : %s\n", info->changeset);
-    maybe_printf("xen_commandline        : %s\n", info->commandline);
-    maybe_printf("cc_compiler            : %s\n", info->compiler);
-    maybe_printf("cc_compile_by          : %s\n", info->compile_by);
-    maybe_printf("cc_compile_domain      : %s\n", info->compile_domain);
-    maybe_printf("cc_compile_date        : %s\n", info->compile_date);
-    maybe_printf("build_id               : %s\n", info->build_id);
-
-    return;
-}
-
-static void output_nodeinfo(void)
-{
-    struct utsname utsbuf;
-
-    if (uname(&utsbuf) < 0)
-        return;
-
-    maybe_printf("host                   : %s\n", utsbuf.nodename);
-    maybe_printf("release                : %s\n", utsbuf.release);
-    maybe_printf("version                : %s\n", utsbuf.version);
-    maybe_printf("machine                : %s\n", utsbuf.machine);
-}
-
-static void output_physinfo(void)
-{
-    libxl_physinfo info;
-    const libxl_version_info *vinfo;
-    unsigned int i;
-    libxl_bitmap cpumap;
-    int n = 0;
-
-    if (libxl_get_physinfo(ctx, &info) != 0) {
-        fprintf(stderr, "libxl_physinfo failed.\n");
-        return;
-    }
-    maybe_printf("nr_cpus                : %d\n", info.nr_cpus);
-    maybe_printf("max_cpu_id             : %d\n", info.max_cpu_id);
-    maybe_printf("nr_nodes               : %d\n", info.nr_nodes);
-    maybe_printf("cores_per_socket       : %d\n", info.cores_per_socket);
-    maybe_printf("threads_per_core       : %d\n", info.threads_per_core);
-    maybe_printf("cpu_mhz                : %d\n", info.cpu_khz / 1000);
-
-    maybe_printf("hw_caps                : %08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x\n",
-         info.hw_cap[0], info.hw_cap[1], info.hw_cap[2], info.hw_cap[3],
-         info.hw_cap[4], info.hw_cap[5], info.hw_cap[6], info.hw_cap[7]
-        );
-
-    maybe_printf("virt_caps              :%s%s\n",
-         info.cap_hvm ? " hvm" : "",
-         info.cap_hvm_directio ? " hvm_directio" : ""
-        );
-
-    vinfo = libxl_get_version_info(ctx);
-    if (vinfo) {
-        i = (1 << 20) / vinfo->pagesize;
-        maybe_printf("total_memory           : %"PRIu64"\n", info.total_pages / i);
-        maybe_printf("free_memory            : %"PRIu64"\n", (info.free_pages - info.outstanding_pages) / i);
-        maybe_printf("sharing_freed_memory   : %"PRIu64"\n", info.sharing_freed_pages / i);
-        maybe_printf("sharing_used_memory    : %"PRIu64"\n", info.sharing_used_frames / i);
-        maybe_printf("outstanding_claims     : %"PRIu64"\n", info.outstanding_pages / i);
-    }
-    if (!libxl_get_freecpus(ctx, &cpumap)) {
-        libxl_for_each_bit(i, cpumap)
-            if (libxl_bitmap_test(&cpumap, i))
-                n++;
-        maybe_printf("free_cpus              : %d\n", n);
-        free(cpumap.map);
-    }
-    libxl_physinfo_dispose(&info);
-    return;
-}
-
-static void output_numainfo(void)
-{
-    libxl_numainfo *info;
-    int i, j, nr;
-
-    info = libxl_get_numainfo(ctx, &nr);
-    if (info == NULL) {
-        fprintf(stderr, "libxl_get_numainfo failed.\n");
-        return;
-    }
-
-    printf("numa_info              :\n");
-    printf("node:    memsize    memfree    distances\n");
-
-    for (i = 0; i < nr; i++) {
-        if (info[i].size != LIBXL_NUMAINFO_INVALID_ENTRY) {
-            printf("%4d:    %6"PRIu64"     %6"PRIu64"      %d", i,
-                   info[i].size >> 20, info[i].free >> 20,
-                   info[i].dists[0]);
-            for (j = 1; j < info[i].num_dists; j++)
-                printf(",%d", info[i].dists[j]);
-            printf("\n");
-        }
-    }
-
-    libxl_numainfo_list_free(info, nr);
-
-    return;
-}
-
-static void output_topologyinfo(void)
-{
-    libxl_cputopology *cpuinfo;
-    int i, nr;
-    libxl_pcitopology *pciinfo;
-    int valid_devs = 0;
-
-
-    cpuinfo = libxl_get_cpu_topology(ctx, &nr);
-    if (cpuinfo == NULL) {
-        fprintf(stderr, "libxl_get_cpu_topology failed.\n");
-        return;
-    }
-
-    printf("cpu_topology           :\n");
-    printf("cpu:    core    socket     node\n");
-
-    for (i = 0; i < nr; i++) {
-        if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
-            printf("%3d:    %4d     %4d     %4d\n", i,
-                   cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node);
-    }
-
-    libxl_cputopology_list_free(cpuinfo, nr);
-
-    pciinfo = libxl_get_pci_topology(ctx, &nr);
-    if (pciinfo == NULL) {
-        fprintf(stderr, "libxl_get_pci_topology failed.\n");
-        return;
-    }
-
-    printf("device topology        :\n");
-    printf("device           node\n");
-    for (i = 0; i < nr; i++) {
-        if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) {
-            printf("%04x:%02x:%02x.%01x      %d\n", pciinfo[i].seg,
-                   pciinfo[i].bus,
-                   ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7),
-                   pciinfo[i].node);
-            valid_devs++;
-        }
-    }
-
-    if (valid_devs == 0)
-        printf("No device topology data available\n");
-
-    libxl_pcitopology_list_free(pciinfo, nr);
-
-    return;
-}
-
-static void print_info(int numa)
-{
-    output_nodeinfo();
-
-    output_physinfo();
-
-    if (numa) {
-        output_topologyinfo();
-        output_numainfo();
-    }
-    output_xeninfo();
-
-    maybe_printf("xend_config_format     : 4\n");
-
-    return;
-}
-
-int main_info(int argc, char **argv)
-{
-    int opt;
-    static struct option opts[] = {
-        {"numa", 0, 0, 'n'},
-        COMMON_LONG_OPTS
-    };
-    int numa = 0;
-
-    SWITCH_FOREACH_OPT(opt, "n", opts, "info", 0) {
-    case 'n':
-        numa = 1;
-        break;
-    }
-
-    /*
-     * If an extra argument is provided, filter out a specific piece of
-     * information.
-     */
-    if (numa == 0 && argc > optind)
-        info_name = argv[optind];
-
-    print_info(numa);
-    return 0;
-}
-
-static void sharing(const libxl_dominfo *info, int nb_domain)
-{
-    int i;
-
-    printf("Name                                        ID   Mem Shared\n");
-
-    for (i = 0; i < nb_domain; i++) {
-        char *domname;
-        unsigned shutdown_reason;
-        domname = libxl_domid_to_name(ctx, info[i].domid);
-        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
-        printf("%-40s %5d %5lu  %5lu\n",
-                domname,
-                info[i].domid,
-                (unsigned long) ((info[i].current_memkb +
-                    info[i].outstanding_memkb) / 1024),
-                (unsigned long) (info[i].shared_memkb / 1024));
-        free(domname);
-    }
-}
-
-int main_sharing(int argc, char **argv)
-{
-    int opt = 0;
-    libxl_dominfo info_buf;
-    libxl_dominfo *info, *info_free = NULL;
-    int nb_domain, rc;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "sharing", 0) {
-        /* No options */
-    }
-
-    if (optind >= argc) {
-        info = libxl_list_domain(ctx, &nb_domain);
-        if (!info) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            return EXIT_FAILURE;
-        }
-        info_free = info;
-    } else if (optind == argc-1) {
-        uint32_t domid = find_domain(argv[optind]);
-        rc = libxl_domain_info(ctx, &info_buf, domid);
-        if (rc == ERROR_DOMAIN_NOTFOUND) {
-            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
-                argv[optind]);
-            return EXIT_FAILURE;
-        }
-        if (rc) {
-            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
-            return EXIT_FAILURE;
-        }
-        info = &info_buf;
-        nb_domain = 1;
-    } else {
-        help("sharing");
-        return EXIT_FAILURE;
-    }
-
-    sharing(info, nb_domain);
-
-    if (info_free)
-        libxl_dominfo_list_free(info_free, nb_domain);
-    else
-        libxl_dominfo_dispose(info);
-
-    return EXIT_SUCCESS;
-}
-
-static int sched_domain_get(libxl_scheduler sched, int domid,
-                            libxl_domain_sched_params *scinfo)
-{
-    if (libxl_domain_sched_params_get(ctx, domid, scinfo)) {
-        fprintf(stderr, "libxl_domain_sched_params_get failed.\n");
-        return 1;
-    }
-    if (scinfo->sched != sched) {
-        fprintf(stderr, "libxl_domain_sched_params_get returned %s not %s.\n",
-                libxl_scheduler_to_string(scinfo->sched),
-                libxl_scheduler_to_string(sched));
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_domain_set(int domid, const libxl_domain_sched_params *scinfo)
-{
-    if (libxl_domain_sched_params_set(ctx, domid, scinfo)) {
-        fprintf(stderr, "libxl_domain_sched_params_set failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_vcpu_get(libxl_scheduler sched, int domid,
-                          libxl_vcpu_sched_params *scinfo)
-{
-    int rc;
-
-    rc = libxl_vcpu_sched_params_get(ctx, domid, scinfo);
-    if (rc) {
-        fprintf(stderr, "libxl_vcpu_sched_params_get failed.\n");
-        exit(EXIT_FAILURE);
-    }
-    if (scinfo->sched != sched) {
-        fprintf(stderr, "libxl_vcpu_sched_params_get returned %s not %s.\n",
-                libxl_scheduler_to_string(scinfo->sched),
-                libxl_scheduler_to_string(sched));
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_vcpu_get_all(libxl_scheduler sched, int domid,
-                              libxl_vcpu_sched_params *scinfo)
-{
-    int rc;
-
-    rc = libxl_vcpu_sched_params_get_all(ctx, domid, scinfo);
-    if (rc) {
-        fprintf(stderr, "libxl_vcpu_sched_params_get_all failed.\n");
-        exit(EXIT_FAILURE);
-    }
-    if (scinfo->sched != sched) {
-        fprintf(stderr, "libxl_vcpu_sched_params_get_all returned %s not %s.\n",
-                libxl_scheduler_to_string(scinfo->sched),
-                libxl_scheduler_to_string(sched));
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_vcpu_set(int domid, const libxl_vcpu_sched_params *scinfo)
-{
-    int rc;
-
-    rc = libxl_vcpu_sched_params_set(ctx, domid, scinfo);
-    if (rc) {
-        fprintf(stderr, "libxl_vcpu_sched_params_set failed.\n");
-        exit(EXIT_FAILURE);
-    }
-
-    return 0;
-}
-
-static int sched_vcpu_set_all(int domid, const libxl_vcpu_sched_params *scinfo)
-{
-    int rc;
-
-    rc = libxl_vcpu_sched_params_set_all(ctx, domid, scinfo);
-    if (rc) {
-        fprintf(stderr, "libxl_vcpu_sched_params_set_all failed.\n");
-        exit(EXIT_FAILURE);
-    }
-
-    return 0;
-}
-
-static int sched_credit_params_set(int poolid, libxl_sched_credit_params *scinfo)
-{
-    if (libxl_sched_credit_params_set(ctx, poolid, scinfo)) {
-        fprintf(stderr, "libxl_sched_credit_params_set failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_credit_params_get(int poolid, libxl_sched_credit_params *scinfo)
-{
-    if (libxl_sched_credit_params_get(ctx, poolid, scinfo)) {
-        fprintf(stderr, "libxl_sched_credit_params_get failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_credit_domain_output(int domid)
-{
-    char *domname;
-    libxl_domain_sched_params scinfo;
-
-    if (domid < 0) {
-        printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
-        return 0;
-    }
-
-    libxl_domain_sched_params_init(&scinfo);
-    if (sched_domain_get(LIBXL_SCHEDULER_CREDIT, domid, &scinfo)) {
-        libxl_domain_sched_params_dispose(&scinfo);
-        return 1;
-    }
-    domname = libxl_domid_to_name(ctx, domid);
-    printf("%-33s %4d %6d %4d\n",
-        domname,
-        domid,
-        scinfo.weight,
-        scinfo.cap);
-    free(domname);
-    libxl_domain_sched_params_dispose(&scinfo);
-    return 0;
-}
-
-static int sched_credit_pool_output(uint32_t poolid)
-{
-    libxl_sched_credit_params scparam;
-    char *poolname;
-
-    poolname = libxl_cpupoolid_to_name(ctx, poolid);
-    if (sched_credit_params_get(poolid, &scparam)) {
-        printf("Cpupool %s: [sched params unavailable]\n",
-               poolname);
-    } else {
-        printf("Cpupool %s: tslice=%dms ratelimit=%dus\n",
-               poolname,
-               scparam.tslice_ms,
-               scparam.ratelimit_us);
-    }
-    free(poolname);
-    return 0;
-}
-
-static int sched_credit2_params_set(int poolid,
-                                    libxl_sched_credit2_params *scinfo)
-{
-    if (libxl_sched_credit2_params_set(ctx, poolid, scinfo)) {
-        fprintf(stderr, "libxl_sched_credit2_params_set failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_credit2_params_get(int poolid,
-                                    libxl_sched_credit2_params *scinfo)
-{
-    if (libxl_sched_credit2_params_get(ctx, poolid, scinfo)) {
-        fprintf(stderr, "libxl_sched_credit2_params_get failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_credit2_domain_output(int domid)
-{
-    char *domname;
-    libxl_domain_sched_params scinfo;
-
-    if (domid < 0) {
-        printf("%-33s %4s %6s\n", "Name", "ID", "Weight");
-        return 0;
-    }
-
-    libxl_domain_sched_params_init(&scinfo);
-    if (sched_domain_get(LIBXL_SCHEDULER_CREDIT2, domid, &scinfo)) {
-        libxl_domain_sched_params_dispose(&scinfo);
-        return 1;
-    }
-    domname = libxl_domid_to_name(ctx, domid);
-    printf("%-33s %4d %6d\n",
-        domname,
-        domid,
-        scinfo.weight);
-    free(domname);
-    libxl_domain_sched_params_dispose(&scinfo);
-    return 0;
-}
-
-static int sched_credit2_pool_output(uint32_t poolid)
-{
-    libxl_sched_credit2_params scparam;
-    char *poolname = libxl_cpupoolid_to_name(ctx, poolid);
-
-    if (sched_credit2_params_get(poolid, &scparam))
-        printf("Cpupool %s: [sched params unavailable]\n", poolname);
-    else
-        printf("Cpupool %s: ratelimit=%dus\n",
-               poolname, scparam.ratelimit_us);
-
-    free(poolname);
-
-    return 0;
-}
-
-static int sched_rtds_domain_output(
-    int domid)
-{
-    char *domname;
-    libxl_domain_sched_params scinfo;
-
-    if (domid < 0) {
-        printf("%-33s %4s %9s %9s\n", "Name", "ID", "Period", "Budget");
-        return 0;
-    }
-
-    libxl_domain_sched_params_init(&scinfo);
-    if (sched_domain_get(LIBXL_SCHEDULER_RTDS, domid, &scinfo)) {
-        libxl_domain_sched_params_dispose(&scinfo);
-        return 1;
-    }
-
-    domname = libxl_domid_to_name(ctx, domid);
-    printf("%-33s %4d %9d %9d\n",
-        domname,
-        domid,
-        scinfo.period,
-        scinfo.budget);
-    free(domname);
-    libxl_domain_sched_params_dispose(&scinfo);
-    return 0;
-}
-
-static int sched_rtds_vcpu_output(int domid, libxl_vcpu_sched_params *scinfo)
-{
-    char *domname;
-    int rc = 0;
-    int i;
-
-    if (domid < 0) {
-        printf("%-33s %4s %4s %9s %9s\n", "Name", "ID",
-               "VCPU", "Period", "Budget");
-        return 0;
-    }
-
-    rc = sched_vcpu_get(LIBXL_SCHEDULER_RTDS, domid, scinfo);
-    if (rc)
-        return 1;
-
-    domname = libxl_domid_to_name(ctx, domid);
-    for ( i = 0; i < scinfo->num_vcpus; i++ ) {
-        printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32"\n",
-               domname,
-               domid,
-               scinfo->vcpus[i].vcpuid,
-               scinfo->vcpus[i].period,
-               scinfo->vcpus[i].budget);
-    }
-    free(domname);
-    return 0;
-}
-
-static int sched_rtds_vcpu_output_all(int domid,
-                                      libxl_vcpu_sched_params *scinfo)
-{
-    char *domname;
-    int rc = 0;
-    int i;
-
-    if (domid < 0) {
-        printf("%-33s %4s %4s %9s %9s\n", "Name", "ID",
-               "VCPU", "Period", "Budget");
-        return 0;
-    }
-
-    scinfo->num_vcpus = 0;
-    rc = sched_vcpu_get_all(LIBXL_SCHEDULER_RTDS, domid, scinfo);
-    if (rc)
-        return 1;
-
-    domname = libxl_domid_to_name(ctx, domid);
-    for ( i = 0; i < scinfo->num_vcpus; i++ ) {
-        printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32"\n",
-               domname,
-               domid,
-               scinfo->vcpus[i].vcpuid,
-               scinfo->vcpus[i].period,
-               scinfo->vcpus[i].budget);
-    }
-    free(domname);
-    return 0;
-}
-
-static int sched_rtds_pool_output(uint32_t poolid)
-{
-    char *poolname;
-
-    poolname = libxl_cpupoolid_to_name(ctx, poolid);
-    printf("Cpupool %s: sched=RTDS\n", poolname);
-
-    free(poolname);
-    return 0;
-}
-
-static int sched_domain_output(libxl_scheduler sched, int (*output)(int),
-                               int (*pooloutput)(uint32_t), const char *cpupool)
-{
-    libxl_dominfo *info;
-    libxl_cpupoolinfo *poolinfo = NULL;
-    uint32_t poolid;
-    int nb_domain, n_pools = 0, i, p;
-    int rc = 0;
-
-    if (cpupool) {
-        if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL) ||
-            !libxl_cpupoolid_is_valid(ctx, poolid)) {
-            fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
-            return 1;
-        }
-    }
-
-    info = libxl_list_domain(ctx, &nb_domain);
-    if (!info) {
-        fprintf(stderr, "libxl_list_domain failed.\n");
-        return 1;
-    }
-    poolinfo = libxl_list_cpupool(ctx, &n_pools);
-    if (!poolinfo) {
-        fprintf(stderr, "error getting cpupool info\n");
-        libxl_dominfo_list_free(info, nb_domain);
-        return 1;
-    }
-
-    for (p = 0; !rc && (p < n_pools); p++) {
-        if ((poolinfo[p].sched != sched) ||
-            (cpupool && (poolid != poolinfo[p].poolid)))
-            continue;
-
-        pooloutput(poolinfo[p].poolid);
-
-        output(-1);
-        for (i = 0; i < nb_domain; i++) {
-            if (info[i].cpupool != poolinfo[p].poolid)
-                continue;
-            rc = output(info[i].domid);
-            if (rc)
-                break;
-        }
-    }
-
-    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
-    libxl_dominfo_list_free(info, nb_domain);
-    return 0;
-}
-
-static int sched_vcpu_output(libxl_scheduler sched,
-                             int (*output)(int, libxl_vcpu_sched_params *),
-                             int (*pooloutput)(uint32_t), const char *cpupool)
-{
-    libxl_dominfo *info;
-    libxl_cpupoolinfo *poolinfo = NULL;
-    uint32_t poolid;
-    int nb_domain, n_pools = 0, i, p;
-    int rc = 0;
-
-    if (cpupool) {
-        if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL)
-            || !libxl_cpupoolid_is_valid(ctx, poolid)) {
-            fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
-            return 1;
-        }
-    }
-
-    info = libxl_list_domain(ctx, &nb_domain);
-    if (!info) {
-        fprintf(stderr, "libxl_list_domain failed.\n");
-        return 1;
-    }
-    poolinfo = libxl_list_cpupool(ctx, &n_pools);
-    if (!poolinfo) {
-        fprintf(stderr, "error getting cpupool info\n");
-        libxl_dominfo_list_free(info, nb_domain);
-        return 1;
-    }
-
-    for (p = 0; !rc && (p < n_pools); p++) {
-        if ((poolinfo[p].sched != sched) ||
-            (cpupool && (poolid != poolinfo[p].poolid)))
-            continue;
-
-        pooloutput(poolinfo[p].poolid);
-
-        output(-1, NULL);
-        for (i = 0; i < nb_domain; i++) {
-            libxl_vcpu_sched_params scinfo;
-            if (info[i].cpupool != poolinfo[p].poolid)
-                continue;
-            libxl_vcpu_sched_params_init(&scinfo);
-            rc = output(info[i].domid, &scinfo);
-            libxl_vcpu_sched_params_dispose(&scinfo);
-            if (rc)
-                break;
-        }
-    }
-
-    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
-    libxl_dominfo_list_free(info, nb_domain);
-    return 0;
-}
-
-/* 
- * <nothing>             : List all domain params and sched params from all pools
- * -d [domid]            : List domain params for domain
- * -d [domid] [params]   : Set domain params for domain
- * -p [pool]             : list all domains and sched params for pool
- * -s                    : List sched params for poolid 0
- * -s [params]           : Set sched params for poolid 0
- * -p [pool] -s          : List sched params for pool
- * -p [pool] -s [params] : Set sched params for pool
- * -p [pool] -d...       : Illegal
- */
-int main_sched_credit(int argc, char **argv)
-{
-    const char *dom = NULL;
-    const char *cpupool = NULL;
-    int weight = 256, cap = 0;
-    int tslice = 0, ratelimit = 0;
-    bool opt_w = false, opt_c = false;
-    bool opt_t = false, opt_r = false;
-    bool opt_s = false;
-    int opt, rc;
-    static struct option opts[] = {
-        {"domain", 1, 0, 'd'},
-        {"weight", 1, 0, 'w'},
-        {"cap", 1, 0, 'c'},
-        {"schedparam", 0, 0, 's'},
-        {"tslice_ms", 1, 0, 't'},
-        {"ratelimit_us", 1, 0, 'r'},
-        {"cpupool", 1, 0, 'p'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "d:w:c:p:t:r:s", opts, "sched-credit", 0) {
-    case 'd':
-        dom = optarg;
-        break;
-    case 'w':
-        weight = strtol(optarg, NULL, 10);
-        opt_w = true;
-        break;
-    case 'c':
-        cap = strtol(optarg, NULL, 10);
-        opt_c = true;
-        break;
-    case 't':
-        tslice = strtol(optarg, NULL, 10);
-        opt_t = true;
-        break;
-    case 'r':
-        ratelimit = strtol(optarg, NULL, 10);
-        opt_r = true;
-        break;
-    case 's':
-        opt_s = true;
-        break;
-    case 'p':
-        cpupool = optarg;
-        break;
-    }
-
-    if ((cpupool || opt_s) && (dom || opt_w || opt_c)) {
-        fprintf(stderr, "Specifying a cpupool or schedparam is not "
-                "allowed with domain options.\n");
-        return EXIT_FAILURE;
-    }
-    if (!dom && (opt_w || opt_c)) {
-        fprintf(stderr, "Must specify a domain.\n");
-        return EXIT_FAILURE;
-    }
-    if (!opt_s && (opt_t || opt_r)) {
-        fprintf(stderr, "Must specify schedparam to set schedule "
-                "parameter values.\n");
-        return EXIT_FAILURE;
-    }
-
-    if (opt_s) {
-        libxl_sched_credit_params scparam;
-        uint32_t poolid = 0;
-
-        if (cpupool) {
-            if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
-                                                     &poolid, NULL) ||
-                !libxl_cpupoolid_is_valid(ctx, poolid)) {
-                fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
-                return EXIT_FAILURE;
-            }
-        }
-
-        if (!opt_t && !opt_r) { /* Output scheduling parameters */
-            if (sched_credit_pool_output(poolid))
-                return EXIT_FAILURE;
-        } else { /* Set scheduling parameters*/
-            if (sched_credit_params_get(poolid, &scparam))
-                return EXIT_FAILURE;
-
-            if (opt_t)
-                scparam.tslice_ms = tslice;
-
-            if (opt_r)
-                scparam.ratelimit_us = ratelimit;
-
-            if (sched_credit_params_set(poolid, &scparam))
-                return EXIT_FAILURE;
-        }
-    } else if (!dom) { /* list all domain's credit scheduler info */
-        if (sched_domain_output(LIBXL_SCHEDULER_CREDIT,
-                                sched_credit_domain_output,
-                                sched_credit_pool_output,
-                                cpupool))
-            return EXIT_FAILURE;
-    } else {
-        uint32_t domid = find_domain(dom);
-
-        if (!opt_w && !opt_c) { /* output credit scheduler info */
-            sched_credit_domain_output(-1);
-            if (sched_credit_domain_output(domid))
-                return EXIT_FAILURE;
-        } else { /* set credit scheduler paramaters */
-            libxl_domain_sched_params scinfo;
-            libxl_domain_sched_params_init(&scinfo);
-            scinfo.sched = LIBXL_SCHEDULER_CREDIT;
-            if (opt_w)
-                scinfo.weight = weight;
-            if (opt_c)
-                scinfo.cap = cap;
-            rc = sched_domain_set(domid, &scinfo);
-            libxl_domain_sched_params_dispose(&scinfo);
-            if (rc)
-                return EXIT_FAILURE;
-        }
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_sched_credit2(int argc, char **argv)
-{
-    const char *dom = NULL;
-    const char *cpupool = NULL;
-    int ratelimit = 0;
-    int weight = 256;
-    bool opt_s = false;
-    bool opt_r = false;
-    bool opt_w = false;
-    int opt, rc;
-    static struct option opts[] = {
-        {"domain", 1, 0, 'd'},
-        {"weight", 1, 0, 'w'},
-        {"schedparam", 0, 0, 's'},
-        {"ratelimit_us", 1, 0, 'r'},
-        {"cpupool", 1, 0, 'p'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "d:w:p:r:s", opts, "sched-credit2", 0) {
-    case 'd':
-        dom = optarg;
-        break;
-    case 'w':
-        weight = strtol(optarg, NULL, 10);
-        opt_w = true;
-        break;
-    case 's':
-        opt_s = true;
-        break;
-    case 'r':
-        ratelimit = strtol(optarg, NULL, 10);
-        opt_r = true;
-        break;
-    case 'p':
-        cpupool = optarg;
-        break;
-    }
-
-    if (cpupool && (dom || opt_w)) {
-        fprintf(stderr, "Specifying a cpupool is not allowed with other "
-                "options.\n");
-        return EXIT_FAILURE;
-    }
-    if (!dom && opt_w) {
-        fprintf(stderr, "Must specify a domain.\n");
-        return EXIT_FAILURE;
-    }
-
-    if (opt_s) {
-        libxl_sched_credit2_params scparam;
-        uint32_t poolid = 0;
-
-        if (cpupool) {
-            if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
-                                                     &poolid, NULL) ||
-                !libxl_cpupoolid_is_valid(ctx, poolid)) {
-                fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
-                return EXIT_FAILURE;
-            }
-        }
-
-        if (!opt_r) { /* Output scheduling parameters */
-            if (sched_credit2_pool_output(poolid))
-                return EXIT_FAILURE;
-        } else {      /* Set scheduling parameters (so far, just ratelimit) */
-            scparam.ratelimit_us = ratelimit;
-            if (sched_credit2_params_set(poolid, &scparam))
-                return EXIT_FAILURE;
-        }
-    } else if (!dom) { /* list all domain's credit scheduler info */
-        if (sched_domain_output(LIBXL_SCHEDULER_CREDIT2,
-                                sched_credit2_domain_output,
-                                sched_credit2_pool_output,
-                                cpupool))
-            return EXIT_FAILURE;
-    } else {
-        uint32_t domid = find_domain(dom);
-
-        if (!opt_w) { /* output credit2 scheduler info */
-            sched_credit2_domain_output(-1);
-            if (sched_credit2_domain_output(domid))
-                return EXIT_FAILURE;
-        } else { /* set credit2 scheduler paramaters */
-            libxl_domain_sched_params scinfo;
-            libxl_domain_sched_params_init(&scinfo);
-            scinfo.sched = LIBXL_SCHEDULER_CREDIT2;
-            if (opt_w)
-                scinfo.weight = weight;
-            rc = sched_domain_set(domid, &scinfo);
-            libxl_domain_sched_params_dispose(&scinfo);
-            if (rc)
-                return EXIT_FAILURE;
-        }
-    }
-
-    return EXIT_SUCCESS;
-}
-
-/*
- * <nothing>            : List all domain paramters and sched params
- * -d [domid]           : List default domain params for domain
- * -d [domid] [params]  : Set domain params for domain
- * -d [domid] -v [vcpuid 1] -v [vcpuid 2] ...  :
- * List per-VCPU params for domain
- * -d [domid] -v all  : List all per-VCPU params for domain
- * -v all  : List all per-VCPU params for all domains
- * -d [domid] -v [vcpuid 1] [params] -v [vcpuid 2] [params] ...  :
- * Set per-VCPU params for domain
- * -d [domid] -v all [params]  : Set all per-VCPU params for domain
- */
-int main_sched_rtds(int argc, char **argv)
-{
-    const char *dom = NULL;
-    const char *cpupool = NULL;
-    int *vcpus = (int *)xmalloc(sizeof(int)); /* IDs of VCPUs that change */
-    int *periods = (int *)xmalloc(sizeof(int)); /* period is in microsecond */
-    int *budgets = (int *)xmalloc(sizeof(int)); /* budget is in microsecond */
-    int v_size = 1; /* size of vcpus array */
-    int p_size = 1; /* size of periods array */
-    int b_size = 1; /* size of budgets array */
-    int v_index = 0; /* index in vcpus array */
-    int p_index =0; /* index in periods array */
-    int b_index =0; /* index for in budgets array */
-    bool opt_p = false;
-    bool opt_b = false;
-    bool opt_v = false;
-    bool opt_all = false; /* output per-dom parameters */
-    int opt, i, rc, r;
-    static struct option opts[] = {
-        {"domain", 1, 0, 'd'},
-        {"period", 1, 0, 'p'},
-        {"budget", 1, 0, 'b'},
-        {"vcpuid",1, 0, 'v'},
-        {"cpupool", 1, 0, 'c'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "d:p:b:v:c", opts, "sched-rtds", 0) {
-    case 'd':
-        dom = optarg;
-        break;
-    case 'p':
-        if (p_index >= p_size) {
-            /*
-             * periods array is full
-             * double the array size for new elements
-             */
-            p_size *= 2;
-            periods = xrealloc(periods, p_size);
-        }
-        periods[p_index++] = strtol(optarg, NULL, 10);
-        opt_p = 1;
-        break;
-    case 'b':
-        if (b_index >= b_size) { /* budgets array is full */
-            b_size *= 2;
-            budgets = xrealloc(budgets, b_size);
-        }
-        budgets[b_index++] = strtol(optarg, NULL, 10);
-        opt_b = 1;
-        break;
-    case 'v':
-        if (!strcmp(optarg, "all")) { /* get or set all vcpus of a domain */
-            opt_all = 1;
-            break;
-        }
-        if (v_index >= v_size) { /* vcpus array is full */
-            v_size *= 2;
-            vcpus = xrealloc(vcpus, v_size);
-        }
-        vcpus[v_index++] = strtol(optarg, NULL, 10);
-        opt_v = 1;
-        break;
-    case 'c':
-        cpupool = optarg;
-        break;
-    }
-
-    if (cpupool && (dom || opt_p || opt_b || opt_v || opt_all)) {
-        fprintf(stderr, "Specifying a cpupool is not allowed with "
-                "other options.\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-    if (!dom && (opt_p || opt_b || opt_v)) {
-        fprintf(stderr, "Missing parameters.\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-    if (dom && !opt_v && !opt_all && (opt_p || opt_b)) {
-        fprintf(stderr, "Must specify VCPU.\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-    if (opt_v && opt_all) {
-        fprintf(stderr, "Incorrect VCPU IDs.\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-    if (((v_index > b_index) && opt_b) || ((v_index > p_index) && opt_p)
-        || p_index != b_index) {
-        fprintf(stderr, "Incorrect number of period and budget\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-
-    if ((!dom) && opt_all) {
-        /* get all domain's per-vcpu rtds scheduler parameters */
-        rc = -sched_vcpu_output(LIBXL_SCHEDULER_RTDS,
-                                sched_rtds_vcpu_output_all,
-                                sched_rtds_pool_output,
-                                cpupool);
-        if (rc) {
-            r = EXIT_FAILURE;
-            goto out;
-        }
-    } else if (!dom && !opt_all) {
-        /* list all domain's default scheduling parameters */
-        rc = -sched_domain_output(LIBXL_SCHEDULER_RTDS,
-                                  sched_rtds_domain_output,
-                                  sched_rtds_pool_output,
-                                  cpupool);
-        if (rc) {
-            r = EXIT_FAILURE;
-            goto out;
-        }
-    } else {
-        uint32_t domid = find_domain(dom);
-        if (!opt_v && !opt_all) { /* output default scheduling parameters */
-            sched_rtds_domain_output(-1);
-            rc = -sched_rtds_domain_output(domid);
-            if (rc) {
-                r = EXIT_FAILURE;
-                goto out;
-            }
-        } else if (!opt_p && !opt_b) {
-            /* get per-vcpu rtds scheduling parameters */
-            libxl_vcpu_sched_params scinfo;
-            libxl_vcpu_sched_params_init(&scinfo);
-            sched_rtds_vcpu_output(-1, &scinfo);
-            scinfo.num_vcpus = v_index;
-            if (v_index > 0) {
-                scinfo.vcpus = (libxl_sched_params *)
-                               xmalloc(sizeof(libxl_sched_params) * (v_index));
-                for (i = 0; i < v_index; i++)
-                    scinfo.vcpus[i].vcpuid = vcpus[i];
-                rc = -sched_rtds_vcpu_output(domid, &scinfo);
-            } else /* get params for all vcpus */
-                rc = -sched_rtds_vcpu_output_all(domid, &scinfo);
-            libxl_vcpu_sched_params_dispose(&scinfo);
-            if (rc) {
-                r = EXIT_FAILURE;
-                goto out;
-            }
-    } else if (opt_v || opt_all) {
-            /* set per-vcpu rtds scheduling parameters */
-            libxl_vcpu_sched_params scinfo;
-            libxl_vcpu_sched_params_init(&scinfo);
-            scinfo.sched = LIBXL_SCHEDULER_RTDS;
-            if (v_index > 0) {
-                scinfo.num_vcpus = v_index;
-                scinfo.vcpus = (libxl_sched_params *)
-                               xmalloc(sizeof(libxl_sched_params) * (v_index));
-                for (i = 0; i < v_index; i++) {
-                    scinfo.vcpus[i].vcpuid = vcpus[i];
-                    scinfo.vcpus[i].period = periods[i];
-                    scinfo.vcpus[i].budget = budgets[i];
-                }
-                rc = sched_vcpu_set(domid, &scinfo);
-            } else { /* set params for all vcpus */
-                scinfo.num_vcpus = 1;
-                scinfo.vcpus = (libxl_sched_params *)
-                               xmalloc(sizeof(libxl_sched_params));
-                scinfo.vcpus[0].period = periods[0];
-                scinfo.vcpus[0].budget = budgets[0];
-                rc = sched_vcpu_set_all(domid, &scinfo);
-            }
-
-            libxl_vcpu_sched_params_dispose(&scinfo);
-            if (rc) {
-                r = EXIT_FAILURE;
-                goto out;
-            }
-        }
-    }
-
-    r = EXIT_SUCCESS;
-out:
-    free(vcpus);
-    free(periods);
-    free(budgets);
-    return r;
-}
-
-int main_domid(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    const char *domname = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "domid", 1) {
-        /* No options */
-    }
-
-    domname = argv[optind];
-
-    if (libxl_name_to_domid(ctx, domname, &domid)) {
-        fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
-        return EXIT_FAILURE;
-    }
-
-    printf("%u\n", domid);
-
-    return EXIT_SUCCESS;
-}
-
-int main_domname(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    char *domname = NULL;
-    char *endptr = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "domname", 1) {
-        /* No options */
-    }
-
-    domid = strtol(argv[optind], &endptr, 10);
-    if (domid == 0 && !strcmp(endptr, argv[optind])) {
-        /*no digits at all*/
-        fprintf(stderr, "Invalid domain id.\n\n");
-        return EXIT_FAILURE;
-    }
-
-    domname = libxl_domid_to_name(ctx, domid);
-    if (!domname) {
-        fprintf(stderr, "Can't get domain name of domain id '%u', maybe this domain does not exist.\n", domid);
-        return EXIT_FAILURE;
-    }
-
-    printf("%s\n", domname);
-    free(domname);
-
-    return EXIT_SUCCESS;
-}
-
-int main_rename(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    const char *dom, *new_name;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "rename", 2) {
-        /* No options */
-    }
-
-    dom = argv[optind++];
-    new_name = argv[optind];
-
-    domid = find_domain(dom);
-    if (libxl_domain_rename(ctx, domid, common_domname, new_name)) {
-        fprintf(stderr, "Can't rename domain '%s'.\n", dom);
-        return 1;
-    }
-
-    return 0;
-}
-
-int main_trigger(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    char *endptr = NULL;
-    int vcpuid = 0;
-    const char *trigger_name = NULL;
-    libxl_trigger trigger;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "trigger", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind++]);
-
-    trigger_name = argv[optind++];
-    if (libxl_trigger_from_string(trigger_name, &trigger)) {
-        fprintf(stderr, "Invalid trigger \"%s\"\n", trigger_name);
-        return EXIT_FAILURE;
-    }
-
-    if (argv[optind]) {
-        vcpuid = strtol(argv[optind], &endptr, 10);
-        if (vcpuid == 0 && !strcmp(endptr, argv[optind])) {
-            fprintf(stderr, "Invalid vcpuid, using default vcpuid=0.\n\n");
-        }
-    }
-
-    libxl_send_trigger(ctx, domid, trigger, vcpuid);
-
-    return EXIT_SUCCESS;
-}
-
-
-int main_sysrq(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    const char *sysrq = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "sysrq", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind++]);
-
-    sysrq = argv[optind];
-
-    if (sysrq[1] != '\0') {
-        fprintf(stderr, "Invalid sysrq.\n\n");
-        help("sysrq");
-        return EXIT_FAILURE;
-    }
-
-    libxl_send_sysrq(ctx, domid, sysrq[0]);
-
-    return EXIT_SUCCESS;
-}
-
-int main_debug_keys(int argc, char **argv)
-{
-    int opt;
-    char *keys;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "debug-keys", 1) {
-        /* No options */
-    }
-
-    keys = argv[optind];
-
-    if (libxl_send_debug_keys(ctx, keys)) {
-        fprintf(stderr, "cannot send debug keys: %s\n", keys);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_dmesg(int argc, char **argv)
-{
-    unsigned int clear = 0;
-    libxl_xen_console_reader *cr;
-    char *line;
-    int opt, ret = 1;
-
-    SWITCH_FOREACH_OPT(opt, "c", NULL, "dmesg", 0) {
-    case 'c':
-        clear = 1;
-        break;
-    }
-
-    cr = libxl_xen_console_read_start(ctx, clear);
-    if (!cr)
-        goto finish;
-
-    while ((ret = libxl_xen_console_read_line(ctx, cr, &line)) > 0)
-        printf("%s", line);
-
-finish:
-    if (cr)
-        libxl_xen_console_read_finish(ctx, cr);
-    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-int main_top(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "top", 0) {
-        /* No options */
-    }
-
-    return system("xentop");
-}
-
-int main_networkattach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    libxl_device_nic nic;
-    XLU_Config *config = 0;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "network-attach", 1) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-
-    config= xlu_cfg_init(stderr, "command line");
-    if (!config) {
-        fprintf(stderr, "Failed to allocate for configuration\n");
-        return 1;
-    }
-
-    libxl_device_nic_init(&nic);
-    set_default_nic_values(&nic);
-
-    for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
-        if (parse_nic_config(&nic, &config, *argv))
-            return 1;
-    }
-
-    if (dryrun_only) {
-        char *json = libxl_device_nic_to_json(ctx, &nic);
-        printf("vif: %s\n", json);
-        free(json);
-        libxl_device_nic_dispose(&nic);
-        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
-        return 0;
-    }
-
-    if (libxl_device_nic_add(ctx, domid, &nic, 0)) {
-        fprintf(stderr, "libxl_device_nic_add failed.\n");
-        return 1;
-    }
-    libxl_device_nic_dispose(&nic);
-    xlu_cfg_destroy(config);
-    return 0;
-}
-
-int main_networklist(int argc, char **argv)
-{
-    int opt;
-    libxl_device_nic *nics;
-    libxl_nicinfo nicinfo;
-    int nb, i;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "network-list", 1) {
-        /* No options */
-    }
-
-    /*      Idx  BE   MAC   Hdl  Sta  evch txr/rxr  BE-path */
-    printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
-           "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
-    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid = find_domain(*argv);
-        nics = libxl_device_nic_list(ctx, domid, &nb);
-        if (!nics) {
-            continue;
-        }
-        for (i = 0; i < nb; ++i) {
-            if (!libxl_device_nic_getinfo(ctx, domid, &nics[i], &nicinfo)) {
-                /* Idx BE */
-                printf("%-3d %-2d ", nicinfo.devid, nicinfo.backend_id);
-                /* MAC */
-                printf(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nics[i].mac));
-                /* Hdl  Sta  evch txr/rxr  BE-path */
-                printf("%6d %5d %6d %5d/%-11d %-30s\n",
-                       nicinfo.devid, nicinfo.state, nicinfo.evtch,
-                       nicinfo.rref_tx, nicinfo.rref_rx, nicinfo.backend);
-                libxl_nicinfo_dispose(&nicinfo);
-            }
-            libxl_device_nic_dispose(&nics[i]);
-        }
-        free(nics);
-    }
-    return 0;
-}
-
-int main_networkdetach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    libxl_device_nic nic;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "network-detach", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-
-    if (!strchr(argv[optind+1], ':')) {
-        if (libxl_devid_to_device_nic(ctx, domid, atoi(argv[optind+1]), &nic)) {
-            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-            return 1;
-        }
-    } else {
-        if (libxl_mac_to_device_nic(ctx, domid, argv[optind+1], &nic)) {
-            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-            return 1;
-        }
-    }
-    if (libxl_device_nic_remove(ctx, domid, &nic, 0)) {
-        fprintf(stderr, "libxl_device_nic_del failed.\n");
-        return 1;
-    }
-    libxl_device_nic_dispose(&nic);
-    return 0;
-}
-
-int main_channellist(int argc, char **argv)
-{
-    int opt;
-    libxl_device_channel *channels;
-    libxl_channelinfo channelinfo;
-    int nb, i;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "channel-list", 1) {
-        /* No options */
-    }
-
-    /*      Idx BE state evt-ch ring-ref connection params*/
-    printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
-           "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
-    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid = find_domain(*argv);
-        channels = libxl_device_channel_list(ctx, domid, &nb);
-        if (!channels)
-            continue;
-        for (i = 0; i < nb; ++i) {
-            if (!libxl_device_channel_getinfo(ctx, domid, &channels[i],
-                &channelinfo)) {
-                printf("%-3d %-2d ", channels[i].devid, channelinfo.backend_id);
-                printf("%-5d ", channelinfo.state);
-                printf("%-6d %-8d ", channelinfo.evtch, channelinfo.rref);
-                printf("%-10s ", libxl_channel_connection_to_string(
-                       channels[i].connection));
-                switch (channels[i].connection) {
-                    case LIBXL_CHANNEL_CONNECTION_PTY:
-                        printf("%-30s ", channelinfo.u.pty.path);
-                        break;
-                    default:
-                        break;
-                }
-                printf("\n");
-                libxl_channelinfo_dispose(&channelinfo);
-            }
-            libxl_device_channel_dispose(&channels[i]);
-        }
-        free(channels);
-    }
-    return 0;
-}
-
-int main_blockattach(int argc, char **argv)
-{
-    int opt;
-    uint32_t fe_domid;
-    libxl_device_disk disk;
-    XLU_Config *config = 0;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "block-attach", 2) {
-        /* No options */
-    }
-
-    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
-        return 1;
-    }
-    optind++;
-
-    parse_disk_config_multistring
-        (&config, argc-optind, (const char* const*)argv + optind, &disk);
-
-    if (dryrun_only) {
-        char *json = libxl_device_disk_to_json(ctx, &disk);
-        printf("disk: %s\n", json);
-        free(json);
-        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
-        return 0;
-    }
-
-    if (libxl_device_disk_add(ctx, fe_domid, &disk, 0)) {
-        fprintf(stderr, "libxl_device_disk_add failed.\n");
-        return 1;
-    }
-    return 0;
-}
-
-int main_blocklist(int argc, char **argv)
-{
-    int opt;
-    int i, nb;
-    libxl_device_disk *disks;
-    libxl_diskinfo diskinfo;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "block-list", 1) {
-        /* No options */
-    }
-
-    printf("%-5s %-3s %-6s %-5s %-6s %-8s %-30s\n",
-           "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path");
-    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid;
-        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
-            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
-            continue;
-        }
-        disks = libxl_device_disk_list(ctx, domid, &nb);
-        if (!disks) {
-            continue;
-        }
-        for (i=0; i<nb; i++) {
-            if (!libxl_device_disk_getinfo(ctx, domid, &disks[i], &diskinfo)) {
-                /*      Vdev BE   hdl  st   evch rref BE-path*/
-                printf("%-5d %-3d %-6d %-5d %-6d %-8d %-30s\n",
-                       diskinfo.devid, diskinfo.backend_id, diskinfo.frontend_id,
-                       diskinfo.state, diskinfo.evtch, diskinfo.rref, diskinfo.backend);
-                libxl_diskinfo_dispose(&diskinfo);
-            }
-            libxl_device_disk_dispose(&disks[i]);
-        }
-        free(disks);
-    }
-    return 0;
-}
-
-int main_blockdetach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc = 0;
-    libxl_device_disk disk;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "block-detach", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-
-    if (libxl_vdev_to_device_disk(ctx, domid, argv[optind+1], &disk)) {
-        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
-        return 1;
-    }
-    rc = libxl_device_disk_remove(ctx, domid, &disk, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_disk_remove failed.\n");
-        return 1;
-    }
-    libxl_device_disk_dispose(&disk);
-    return rc;
-}
-
-int main_vtpmattach(int argc, char **argv)
-{
-    int opt;
-    libxl_device_vtpm vtpm;
-    char *oparg;
-    uint32_t domid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-attach", 1) {
-        /* No options */
-    }
-
-    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
-        return 1;
-    }
-    ++optind;
-
-    libxl_device_vtpm_init(&vtpm);
-    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
-        if (MATCH_OPTION("uuid", *argv, oparg)) {
-            if(libxl_uuid_from_string(&(vtpm.uuid), oparg)) {
-                fprintf(stderr, "Invalid uuid specified (%s)\n", oparg);
-                return 1;
-            }
-        } else if (MATCH_OPTION("backend", *argv, oparg)) {
-            replace_string(&vtpm.backend_domname, oparg);
-        } else {
-            fprintf(stderr, "unrecognized argument `%s'\n", *argv);
-            return 1;
-        }
-    }
-
-    if(dryrun_only) {
-       char* json = libxl_device_vtpm_to_json(ctx, &vtpm);
-       printf("vtpm: %s\n", json);
-       free(json);
-       libxl_device_vtpm_dispose(&vtpm);
-       if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
-       return 0;
-    }
-
-    if (libxl_device_vtpm_add(ctx, domid, &vtpm, 0)) {
-        fprintf(stderr, "libxl_device_vtpm_add failed.\n");
-        return 1;
-    }
-    libxl_device_vtpm_dispose(&vtpm);
-    return 0;
-}
-
-int main_vtpmlist(int argc, char **argv)
-{
-    int opt;
-    libxl_device_vtpm *vtpms;
-    libxl_vtpminfo vtpminfo;
-    int nb, i;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-list", 1) {
-        /* No options */
-    }
-
-    /*      Idx  BE   UUID   Hdl  Sta  evch rref  BE-path */
-    printf("%-3s %-2s %-36s %-6s %-5s %-6s %-5s %-10s\n",
-           "Idx", "BE", "Uuid", "handle", "state", "evt-ch", "ring-ref", "BE-path");
-    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid;
-        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
-            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
-            continue;
-        }
-        if (!(vtpms = libxl_device_vtpm_list(ctx, domid, &nb))) {
-            continue;
-        }
-        for (i = 0; i < nb; ++i) {
-           if(!libxl_device_vtpm_getinfo(ctx, domid, &vtpms[i], &vtpminfo)) {
-              /*      Idx  BE     UUID             Hdl Sta evch rref BE-path*/
-              printf("%-3d %-2d " LIBXL_UUID_FMT " %6d %5d %6d %8d %-30s\n",
-                    vtpminfo.devid, vtpminfo.backend_id,
-                    LIBXL_UUID_BYTES(vtpminfo.uuid),
-                    vtpminfo.devid, vtpminfo.state, vtpminfo.evtch,
-                    vtpminfo.rref, vtpminfo.backend);
-
-              libxl_vtpminfo_dispose(&vtpminfo);
-           }
-           libxl_device_vtpm_dispose(&vtpms[i]);
-        }
-        free(vtpms);
-    }
-    return 0;
-}
-
-int main_vtpmdetach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc=0;
-    libxl_device_vtpm vtpm;
-    libxl_uuid uuid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-detach", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-
-    if ( libxl_uuid_from_string(&uuid, argv[optind+1])) {
-        if (libxl_devid_to_device_vtpm(ctx, domid, atoi(argv[optind+1]), &vtpm)) {
-            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-            return 1;
-        }
-    } else {
-        if (libxl_uuid_to_device_vtpm(ctx, domid, &uuid, &vtpm)) {
-            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-            return 1;
-        }
-    }
-    rc = libxl_device_vtpm_remove(ctx, domid, &vtpm, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_vtpm_remove failed.\n");
-    }
-    libxl_device_vtpm_dispose(&vtpm);
-    return rc;
-}
-
-
-static char *uptime_to_string(unsigned long uptime, int short_mode)
-{
-    int sec, min, hour, day;
-    char *time_string;
-
-    day = (int)(uptime / 86400);
-    uptime -= (day * 86400);
-    hour = (int)(uptime / 3600);
-    uptime -= (hour * 3600);
-    min = (int)(uptime / 60);
-    uptime -= (min * 60);
-    sec = uptime;
-
-    if (short_mode)
-        if (day > 1)
-            xasprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
-        else if (day == 1)
-            xasprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
-        else
-            xasprintf(&time_string, "%2d:%02d", hour, min);
-    else
-        if (day > 1)
-            xasprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
-        else if (day == 1)
-            xasprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
-        else
-            xasprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
-
-    return time_string;
-}
-
-int main_claims(int argc, char **argv)
-{
-    libxl_dominfo *info;
-    int opt;
-    int nb_domain;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "claims", 0) {
-        /* No options */
-    }
-
-    if (!claim_mode)
-        fprintf(stderr, "claim_mode not enabled (see man xl.conf).\n");
-
-    info = libxl_list_domain(ctx, &nb_domain);
-    if (!info) {
-        fprintf(stderr, "libxl_list_domain failed.\n");
-        return 1;
-    }
-
-    list_domains(false /* verbose */, false /* context */, true /* claim */,
-                 false /* numa */, false /* cpupool */, info, nb_domain);
-
-    libxl_dominfo_list_free(info, nb_domain);
-    return 0;
-}
-
-static char *current_time_to_string(time_t now)
-{
-    char now_str[100];
-    struct tm *tmp;
-
-    tmp = localtime(&now);
-    if (tmp == NULL) {
-        fprintf(stderr, "Get localtime error");
-        exit(-1);
-    }
-    if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
-        fprintf(stderr, "strftime returned 0");
-        exit(-1);
-    }
-    return strdup(now_str);
-}
-
-static void print_dom0_uptime(int short_mode, time_t now)
-{
-    int fd;
-    ssize_t nr;
-    char buf[512];
-    uint32_t uptime = 0;
-    char *uptime_str = NULL;
-    char *now_str = NULL;
-    char *domname;
-
-    fd = open("/proc/uptime", O_RDONLY);
-    if (fd == -1)
-        goto err;
-
-    nr = read(fd, buf, sizeof(buf) - 1);
-    if (nr == -1) {
-        close(fd);
-        goto err;
-    }
-    close(fd);
-
-    buf[nr] = '\0';
-
-    strtok(buf, " ");
-    uptime = strtoul(buf, NULL, 10);
-
-    domname = libxl_domid_to_name(ctx, 0);
-    if (short_mode)
-    {
-        now_str = current_time_to_string(now);
-        uptime_str = uptime_to_string(uptime, 1);
-        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
-               domname, 0);
-    }
-    else
-    {
-        now_str = NULL;
-        uptime_str = uptime_to_string(uptime, 0);
-        printf("%-33s %4d %s\n", domname,
-               0, uptime_str);
-    }
-
-    free(now_str);
-    free(uptime_str);
-    free(domname);
-    return;
-err:
-    fprintf(stderr, "Can not get Dom0 uptime.\n");
-    exit(-1);
-}
-
-static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
-{
-    uint32_t s_time = 0;
-    uint32_t uptime = 0;
-    char *uptime_str = NULL;
-    char *now_str = NULL;
-    char *domname;
-
-    s_time = libxl_vm_get_start_time(ctx, domuid);
-    if (s_time == -1)
-        return;
-    uptime = now - s_time;
-    domname = libxl_domid_to_name(ctx, domuid);
-    if (short_mode)
-    {
-        now_str = current_time_to_string(now);
-        uptime_str = uptime_to_string(uptime, 1);
-        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
-               domname, domuid);
-    }
-    else
-    {
-        now_str = NULL;
-        uptime_str = uptime_to_string(uptime, 0);
-        printf("%-33s %4d %s\n", domname,
-               domuid, uptime_str);
-    }
-
-    free(domname);
-    free(now_str);
-    free(uptime_str);
-    return;
-}
-
-static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
-{
-    libxl_vminfo *info;
-    time_t now;
-    int nb_vm, i;
-
-    now = time(NULL);
-
-    if (!short_mode)
-        printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
-
-    if (nb_doms == 0) {
-        print_dom0_uptime(short_mode, now);
-        info = libxl_list_vm(ctx, &nb_vm);
-        if (info == NULL) {
-            fprintf(stderr, "Could not list vms.\n");
-            return;
-        }
-        for (i = 0; i < nb_vm; i++) {
-            if (info[i].domid == 0) continue;
-            print_domU_uptime(info[i].domid, short_mode, now);
-        }
-        libxl_vminfo_list_free(info, nb_vm);
-    } else {
-        for (i = 0; i < nb_doms; i++) {
-            if (doms[i] == 0)
-                print_dom0_uptime(short_mode, now);
-            else
-                print_domU_uptime(doms[i], short_mode, now);
-        }
-    }
-}
-
-int main_uptime(int argc, char **argv)
-{
-    const char *dom;
-    int short_mode = 0;
-    uint32_t domains[100];
-    int nb_doms = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "s", NULL, "uptime", 0) {
-    case 's':
-        short_mode = 1;
-        break;
-    }
-
-    for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
-        domains[nb_doms] = find_domain(dom);
-
-    print_uptime(short_mode, domains, nb_doms);
-
-    return 0;
-}
-
-int main_tmem_list(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *dom = NULL;
-    char *buf = NULL;
-    int use_long = 0;
-    int all = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "al", NULL, "tmem-list", 0) {
-    case 'l':
-        use_long = 1;
-        break;
-    case 'a':
-        all = 1;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-list");
-        return 1;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = find_domain(dom);
-
-    buf = libxl_tmem_list(ctx, domid, use_long);
-    if (buf == NULL)
-        return EXIT_FAILURE;
-
-    printf("%s\n", buf);
-    free(buf);
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_freeze(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *dom = NULL;
-    int all = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "a", NULL, "tmem-freeze", 0) {
-    case 'a':
-        all = 1;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-freeze");
-        return EXIT_FAILURE;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = find_domain(dom);
-
-    if (libxl_tmem_freeze(ctx, domid) < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_thaw(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *dom = NULL;
-    int all = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "a", NULL, "tmem-thaw", 0) {
-    case 'a':
-        all = 1;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-thaw");
-        return EXIT_FAILURE;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = find_domain(dom);
-
-    if (libxl_tmem_thaw(ctx, domid) < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_set(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *dom = NULL;
-    uint32_t weight = 0, cap = 0, compress = 0;
-    int opt_w = 0, opt_c = 0, opt_p = 0;
-    int all = 0;
-    int opt;
-    int rc = 0;
-
-    SWITCH_FOREACH_OPT(opt, "aw:c:p:", NULL, "tmem-set", 0) {
-    case 'a':
-        all = 1;
-        break;
-    case 'w':
-        weight = strtol(optarg, NULL, 10);
-        opt_w = 1;
-        break;
-    case 'c':
-        cap = strtol(optarg, NULL, 10);
-        opt_c = 1;
-        break;
-    case 'p':
-        compress = strtol(optarg, NULL, 10);
-        opt_p = 1;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-set");
-        return EXIT_FAILURE;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = find_domain(dom);
-
-    if (!opt_w && !opt_c && !opt_p) {
-        fprintf(stderr, "No set value specified.\n\n");
-        help("tmem-set");
-        return EXIT_FAILURE;
-    }
-
-    if (opt_w)
-        rc = libxl_tmem_set(ctx, domid, "weight", weight);
-    if (opt_c)
-        rc = libxl_tmem_set(ctx, domid, "cap", cap);
-    if (opt_p)
-        rc = libxl_tmem_set(ctx, domid, "compress", compress);
-
-    if (rc < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_shared_auth(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *autharg = NULL;
-    char *endptr = NULL;
-    const char *dom = NULL;
-    char *uuid = NULL;
-    int auth = -1;
-    int all = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "au:A:", NULL, "tmem-shared-auth", 0) {
-    case 'a':
-        all = 1;
-        break;
-    case 'u':
-        uuid = optarg;
-        break;
-    case 'A':
-        autharg = optarg;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-shared-auth");
-        return EXIT_FAILURE;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = find_domain(dom);
-
-    if (uuid == NULL || autharg == NULL) {
-        fprintf(stderr, "No uuid or auth specified.\n\n");
-        help("tmem-shared-auth");
-        return EXIT_FAILURE;
-    }
-
-    auth = strtol(autharg, &endptr, 10);
-    if (*endptr != '\0') {
-        fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_tmem_shared_auth(ctx, domid, uuid, auth) < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_freeable(int argc, char **argv)
-{
-    int opt;
-    int mb;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "tmem-freeable", 0) {
-        /* No options */
-    }
-
-    mb = libxl_tmem_freeable(ctx);
-    if (mb == -1)
-        return EXIT_FAILURE;
-
-    printf("%d\n", mb);
-    return EXIT_SUCCESS;
-}
-
-int main_cpupoolcreate(int argc, char **argv)
-{
-    const char *filename = NULL, *config_src=NULL;
-    const char *p;
-    char *extra_config = NULL;
-    int opt;
-    static struct option opts[] = {
-        {"defconfig", 1, 0, 'f'},
-        {"dryrun", 0, 0, 'n'},
-        COMMON_LONG_OPTS
-    };
-    int ret;
-    char *config_data = 0;
-    int config_len = 0;
-    XLU_Config *config;
-    const char *buf;
-    char *name = NULL;
-    uint32_t poolid;
-    libxl_scheduler sched = 0;
-    XLU_ConfigList *cpus;
-    XLU_ConfigList *nodes;
-    int n_cpus, n_nodes, i, n;
-    libxl_bitmap freemap;
-    libxl_bitmap cpumap;
-    libxl_uuid uuid;
-    libxl_cputopology *topology;
-    int rc = EXIT_FAILURE;
-
-    SWITCH_FOREACH_OPT(opt, "nf:", opts, "cpupool-create", 0) {
-    case 'f':
-        filename = optarg;
-        break;
-    case 'n':
-        dryrun_only = 1;
-        break;
-    }
-
-    libxl_bitmap_init(&freemap);
-    libxl_bitmap_init(&cpumap);
-
-    while (optind < argc) {
-        if ((p = strchr(argv[optind], '='))) {
-            string_realloc_append(&extra_config, "\n");
-            string_realloc_append(&extra_config, argv[optind]);
-        } else if (!filename) {
-            filename = argv[optind];
-        } else {
-            help("cpupool-create");
-            goto out;
-        }
-        optind++;
-    }
-
-    if (filename)
-    {
-        if (libxl_read_file_contents(ctx, filename, (void **)&config_data,
-                                     &config_len)) {
-            fprintf(stderr, "Failed to read config file: %s: %s\n",
-                    filename, strerror(errno));
-            goto out;
-        }
-        config_src=filename;
-    }
-    else
-        config_src="command line";
-
-    if (extra_config && strlen(extra_config)) {
-        if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
-            fprintf(stderr, "Failed to attach extra configuration\n");
-            goto out;
-        }
-        config_data = xrealloc(config_data,
-                               config_len + strlen(extra_config) + 2);
-        if (!config_data) {
-            fprintf(stderr, "Failed to realloc config_data\n");
-            goto out;
-        }
-        config_data[config_len] = 0;
-        strcat(config_data, extra_config);
-        strcat(config_data, "\n");
-        config_len += strlen(extra_config) + 1;
-    }
-
-    config = xlu_cfg_init(stderr, config_src);
-    if (!config) {
-        fprintf(stderr, "Failed to allocate for configuration\n");
-        goto out;
-    }
-
-    ret = xlu_cfg_readdata(config, config_data, config_len);
-    if (ret) {
-        fprintf(stderr, "Failed to parse config file: %s\n", strerror(ret));
-        goto out_cfg;
-    }
-
-    if (!xlu_cfg_get_string (config, "name", &buf, 0))
-        name = strdup(buf);
-    else if (filename)
-        name = libxl_basename(filename);
-    else {
-        fprintf(stderr, "Missing cpupool name!\n");
-        goto out_cfg;
-    }
-    if (!libxl_name_to_cpupoolid(ctx, name, &poolid)) {
-        fprintf(stderr, "Pool name \"%s\" already exists\n", name);
-        goto out_cfg;
-    }
-
-    if (!xlu_cfg_get_string (config, "sched", &buf, 0)) {
-        if ((libxl_scheduler_from_string(buf, &sched)) < 0) {
-            fprintf(stderr, "Unknown scheduler\n");
-            goto out_cfg;
-        }
-    } else {
-        rc = libxl_get_scheduler(ctx);
-        if (rc < 0) {
-            fprintf(stderr, "get_scheduler sysctl failed.\n");
-            goto out_cfg;
-        }
-        sched = rc;
-    }
-
-    if (libxl_get_freecpus(ctx, &freemap)) {
-        fprintf(stderr, "libxl_get_freecpus failed\n");
-        goto out_cfg;
-    }
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
-        fprintf(stderr, "Failed to allocate cpumap\n");
-        goto out_cfg;
-    }
-    if (!xlu_cfg_get_list(config, "nodes", &nodes, 0, 0)) {
-        int nr;
-        n_cpus = 0;
-        n_nodes = 0;
-        topology = libxl_get_cpu_topology(ctx, &nr);
-        if (topology == NULL) {
-            fprintf(stderr, "libxl_get_topologyinfo failed\n");
-            goto out_cfg;
-        }
-        while ((buf = xlu_cfg_get_listitem(nodes, n_nodes)) != NULL) {
-            n = atoi(buf);
-            for (i = 0; i < nr; i++) {
-                if ((topology[i].node == n) &&
-                    libxl_bitmap_test(&freemap, i)) {
-                    libxl_bitmap_set(&cpumap, i);
-                    n_cpus++;
-                }
-            }
-            n_nodes++;
-        }
-
-        libxl_cputopology_list_free(topology, nr);
-
-        if (n_cpus == 0) {
-            fprintf(stderr, "no free cpu found\n");
-            goto out_cfg;
-        }
-    } else if (!xlu_cfg_get_list(config, "cpus", &cpus, 0, 1)) {
-        n_cpus = 0;
-        while ((buf = xlu_cfg_get_listitem(cpus, n_cpus)) != NULL) {
-            i = atoi(buf);
-            if ((i < 0) || !libxl_bitmap_test(&freemap, i)) {
-                fprintf(stderr, "cpu %d illegal or not free\n", i);
-                goto out_cfg;
-            }
-            libxl_bitmap_set(&cpumap, i);
-            n_cpus++;
-        }
-    } else if (!xlu_cfg_get_string(config, "cpus", &buf, 0)) {
-        if (cpurange_parse(buf, &cpumap))
-            goto out_cfg;
-
-        n_cpus = 0;
-        libxl_for_each_set_bit(i, cpumap) {
-            if (!libxl_bitmap_test(&freemap, i)) {
-                fprintf(stderr, "cpu %d illegal or not free\n", i);
-                goto out_cfg;
-            }
-            n_cpus++;
-        }
-    } else
-        n_cpus = 0;
-
-    libxl_uuid_generate(&uuid);
-
-    printf("Using config file \"%s\"\n", config_src);
-    printf("cpupool name:   %s\n", name);
-    printf("scheduler:      %s\n", libxl_scheduler_to_string(sched));
-    printf("number of cpus: %d\n", n_cpus);
-
-    if (!dryrun_only) {
-        poolid = LIBXL_CPUPOOL_POOLID_ANY;
-        if (libxl_cpupool_create(ctx, name, sched, cpumap, &uuid, &poolid)) {
-            fprintf(stderr, "error on creating cpupool\n");
-            goto out_cfg;
-        }
-    }
-    /* We made it! */
-    rc = EXIT_SUCCESS;
-   
-out_cfg:
-    xlu_cfg_destroy(config);
-out:
-    libxl_bitmap_dispose(&freemap);
-    libxl_bitmap_dispose(&cpumap);
-    free(name);
-    free(config_data);
-    free(extra_config);
-    return rc;
-}
-
-int main_cpupoollist(int argc, char **argv)
-{
-    int opt;
-    static struct option opts[] = {
-        {"cpus", 0, 0, 'c'},
-        COMMON_LONG_OPTS
-    };
-    int opt_cpus = 0;
-    const char *pool = NULL;
-    libxl_cpupoolinfo *poolinfo;
-    int n_pools, p, c, n;
-    uint32_t poolid;
-    char *name;
-
-    SWITCH_FOREACH_OPT(opt, "c", opts, "cpupool-list", 0) {
-    case 'c':
-        opt_cpus = 1;
-        break;
-    }
-
-    if (optind < argc) {
-        pool = argv[optind];
-        if (libxl_name_to_cpupoolid(ctx, pool, &poolid)) {
-            fprintf(stderr, "Pool \'%s\' does not exist\n", pool);
-            return EXIT_FAILURE;
-        }
-    }
-
-    poolinfo = libxl_list_cpupool(ctx, &n_pools);
-    if (!poolinfo) {
-        fprintf(stderr, "error getting cpupool info\n");
-        return EXIT_FAILURE;
-    }
-
-    printf("%-19s", "Name");
-    if (opt_cpus)
-        printf("CPU list\n");
-    else
-        printf("CPUs   Sched     Active   Domain count\n");
-
-    for (p = 0; p < n_pools; p++) {
-        if (!pool || (poolinfo[p].poolid == poolid)) {
-            name = poolinfo[p].pool_name;
-            printf("%-19s", name);
-            n = 0;
-            libxl_for_each_bit(c, poolinfo[p].cpumap)
-                if (libxl_bitmap_test(&poolinfo[p].cpumap, c)) {
-                    if (n && opt_cpus) printf(",");
-                    if (opt_cpus) printf("%d", c);
-                    n++;
-                }
-            if (!opt_cpus) {
-                printf("%3d %9s       y       %4d", n,
-                       libxl_scheduler_to_string(poolinfo[p].sched),
-                       poolinfo[p].n_dom);
-            }
-            printf("\n");
-        }
-    }
-
-    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
-
-    return EXIT_SUCCESS;
-}
-
-int main_cpupooldestroy(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    uint32_t poolid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-destroy", 1) {
-        /* No options */
-    }
-
-    pool = argv[optind];
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_cpupool_destroy(ctx, poolid)) {
-        fprintf(stderr, "Can't destroy cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_cpupoolrename(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    const char *new_name;
-    uint32_t poolid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-rename", 2) {
-        /* No options */
-    }
-
-    pool = argv[optind++];
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    new_name = argv[optind];
-
-    if (libxl_cpupool_rename(ctx, new_name, poolid)) {
-        fprintf(stderr, "Can't rename cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_cpupoolcpuadd(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    uint32_t poolid;
-    libxl_bitmap cpumap;
-    int rc = EXIT_FAILURE;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-cpu-add", 2) {
-        /* No options */
-    }
-
-    libxl_bitmap_init(&cpumap);
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
-        fprintf(stderr, "Unable to allocate cpumap");
-        return EXIT_FAILURE;
-    }
-
-    pool = argv[optind++];
-    if (cpurange_parse(argv[optind], &cpumap))
-        goto out;
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
-        goto out;
-    }
-
-    if (libxl_cpupool_cpuadd_cpumap(ctx, poolid, &cpumap))
-        fprintf(stderr, "some cpus may not have been added to %s\n", pool);
-
-    rc = EXIT_SUCCESS;
-
-out:
-    libxl_bitmap_dispose(&cpumap);
-    return rc;
-}
-
-int main_cpupoolcpuremove(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    uint32_t poolid;
-    libxl_bitmap cpumap;
-    int rc = EXIT_FAILURE;
-
-    libxl_bitmap_init(&cpumap);
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
-        fprintf(stderr, "Unable to allocate cpumap");
-        return EXIT_FAILURE;
-    }
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-cpu-remove", 2) {
-        /* No options */
-    }
-
-    pool = argv[optind++];
-    if (cpurange_parse(argv[optind], &cpumap))
-        goto out;
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
-        goto out;
-    }
-
-    if (libxl_cpupool_cpuremove_cpumap(ctx, poolid, &cpumap)) {
-        fprintf(stderr, "Some cpus may have not or only partially been removed from '%s'.\n", pool);
-        fprintf(stderr, "If a cpu can't be added to another cpupool, add it to '%s' again and retry.\n", pool);
-    }
-
-    rc = EXIT_SUCCESS;
-
-out:
-    libxl_bitmap_dispose(&cpumap);
-    return rc;
-}
-
-int main_cpupoolmigrate(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    uint32_t poolid;
-    const char *dom;
-    uint32_t domid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-migrate", 2) {
-        /* No options */
-    }
-
-    dom = argv[optind++];
-    pool = argv[optind];
-
-    if (libxl_domain_qualifier_to_domid(ctx, dom, &domid) ||
-        !libxl_domid_to_name(ctx, domid)) {
-        fprintf(stderr, "unknown domain '%s'\n", dom);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_cpupool_movedomain(ctx, poolid, domid))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_cpupoolnumasplit(int argc, char **argv)
-{
-    int rc;
-    int opt;
-    int p;
-    int c;
-    int n;
-    uint32_t poolid;
-    libxl_scheduler sched;
-    int n_pools;
-    int node;
-    int n_cpus;
-    char *name = NULL;
-    libxl_uuid uuid;
-    libxl_bitmap cpumap;
-    libxl_cpupoolinfo *poolinfo;
-    libxl_cputopology *topology;
-    libxl_dominfo info;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-numa-split", 0) {
-        /* No options */
-    }
-
-    libxl_dominfo_init(&info);
-
-    rc = EXIT_FAILURE;
-
-    libxl_bitmap_init(&cpumap);
-    poolinfo = libxl_list_cpupool(ctx, &n_pools);
-    if (!poolinfo) {
-        fprintf(stderr, "error getting cpupool info\n");
-        return EXIT_FAILURE;
-    }
-    poolid = poolinfo[0].poolid;
-    sched = poolinfo[0].sched;
-    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
-
-    if (n_pools > 1) {
-        fprintf(stderr, "splitting not possible, already cpupools in use\n");
-        return EXIT_FAILURE;
-    }
-
-    topology = libxl_get_cpu_topology(ctx, &n_cpus);
-    if (topology == NULL) {
-        fprintf(stderr, "libxl_get_topologyinfo failed\n");
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
-        fprintf(stderr, "Failed to allocate cpumap\n");
-        goto out;
-    }
-
-    /* Reset Pool-0 to 1st node: first add cpus, then remove cpus to avoid
-       a cpupool without cpus in between */
-
-    node = topology[0].node;
-    if (libxl_cpupool_cpuadd_node(ctx, 0, node, &n)) {
-        fprintf(stderr, "error on adding cpu to Pool 0\n");
-        goto out;
-    }
-
-    xasprintf(&name, "Pool-node%d", node);
-    if (libxl_cpupool_rename(ctx, name, 0)) {
-        fprintf(stderr, "error on renaming Pool 0\n");
-        goto out;
-    }
-
-    n = 0;
-    for (c = 0; c < n_cpus; c++) {
-        if (topology[c].node == node) {
-            topology[c].node = LIBXL_CPUTOPOLOGY_INVALID_ENTRY;
-            libxl_bitmap_set(&cpumap, n);
-            n++;
-        }
-    }
-    if (libxl_domain_info(ctx, &info, 0)) {
-        fprintf(stderr, "error on getting info for Domain-0\n");
-        goto out;
-    }
-    if (info.vcpu_online > n && libxl_set_vcpuonline(ctx, 0, &cpumap)) {
-        fprintf(stderr, "error on removing vcpus for Domain-0\n");
-        goto out;
-    }
-    for (c = 0; c < 10; c++) {
-        /* We've called libxl_dominfo_init before the loop and will
-         * call libxl_dominfo_dispose after the loop when we're done
-         * with info.
-         */
-        libxl_dominfo_dispose(&info);
-        libxl_dominfo_init(&info);
-        if (libxl_domain_info(ctx, &info, 0)) {
-            fprintf(stderr, "error on getting info for Domain-0\n");
-            goto out;
-        }
-        if (info.vcpu_online <= n) {
-            break;
-        }
-        sleep(1);
-    }
-    if (info.vcpu_online > n) {
-        fprintf(stderr, "failed to offline vcpus\n");
-        goto out;
-    }
-    libxl_bitmap_set_none(&cpumap);
-
-    for (c = 0; c < n_cpus; c++) {
-        if (topology[c].node == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) {
-            continue;
-        }
-
-        node = topology[c].node;
-        if (libxl_cpupool_cpuremove_node(ctx, 0, node, &n)) {
-            fprintf(stderr, "error on removing cpu from Pool 0\n");
-            goto out;
-        }
-
-        free(name);
-        xasprintf(&name, "Pool-node%d", node);
-        libxl_uuid_generate(&uuid);
-        poolid = 0;
-        if (libxl_cpupool_create(ctx, name, sched, cpumap, &uuid, &poolid)) {
-            fprintf(stderr, "error on creating cpupool\n");
-            goto out;
-        }
-
-        if (libxl_cpupool_cpuadd_node(ctx, poolid, node, &n)) {
-            fprintf(stderr, "error on adding cpus to cpupool\n");
-            goto out;
-        }
-
-        for (p = c; p < n_cpus; p++) {
-            if (topology[p].node == node) {
-                topology[p].node = LIBXL_CPUTOPOLOGY_INVALID_ENTRY;
-            }
-        }
-    }
-
-    rc = EXIT_SUCCESS;
-
-out:
-    libxl_cputopology_list_free(topology, n_cpus);
-    libxl_bitmap_dispose(&cpumap);
-    libxl_dominfo_dispose(&info);
-    free(name);
-
-    return rc;
-}
-
-int main_getenforce(int argc, char **argv)
-{
-    int ret;
-
-    ret = libxl_flask_getenforce(ctx);
-
-    if (ret < 0) {
-        if (errno == ENOSYS)
-            printf("Flask XSM Disabled\n");
-        else
-            fprintf(stderr, "Failed to get enforcing mode\n");
-    }
-    else if (ret == 1)
-        printf("Enforcing\n");
-    else if (ret == 0)
-        printf("Permissive\n");
-
-    return ret;
-}
-
-int main_setenforce(int argc, char **argv)
-{
-    int ret, mode;
-    const char *p = NULL;
-
-    if (optind >= argc) {
-        help("setenforce");
-        return 2;
-    }
-
-    p = argv[optind];
-
-    if (!strcmp(p, "0"))
-        mode = 0;
-    else if (!strcmp(p, "1"))
-        mode = 1;
-    else if (!strcasecmp(p, "permissive"))
-        mode = 0;
-    else if (!strcasecmp(p, "enforcing"))
-        mode = 1;
-    else {
-        help("setenforce");
-        return 2;
-    }
-
-    ret = libxl_flask_setenforce(ctx, mode);
-
-    if (ret) {
-        if (errno == ENOSYS) {
-            fprintf(stderr, "Flask XSM disabled\n");
-        }
-        else
-            fprintf(stderr, "error occured while setting enforcing mode (%i)\n", ret);
-    }
-
-    return ret;
-}
-
-int main_loadpolicy(int argc, char **argv)
-{
-    const char *polFName;
-    int polFd = -1;
-    void *polMemCp = NULL;
-    struct stat info;
-    int ret;
-
-    if (optind >= argc) {
-        help("loadpolicy");
-        return 2;
-    }
-
-    polFName = argv[optind];
-    polFd = open(polFName, O_RDONLY);
-    if (polFd < 0) {
-        fprintf(stderr, "Error occurred opening policy file '%s': %s\n",
-                polFName, strerror(errno));
-        ret = -1;
-        goto done;
-    }
-
-    ret = stat(polFName, &info);
-    if (ret < 0) {
-        fprintf(stderr, "Error occurred retrieving information about"
-                "policy file '%s': %s\n", polFName, strerror(errno));
-        goto done;
-    }
-
-    polMemCp = malloc(info.st_size);
-
-    ret = read(polFd, polMemCp, info.st_size);
-    if ( ret < 0 ) {
-        fprintf(stderr, "Unable to read new Flask policy file: %s\n",
-                strerror(errno));
-        goto done;
-    }
-
-    ret = libxl_flask_loadpolicy(ctx, polMemCp, info.st_size);
-
-    if (ret < 0) {
-        if (errno == ENOSYS) {
-            fprintf(stderr, "Flask XSM disabled\n");
-        } else {
-            errno = -ret;
-            fprintf(stderr, "Unable to load new Flask policy: %s\n",
-                    strerror(errno));
-            ret = -1;
-        }
-    } else {
-        printf("Successfully loaded policy.\n");
-    }
-
-done:
-    free(polMemCp);
-    if (polFd >= 0)
-        close(polFd);
-
-    return ret;
-}
-
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-int main_remus(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc, daemonize = 1;
-    const char *ssh_command = "ssh";
-    char *host = NULL, *rune = NULL;
-    libxl_domain_remus_info r_info;
-    int send_fd = -1, recv_fd = -1;
-    pid_t child = -1;
-    uint8_t *config_data;
-    int config_len;
-
-    memset(&r_info, 0, sizeof(libxl_domain_remus_info));
-
-    SWITCH_FOREACH_OPT(opt, "Fbundi:s:N:ec", NULL, "remus", 2) {
-    case 'i':
-        r_info.interval = atoi(optarg);
-        break;
-    case 'F':
-        libxl_defbool_set(&r_info.allow_unsafe, true);
-        break;
-    case 'b':
-        libxl_defbool_set(&r_info.blackhole, true);
-        break;
-    case 'u':
-        libxl_defbool_set(&r_info.compression, false);
-        break;
-    case 'n':
-        libxl_defbool_set(&r_info.netbuf, false);
-        break;
-    case 'N':
-        r_info.netbufscript = optarg;
-        break;
-    case 'd':
-        libxl_defbool_set(&r_info.diskbuf, false);
-        break;
-    case 's':
-        ssh_command = optarg;
-        break;
-    case 'e':
-        daemonize = 0;
-        break;
-    case 'c':
-        libxl_defbool_set(&r_info.colo, true);
-    }
-
-    domid = find_domain(argv[optind]);
-    host = argv[optind + 1];
-
-    /* Defaults */
-    libxl_defbool_setdefault(&r_info.blackhole, false);
-    libxl_defbool_setdefault(&r_info.colo, false);
-    if (!libxl_defbool_val(r_info.colo) && !r_info.interval)
-        r_info.interval = 200;
-
-    if (libxl_defbool_val(r_info.colo)) {
-        if (r_info.interval || libxl_defbool_val(r_info.blackhole) ||
-            !libxl_defbool_is_default(r_info.netbuf) ||
-            !libxl_defbool_is_default(r_info.diskbuf)) {
-            perror("option -c is conflict with -i, -d, -n or -b");
-            exit(-1);
-        }
-
-        if (libxl_defbool_is_default(r_info.compression)) {
-            perror("COLO can't be used with memory compression. "
-                   "Disable memory checkpoint compression now...");
-            libxl_defbool_set(&r_info.compression, false);
-        }
-    }
-
-    if (!r_info.netbufscript) {
-        if (libxl_defbool_val(r_info.colo))
-            r_info.netbufscript = default_colo_proxy_script;
-        else
-            r_info.netbufscript = default_remus_netbufscript;
-    }
-
-    if (libxl_defbool_val(r_info.blackhole)) {
-        send_fd = open("/dev/null", O_RDWR, 0644);
-        if (send_fd < 0) {
-            perror("failed to open /dev/null");
-            exit(EXIT_FAILURE);
-        }
-    } else {
-
-        if (!ssh_command[0]) {
-            rune = host;
-        } else {
-            if (!libxl_defbool_val(r_info.colo)) {
-                xasprintf(&rune, "exec %s %s xl migrate-receive %s %s",
-                          ssh_command, host,
-                          "-r",
-                          daemonize ? "" : " -e");
-            } else {
-                xasprintf(&rune, "exec %s %s xl migrate-receive %s %s %s %s",
-                          ssh_command, host,
-                          "--colo",
-                          r_info.netbufscript ? "--coloft-script" : "",
-                          r_info.netbufscript ? r_info.netbufscript : "",
-                          daemonize ? "" : " -e");
-            }
-        }
-
-        save_domain_core_begin(domid, NULL, &config_data, &config_len);
-
-        if (!config_len) {
-            fprintf(stderr, "No config file stored for running domain and "
-                    "none supplied - cannot start remus.\n");
-            exit(EXIT_FAILURE);
-        }
-
-        child = create_migration_child(rune, &send_fd, &recv_fd);
-
-        migrate_do_preamble(send_fd, recv_fd, child, config_data, config_len,
-                            rune);
-
-        if (ssh_command[0])
-            free(rune);
-    }
-
-    /* Point of no return */
-    rc = libxl_domain_remus_start(ctx, &r_info, domid, send_fd, recv_fd, 0);
-
-    /* check if the domain exists. User may have xl destroyed the
-     * domain to force failover
-     */
-    if (libxl_domain_info(ctx, 0, domid)) {
-        fprintf(stderr, "%s: Primary domain has been destroyed.\n",
-                libxl_defbool_val(r_info.colo) ? "COLO" : "Remus");
-        close(send_fd);
-        return EXIT_SUCCESS;
-    }
-
-    /* If we are here, it means remus setup/domain suspend/backup has
-     * failed. Try to resume the domain and exit gracefully.
-     * TODO: Split-Brain check.
-     */
-    if (rc == ERROR_GUEST_TIMEDOUT)
-        fprintf(stderr, "Failed to suspend domain at primary.\n");
-    else {
-        fprintf(stderr, "%s: Backup failed? resuming domain at primary.\n",
-                libxl_defbool_val(r_info.colo) ? "COLO" : "Remus");
-        libxl_domain_resume(ctx, domid, 1, 0);
-    }
-
-    close(send_fd);
-    return EXIT_FAILURE;
-}
-#endif
-
-int main_devd(int argc, char **argv)
-{
-    int ret = 0, opt = 0, daemonize = 1;
-    const char *pidfile = NULL;
-    static const struct option opts[] = {
-        {"pidfile", 1, 0, 'p'},
-        COMMON_LONG_OPTS,
-        {0, 0, 0, 0}
-    };
-
-    SWITCH_FOREACH_OPT(opt, "Fp:", opts, "devd", 0) {
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'p':
-        pidfile = optarg;
-        break;
-    }
-
-    if (daemonize) {
-        ret = do_daemonize("xldevd", pidfile);
-        if (ret) {
-            ret = (ret == 1) ? 0 : ret;
-            goto out;
-        }
-    }
-
-    libxl_device_events_handler(ctx, 0);
-
-out:
-    return ret;
-}
-
-#ifdef LIBXL_HAVE_PSR_CMT
-static int psr_cmt_hwinfo(void)
-{
-    int rc;
-    int enabled;
-    uint32_t total_rmid;
-
-    printf("Cache Monitoring Technology (CMT):\n");
-
-    enabled = libxl_psr_cmt_enabled(ctx);
-    printf("%-16s: %s\n", "Enabled", enabled ? "1" : "0");
-    if (!enabled)
-        return 0;
-
-    rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
-    if (rc) {
-        fprintf(stderr, "Failed to get max RMID value\n");
-        return rc;
-    }
-    printf("%-16s: %u\n", "Total RMID", total_rmid);
-
-    printf("Supported monitor types:\n");
-    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY))
-        printf("cache-occupancy\n");
-    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT))
-        printf("total-mem-bandwidth\n");
-    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT))
-        printf("local-mem-bandwidth\n");
-
-    return rc;
-}
-
-#define MBM_SAMPLE_RETRY_MAX 4
-static int psr_cmt_get_mem_bandwidth(uint32_t domid,
-                                     libxl_psr_cmt_type type,
-                                     uint32_t socketid,
-                                     uint64_t *bandwidth_r)
-{
-    uint64_t sample1, sample2;
-    uint64_t tsc1, tsc2;
-    int retry_attempts = 0;
-    int rc;
-
-    while (1) {
-        rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
-                                      &sample1, &tsc1);
-        if (rc < 0)
-            return rc;
-
-        usleep(10000);
-
-        rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
-                                      &sample2, &tsc2);
-        if (rc < 0)
-            return rc;
-
-        if (tsc2 <= tsc1)
-            return -1;
-
-        /*
-         * Hardware guarantees at most 1 overflow can happen if the duration
-         * between two samples is less than 1 second. Note that tsc returned
-         * from hypervisor is already-scaled time(ns).
-         */
-        if (tsc2 - tsc1 < 1000000000 && sample2 >= sample1)
-            break;
-
-        if (retry_attempts < MBM_SAMPLE_RETRY_MAX) {
-            retry_attempts++;
-        } else {
-            fprintf(stderr, "event counter overflowed\n");
-            return -1;
-        }
-    }
-
-    *bandwidth_r = (sample2 - sample1) * 1000000000 / (tsc2 - tsc1) / 1024;
-    return 0;
-}
-
-static void psr_cmt_print_domain_info(libxl_dominfo *dominfo,
-                                      libxl_psr_cmt_type type,
-                                      libxl_bitmap *socketmap)
-{
-    char *domain_name;
-    uint32_t socketid;
-    uint64_t monitor_data;
-
-    if (!libxl_psr_cmt_domain_attached(ctx, dominfo->domid))
-        return;
-
-    domain_name = libxl_domid_to_name(ctx, dominfo->domid);
-    printf("%-40s %5d", domain_name, dominfo->domid);
-    free(domain_name);
-
-    libxl_for_each_set_bit(socketid, *socketmap) {
-        switch (type) {
-        case LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY:
-            if (!libxl_psr_cmt_get_sample(ctx, dominfo->domid, type, socketid,
-                                          &monitor_data, NULL))
-                printf("%13"PRIu64" KB", monitor_data / 1024);
-            break;
-        case LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT:
-        case LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT:
-            if (!psr_cmt_get_mem_bandwidth(dominfo->domid, type, socketid,
-                                           &monitor_data))
-                printf("%11"PRIu64" KB/s", monitor_data);
-            break;
-        default:
-            return;
-        }
-    }
-
-    printf("\n");
-}
-
-static int psr_cmt_show(libxl_psr_cmt_type type, uint32_t domid)
-{
-    uint32_t i, socketid, total_rmid;
-    uint32_t l3_cache_size;
-    libxl_bitmap socketmap;
-    int rc, nr_domains;
-
-    if (!libxl_psr_cmt_enabled(ctx)) {
-        fprintf(stderr, "CMT is disabled in the system\n");
-        return -1;
-    }
-
-    if (!libxl_psr_cmt_type_supported(ctx, type)) {
-        fprintf(stderr, "Monitor type '%s' is not supported in the system\n",
-                libxl_psr_cmt_type_to_string(type));
-        return -1;
-    }
-
-    libxl_bitmap_init(&socketmap);
-    libxl_socket_bitmap_alloc(ctx, &socketmap, 0);
-    rc = libxl_get_online_socketmap(ctx, &socketmap);
-    if (rc < 0) {
-        fprintf(stderr, "Failed getting available sockets, rc: %d\n", rc);
-        goto out;
-    }
-
-    rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
-    if (rc < 0) {
-        fprintf(stderr, "Failed to get max RMID value\n");
-        goto out;
-    }
-
-    printf("Total RMID: %d\n", total_rmid);
-
-    /* Header */
-    printf("%-40s %5s", "Name", "ID");
-    libxl_for_each_set_bit(socketid, socketmap)
-        printf("%14s %d", "Socket", socketid);
-    printf("\n");
-
-    if (type == LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY) {
-            /* Total L3 cache size */
-            printf("%-46s", "Total L3 Cache Size");
-            libxl_for_each_set_bit(socketid, socketmap) {
-                rc = libxl_psr_cmt_get_l3_cache_size(ctx, socketid,
-                                                     &l3_cache_size);
-                if (rc < 0) {
-                    fprintf(stderr,
-                            "Failed to get system l3 cache size for socket:%d\n",
-                            socketid);
-                    goto out;
-                }
-                printf("%13u KB", l3_cache_size);
-            }
-            printf("\n");
-    }
-
-    /* Each domain */
-    if (domid != INVALID_DOMID) {
-        libxl_dominfo dominfo;
-
-        libxl_dominfo_init(&dominfo);
-        if (libxl_domain_info(ctx, &dominfo, domid)) {
-            fprintf(stderr, "Failed to get domain info for %d\n", domid);
-            rc = -1;
-            goto out;
-        }
-        psr_cmt_print_domain_info(&dominfo, type, &socketmap);
-        libxl_dominfo_dispose(&dominfo);
-    }
-    else
-    {
-        libxl_dominfo *list;
-        if (!(list = libxl_list_domain(ctx, &nr_domains))) {
-            fprintf(stderr, "Failed to get domain info for domain list.\n");
-            rc = -1;
-            goto out;
-        }
-        for (i = 0; i < nr_domains; i++)
-            psr_cmt_print_domain_info(list + i, type, &socketmap);
-        libxl_dominfo_list_free(list, nr_domains);
-    }
-
-out:
-    libxl_bitmap_dispose(&socketmap);
-    return rc;
-}
-
-int main_psr_cmt_attach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, ret = 0;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-attach", 1) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    ret = libxl_psr_cmt_attach(ctx, domid);
-
-    return ret;
-}
-
-int main_psr_cmt_detach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, ret = 0;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-detach", 1) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    ret = libxl_psr_cmt_detach(ctx, domid);
-
-    return ret;
-}
-
-int main_psr_cmt_show(int argc, char **argv)
-{
-    int opt, ret = 0;
-    uint32_t domid;
-    libxl_psr_cmt_type type;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-show", 1) {
-        /* No options */
-    }
-
-    if (!strcmp(argv[optind], "cache-occupancy"))
-        type = LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY;
-    else if (!strcmp(argv[optind], "total-mem-bandwidth"))
-        type = LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT;
-    else if (!strcmp(argv[optind], "local-mem-bandwidth"))
-        type = LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT;
-    else {
-        help("psr-cmt-show");
-        return 2;
-    }
-
-    if (optind + 1 >= argc)
-        domid = INVALID_DOMID;
-    else if (optind + 1 == argc - 1)
-        domid = find_domain(argv[optind + 1]);
-    else {
-        help("psr-cmt-show");
-        return 2;
-    }
-
-    ret = psr_cmt_show(type, domid);
-
-    return ret;
-}
-#endif
-
-#ifdef LIBXL_HAVE_PSR_CAT
-static int psr_cat_hwinfo(void)
-{
-    int rc;
-    int i, nr;
-    uint32_t l3_cache_size;
-    libxl_psr_cat_info *info;
-
-    printf("Cache Allocation Technology (CAT):\n");
-
-    rc = libxl_psr_cat_get_l3_info(ctx, &info, &nr);
-    if (rc) {
-        fprintf(stderr, "Failed to get cat info\n");
-        return rc;
-    }
-
-    for (i = 0; i < nr; i++) {
-        rc = libxl_psr_cmt_get_l3_cache_size(ctx, info[i].id, &l3_cache_size);
-        if (rc) {
-            fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
-                    info[i].id);
-            goto out;
-        }
-        printf("%-16s: %u\n", "Socket ID", info[i].id);
-        printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
-        printf("%-16s: %s\n", "CDP Status",
-               info[i].cdp_enabled ? "Enabled" : "Disabled");
-        printf("%-16s: %u\n", "Maximum COS", info[i].cos_max);
-        printf("%-16s: %u\n", "CBM length", info[i].cbm_len);
-        printf("%-16s: %#llx\n", "Default CBM",
-               (1ull << info[i].cbm_len) - 1);
-    }
-
-out:
-    libxl_psr_cat_info_list_free(info, nr);
-    return rc;
-}
-
-static void psr_cat_print_one_domain_cbm_type(uint32_t domid, uint32_t socketid,
-                                              libxl_psr_cbm_type type)
-{
-    uint64_t cbm;
-
-    if (!libxl_psr_cat_get_cbm(ctx, domid, type, socketid, &cbm))
-        printf("%#16"PRIx64, cbm);
-    else
-        printf("%16s", "error");
-}
-
-static void psr_cat_print_one_domain_cbm(uint32_t domid, uint32_t socketid,
-                                         bool cdp_enabled)
-{
-    char *domain_name;
-
-    domain_name = libxl_domid_to_name(ctx, domid);
-    printf("%5d%25s", domid, domain_name);
-    free(domain_name);
-
-    if (!cdp_enabled) {
-        psr_cat_print_one_domain_cbm_type(domid, socketid,
-                                          LIBXL_PSR_CBM_TYPE_L3_CBM);
-    } else {
-        psr_cat_print_one_domain_cbm_type(domid, socketid,
-                                          LIBXL_PSR_CBM_TYPE_L3_CBM_CODE);
-        psr_cat_print_one_domain_cbm_type(domid, socketid,
-                                          LIBXL_PSR_CBM_TYPE_L3_CBM_DATA);
-    }
-
-    printf("\n");
-}
-
-static int psr_cat_print_domain_cbm(uint32_t domid, uint32_t socketid,
-                                    bool cdp_enabled)
-{
-    int i, nr_domains;
-    libxl_dominfo *list;
-
-    if (domid != INVALID_DOMID) {
-        psr_cat_print_one_domain_cbm(domid, socketid, cdp_enabled);
-        return 0;
-    }
-
-    if (!(list = libxl_list_domain(ctx, &nr_domains))) {
-        fprintf(stderr, "Failed to get domain list for cbm display\n");
-        return -1;
-    }
-
-    for (i = 0; i < nr_domains; i++)
-        psr_cat_print_one_domain_cbm(list[i].domid, socketid, cdp_enabled);
-    libxl_dominfo_list_free(list, nr_domains);
-
-    return 0;
-}
-
-static int psr_cat_print_socket(uint32_t domid, libxl_psr_cat_info *info)
-{
-    int rc;
-    uint32_t l3_cache_size;
-
-    rc = libxl_psr_cmt_get_l3_cache_size(ctx, info->id, &l3_cache_size);
-    if (rc) {
-        fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
-                info->id);
-        return -1;
-    }
-
-    printf("%-16s: %u\n", "Socket ID", info->id);
-    printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
-    printf("%-16s: %#llx\n", "Default CBM", (1ull << info->cbm_len) - 1);
-    if (info->cdp_enabled)
-        printf("%5s%25s%16s%16s\n", "ID", "NAME", "CBM (code)", "CBM (data)");
-    else
-        printf("%5s%25s%16s\n", "ID", "NAME", "CBM");
-
-    return psr_cat_print_domain_cbm(domid, info->id, info->cdp_enabled);
-}
-
-static int psr_cat_show(uint32_t domid)
-{
-    int i, nr;
-    int rc;
-    libxl_psr_cat_info *info;
-
-    rc = libxl_psr_cat_get_l3_info(ctx, &info, &nr);
-    if (rc) {
-        fprintf(stderr, "Failed to get cat info\n");
-        return rc;
-    }
-
-    for (i = 0; i < nr; i++) {
-        rc = psr_cat_print_socket(domid, info + i);
-        if (rc)
-            goto out;
-    }
-
-out:
-    libxl_psr_cat_info_list_free(info, nr);
-    return rc;
-}
-
-int main_psr_cat_cbm_set(int argc, char **argv)
-{
-    uint32_t domid;
-    libxl_psr_cbm_type type;
-    uint64_t cbm;
-    int ret, opt = 0;
-    int opt_data = 0, opt_code = 0;
-    libxl_bitmap target_map;
-    char *value;
-    libxl_string_list socket_list;
-    unsigned long start, end;
-    int i, j, len;
-
-    static struct option opts[] = {
-        {"socket", 1, 0, 's'},
-        {"data", 0, 0, 'd'},
-        {"code", 0, 0, 'c'},
-        COMMON_LONG_OPTS
-    };
-
-    libxl_socket_bitmap_alloc(ctx, &target_map, 0);
-    libxl_bitmap_set_none(&target_map);
-
-    SWITCH_FOREACH_OPT(opt, "s:cd", opts, "psr-cat-cbm-set", 2) {
-    case 's':
-        trim(isspace, optarg, &value);
-        split_string_into_string_list(value, ",", &socket_list);
-        len = libxl_string_list_length(&socket_list);
-        for (i = 0; i < len; i++) {
-            parse_range(socket_list[i], &start, &end);
-            for (j = start; j <= end; j++)
-                libxl_bitmap_set(&target_map, j);
-        }
-
-        libxl_string_list_dispose(&socket_list);
-        free(value);
-        break;
-    case 'd':
-        opt_data = 1;
-        break;
-    case 'c':
-        opt_code = 1;
-        break;
-    }
-
-    if (opt_data && opt_code) {
-        fprintf(stderr, "Cannot handle -c and -d at the same time\n");
-        return -1;
-    } else if (opt_data) {
-        type = LIBXL_PSR_CBM_TYPE_L3_CBM_DATA;
-    } else if (opt_code) {
-        type = LIBXL_PSR_CBM_TYPE_L3_CBM_CODE;
-    } else {
-        type = LIBXL_PSR_CBM_TYPE_L3_CBM;
-    }
-
-    if (libxl_bitmap_is_empty(&target_map))
-        libxl_bitmap_set_any(&target_map);
-
-    if (argc != optind + 2) {
-        help("psr-cat-cbm-set");
-        return 2;
-    }
-
-    domid = find_domain(argv[optind]);
-    cbm = strtoll(argv[optind + 1], NULL , 0);
-
-    ret = libxl_psr_cat_set_cbm(ctx, domid, type, &target_map, cbm);
-
-    libxl_bitmap_dispose(&target_map);
-    return ret;
-}
-
-int main_psr_cat_show(int argc, char **argv)
-{
-    int opt;
-    uint32_t domid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cat-show", 0) {
-        /* No options */
-    }
-
-    if (optind >= argc)
-        domid = INVALID_DOMID;
-    else if (optind == argc - 1)
-        domid = find_domain(argv[optind]);
-    else {
-        help("psr-cat-show");
-        return 2;
-    }
-
-    return psr_cat_show(domid);
-}
-
-int main_psr_hwinfo(int argc, char **argv)
-{
-    int opt, ret = 0;
-    bool all = true, cmt = false, cat = false;
-    static struct option opts[] = {
-        {"cmt", 0, 0, 'm'},
-        {"cat", 0, 0, 'a'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "ma", opts, "psr-hwinfo", 0) {
-    case 'm':
-        all = false; cmt = true;
-        break;
-    case 'a':
-        all = false; cat = true;
-        break;
-    }
-
-    if (!ret && (all || cmt))
-        ret = psr_cmt_hwinfo();
-
-    if (!ret && (all || cat))
-        ret = psr_cat_hwinfo();
-
-    return ret;
-}
-
-#endif
-
-int main_qemu_monitor_command(int argc, char **argv)
-{
-    int opt;
-    uint32_t domid;
-    char *cmd;
-    char *output;
-    int ret;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "qemu-monitor-command", 2) {
-        /* No options */
-    }
-
-    domid = find_domain(argv[optind]);
-    cmd = argv[optind + 1];
-
-    if (argc - optind > 2) {
-        fprintf(stderr, "Invalid arguments.\n");
-        return EXIT_FAILURE;
-    }
-
-    ret = libxl_qemu_monitor_command(ctx, domid, cmd, &output);
-    if (!ret && output) {
-        printf("%s\n", output);
-        free(output);
-    }
-
-    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
deleted file mode 100644 (file)
index 588d5d9..0000000
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * Author Yang Hongyang <yanghy@cn.fujitsu.com>
- *
- * 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 <string.h>
-
-#include "libxl.h"
-#include "xl.h"
-
-struct cmd_spec cmd_table[] = {
-    { "create",
-      &main_create, 1, 1,
-      "Create a domain from config file <filename>",
-      "<ConfigFile> [options] [vars]",
-      "-h                      Print this help.\n"
-      "-p                      Leave the domain paused after it is created.\n"
-      "-c                      Connect to the console after the domain is created.\n"
-      "-f FILE, --defconfig=FILE\n                     Use the given configuration file.\n"
-      "-q, --quiet             Quiet.\n"
-      "-n, --dryrun            Dry run - prints the resulting configuration\n"
-      "                         (deprecated in favour of global -N option).\n"
-      "-d                      Enable debug messages.\n"
-      "-F                      Run in foreground until death of the domain.\n"
-      "-e                      Do not wait in the background for the death of the domain.\n"
-      "-V, --vncviewer         Connect to the VNC display after the domain is created.\n"
-      "-A, --vncviewer-autopass\n"
-      "                        Pass VNC password to viewer via stdin."
-    },
-    { "config-update",
-      &main_config_update, 1, 1,
-      "Update a running domain's saved configuration, used when rebuilding "
-      "the domain after reboot.\n"
-      "WARNING: xl now has better capability to manage domain configuration, "
-      "avoid using this command when possible",
-      "<Domain> <ConfigFile> [options] [vars]",
-      "-h                      Print this help.\n"
-      "-f FILE, --defconfig=FILE\n                     Use the given configuration file.\n"
-      "-d                      Enable debug messages.\n"
-    },
-    { "list",
-      &main_list, 0, 0,
-      "List information about all/some domains",
-      "[options] [Domain]\n",
-      "-l, --long              Output all VM details\n"
-      "-v, --verbose           Prints out UUIDs and security context\n"
-      "-Z, --context           Prints out security context\n"
-      "-c, --cpupool           Prints the cpupool the domain is in\n"
-      "-n, --numa              Prints out NUMA node affinity"
-    },
-    { "destroy",
-      &main_destroy, 0, 1,
-      "Terminate a domain immediately",
-      "[options] <Domain>\n",
-      "-f                      Permit destroying domain 0, which will only succeed\n"
-      "                        when run from disaggregated toolstack domain with a\n"
-      "                        hardware domain distinct from domain 0."
-    },
-    { "shutdown",
-      &main_shutdown, 0, 1,
-      "Issue a shutdown signal to a domain",
-      "[options] <-a|Domain>",
-      "-a, --all               Shutdown all guest domains.\n"
-      "-h                      Print this help.\n"
-      "-F                      Fallback to ACPI power event for HVM guests with\n"
-      "                        no PV drivers.\n"
-      "-w, --wait              Wait for guest(s) to shutdown.\n"
-    },
-    { "reboot",
-      &main_reboot, 0, 1,
-      "Issue a reboot signal to a domain",
-      "[options] <-a|Domain>",
-      "-a, --all               Shutdown all guest domains.\n"
-      "-h                      Print this help.\n"
-      "-F                      Fallback to ACPI reset event for HVM guests with\n"
-      "                        no PV drivers.\n"
-      "-w, --wait              Wait for guest(s) to reboot.\n"
-    },
-    { "pci-attach",
-      &main_pciattach, 0, 1,
-      "Insert a new pass-through pci device",
-      "<Domain> <BDF> [Virtual Slot]",
-    },
-    { "pci-detach",
-      &main_pcidetach, 0, 1,
-      "Remove a domain's pass-through pci device",
-      "<Domain> <BDF>",
-    },
-    { "pci-list",
-      &main_pcilist, 0, 0,
-      "List pass-through pci devices for a domain",
-      "<Domain>",
-    },
-    { "pci-assignable-add",
-      &main_pciassignable_add, 0, 1,
-      "Make a device assignable for pci-passthru",
-      "<BDF>",
-      "-h                      Print this help.\n"
-    },
-    { "pci-assignable-remove",
-      &main_pciassignable_remove, 0, 1,
-      "Remove a device from being assignable",
-      "[options] <BDF>",
-      "-h                      Print this help.\n"
-      "-r                      Attempt to re-assign the device to the\n"
-      "                        original driver"
-    },
-    { "pci-assignable-list",
-      &main_pciassignable_list, 0, 0,
-      "List all the assignable pci devices",
-      "",
-    },
-    { "pause",
-      &main_pause, 0, 1,
-      "Pause execution of a domain",
-      "<Domain>",
-    },
-    { "unpause",
-      &main_unpause, 0, 1,
-      "Unpause a paused domain",
-      "<Domain>",
-    },
-    { "console",
-      &main_console, 0, 0,
-      "Attach to domain's console",
-      "[options] <Domain>\n"
-      "-t <type>       console type, pv or serial\n"
-      "-n <number>     console number"
-    },
-    { "vncviewer",
-      &main_vncviewer, 0, 0,
-      "Attach to domain's VNC server.",
-      "[options] <Domain>\n"
-      "--autopass               Pass VNC password to viewer via stdin and\n"
-      "                         -autopass\n"
-      "--vncviewer-autopass     (consistency alias for --autopass)"
-    },
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-    { "save",
-      &main_save, 0, 1,
-      "Save a domain state to restore later",
-      "[options] <Domain> <CheckpointFile> [<ConfigFile>]",
-      "-h  Print this help.\n"
-      "-c  Leave domain running after creating the snapshot.\n"
-      "-p  Leave domain paused after creating the snapshot."
-    },
-    { "migrate",
-      &main_migrate, 0, 1,
-      "Migrate a domain to another host",
-      "[options] <Domain> <host>",
-      "-h              Print this help.\n"
-      "-C <config>     Send <config> instead of config file from creation.\n"
-      "-s <sshcommand> Use <sshcommand> instead of ssh.  String will be passed\n"
-      "                to sh. If empty, run <host> instead of ssh <host> xl\n"
-      "                migrate-receive [-d -e]\n"
-      "-e              Do not wait in the background (on <host>) for the death\n"
-      "                of the domain.\n"
-      "--debug         Print huge (!) amount of debug during the migration process.\n"
-      "-p              Do not unpause domain after migrating it."
-    },
-    { "restore",
-      &main_restore, 0, 1,
-      "Restore a domain from a saved state",
-      "[options] [<ConfigFile>] <CheckpointFile>",
-      "-h                       Print this help.\n"
-      "-p                       Do not unpause domain after restoring it.\n"
-      "-e                       Do not wait in the background for the death of the domain.\n"
-      "-d                       Enable debug messages.\n"
-      "-V, --vncviewer          Connect to the VNC display after the domain is created.\n"
-      "-A, --vncviewer-autopass Pass VNC password to viewer via stdin."
-    },
-    { "migrate-receive",
-      &main_migrate_receive, 0, 1,
-      "Restore a domain from a saved state",
-      "- for internal use only",
-    },
-#endif
-    { "dump-core",
-      &main_dump_core, 0, 1,
-      "Core dump a domain",
-      "<Domain> <filename>"
-    },
-    { "cd-insert",
-      &main_cd_insert, 1, 1,
-      "Insert a cdrom into a guest's cd drive",
-      "<Domain> <VirtualDevice> <path>",
-    },
-    { "cd-eject",
-      &main_cd_eject, 1, 1,
-      "Eject a cdrom from a guest's cd drive",
-      "<Domain> <VirtualDevice>",
-    },
-    { "mem-max",
-      &main_memmax, 0, 1,
-      "Set the maximum amount reservation for a domain",
-      "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
-    },
-    { "mem-set",
-      &main_memset, 0, 1,
-      "Set the current memory usage for a domain",
-      "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
-    },
-    { "button-press",
-      &main_button_press, 0, 1,
-      "Indicate an ACPI button press to the domain",
-      "<Domain> <Button>",
-      "<Button> may be 'power' or 'sleep'."
-    },
-    { "vcpu-list",
-      &main_vcpulist, 0, 0,
-      "List the VCPUs for all/some domains",
-      "[Domain, ...]",
-    },
-    { "vcpu-pin",
-      &main_vcpupin, 1, 1,
-      "Set which CPUs a VCPU can use",
-      "[option] <Domain> <VCPU|all> <Hard affinity|-|all> <Soft affinity|-|all>",
-      "-f, --force        undo an override pinning done by the kernel",
-    },
-    { "vcpu-set",
-      &main_vcpuset, 0, 1,
-      "Set the number of active VCPUs allowed for the domain",
-      "[option] <Domain> <vCPUs>",
-      "-i, --ignore-host  Don't limit the vCPU based on the host CPU count",
-    },
-    { "vm-list",
-      &main_vm_list, 0, 0,
-      "List guest domains, excluding dom0, stubdoms, etc.",
-      "",
-    },
-    { "info",
-      &main_info, 0, 0,
-      "Get information about Xen host",
-      "-n, --numa         List host NUMA topology information",
-    },
-    { "sharing",
-      &main_sharing, 0, 0,
-      "Get information about page sharing",
-      "[Domain]", 
-    },
-    { "sched-credit",
-      &main_sched_credit, 0, 1,
-      "Get/set credit scheduler parameters",
-      "[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]] [-s [-t TSLICE] [-r RATELIMIT]] [-p CPUPOOL]",
-      "-d DOMAIN, --domain=DOMAIN        Domain to modify\n"
-      "-w WEIGHT, --weight=WEIGHT        Weight (int)\n"
-      "-c CAP, --cap=CAP                 Cap (int)\n"
-      "-s         --schedparam           Query / modify scheduler parameters\n"
-      "-t TSLICE, --tslice_ms=TSLICE     Set the timeslice, in milliseconds\n"
-      "-r RLIMIT, --ratelimit_us=RLIMIT  Set the scheduling rate limit, in microseconds\n"
-      "-p CPUPOOL, --cpupool=CPUPOOL     Restrict output to CPUPOOL"
-    },
-    { "sched-credit2",
-      &main_sched_credit2, 0, 1,
-      "Get/set credit2 scheduler parameters",
-      "[-d <Domain> [-w[=WEIGHT]]] [-p CPUPOOL]",
-      "-d DOMAIN, --domain=DOMAIN     Domain to modify\n"
-      "-w WEIGHT, --weight=WEIGHT     Weight (int)\n"
-      "-s         --schedparam        Query / modify scheduler parameters\n"
-      "-r RLIMIT, --ratelimit_us=RLIMIT Set the scheduling rate limit, in microseconds\n"
-      "-p CPUPOOL, --cpupool=CPUPOOL  Restrict output to CPUPOOL"
-    },
-    { "sched-rtds",
-      &main_sched_rtds, 0, 1,
-      "Get/set rtds scheduler parameters",
-      "[-d <Domain> [-v[=VCPUID/all]] [-p[=PERIOD]] [-b[=BUDGET]]]",
-      "-d DOMAIN, --domain=DOMAIN     Domain to modify\n"
-      "-v VCPUID/all, --vcpuid=VCPUID/all    VCPU to modify or output;\n"
-      "               Using '-v all' to modify/output all vcpus\n"
-      "-p PERIOD, --period=PERIOD     Period (us)\n"
-      "-b BUDGET, --budget=BUDGET     Budget (us)\n"
-    },
-    { "domid",
-      &main_domid, 0, 0,
-      "Convert a domain name to domain id",
-      "<DomainName>",
-    },
-    { "domname",
-      &main_domname, 0, 0,
-      "Convert a domain id to domain name",
-      "<DomainId>",
-    },
-    { "rename",
-      &main_rename, 0, 1,
-      "Rename a domain",
-      "<Domain> <NewDomainName>",
-    },
-    { "trigger",
-      &main_trigger, 0, 1,
-      "Send a trigger to a domain",
-      "<Domain> <nmi|reset|init|power|sleep|s3resume> [<VCPU>]",
-    },
-    { "sysrq",
-      &main_sysrq, 0, 1,
-      "Send a sysrq to a domain",
-      "<Domain> <letter>",
-    },
-    { "debug-keys",
-      &main_debug_keys, 0, 1,
-      "Send debug keys to Xen",
-      "<Keys>",
-    },
-    { "dmesg",
-      &main_dmesg, 0, 0,
-      "Read and/or clear dmesg buffer",
-      "[-c]",
-      "  -c                        Clear dmesg buffer as well as printing it",
-    },
-    { "top",
-      &main_top, 0, 0,
-      "Monitor a host and the domains in real time",
-      "",
-    },
-    { "network-attach",
-      &main_networkattach, 1, 1,
-      "Create a new virtual network device",
-      "<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] "
-      "[ip=<ip>] [script=<script>] [backend=<BackDomain>] [vifname=<name>] "
-      "[rate=<rate>] [model=<model>] [accel=<accel>]",
-    },
-    { "network-list",
-      &main_networklist, 0, 0,
-      "List virtual network interfaces for a domain",
-      "<Domain(s)>",
-    },
-    { "network-detach",
-      &main_networkdetach, 0, 1,
-      "Destroy a domain's virtual network device",
-      "<Domain> <DevId|mac>",
-    },
-    { "channel-list",
-      &main_channellist, 0, 0,
-      "List virtual channel devices for a domain",
-      "<Domain(s)>",
-    },
-    { "block-attach",
-      &main_blockattach, 1, 1,
-      "Create a new virtual block device",
-      "<Domain> <disk-spec-component(s)>...",
-    },
-    { "block-list",
-      &main_blocklist, 0, 0,
-      "List virtual block devices for a domain",
-      "<Domain(s)>",
-    },
-    { "block-detach",
-      &main_blockdetach, 0, 1,
-      "Destroy a domain's virtual block device",
-      "<Domain> <DevId>",
-    },
-    { "vtpm-attach",
-      &main_vtpmattach, 1, 1,
-      "Create a new virtual TPM device",
-      "<Domain> [uuid=<uuid>] [backend=<BackDomain>]",
-    },
-    { "vtpm-list",
-      &main_vtpmlist, 0, 0,
-      "List virtual TPM devices for a domain",
-      "<Domain(s)>",
-    },
-    { "vtpm-detach",
-      &main_vtpmdetach, 0, 1,
-      "Destroy a domain's virtual TPM device",
-      "<Domain> <DevId|uuid>",
-    },
-    { "uptime",
-      &main_uptime, 0, 0,
-      "Print uptime for all/some domains",
-      "[-s] [Domain]",
-    },
-    { "claims",
-      &main_claims, 0, 0,
-      "List outstanding claim information about all domains",
-      "",
-      "",
-    },
-    { "tmem-list",
-      &main_tmem_list, 0, 0,
-      "List tmem pools",
-      "[-l] [<Domain>|-a]",
-      "  -l                             List tmem stats",
-    },
-    { "tmem-freeze",
-      &main_tmem_freeze, 0, 1,
-      "Freeze tmem pools",
-      "[<Domain>|-a]",
-      "  -a                             Freeze all tmem",
-    },
-    { "tmem-thaw",
-      &main_tmem_thaw, 0, 1,
-      "Thaw tmem pools",
-      "[<Domain>|-a]",
-      "  -a                             Thaw all tmem",
-    },
-    { "tmem-set",
-      &main_tmem_set, 0, 1,
-      "Change tmem settings",
-      "[<Domain>|-a] [-w[=WEIGHT]|-c[=CAP]|-p[=COMPRESS]]",
-      "  -a                             Operate on all tmem\n"
-      "  -w WEIGHT                      Weight (int)\n"
-      "  -p COMPRESS                    Compress (int)",
-    },
-    { "tmem-shared-auth",
-      &main_tmem_shared_auth, 0, 1,
-      "De/authenticate shared tmem pool",
-      "[<Domain>|-a] [-u[=UUID] [-A[=AUTH]",
-      "  -a                             Authenticate for all tmem pools\n"
-      "  -u UUID                        Specify uuid\n"
-      "                                 (abcdef01-2345-6789-1234-567890abcdef)\n"
-      "  -A AUTH                        0=auth,1=deauth",
-    },
-    { "tmem-freeable",
-      &main_tmem_freeable, 0, 0,
-      "Get information about how much freeable memory (MB) is in-use by tmem",
-      "",
-    },
-    { "cpupool-create",
-      &main_cpupoolcreate, 1, 1,
-      "Create a new CPU pool",
-      "[options] [<ConfigFile>] [Variable=value ...]",
-      "-h, --help                   Print this help.\n"
-      "-f FILE, --defconfig=FILE    Use the given configuration file.\n"
-      "-n, --dryrun                 Dry run - prints the resulting configuration.\n"
-      "                              (deprecated in favour of global -N option).\n"
-      "\nSee the xlcpupool.cfg(5) manpage for more information.",
-
-    },
-    { "cpupool-list",
-      &main_cpupoollist, 0, 0,
-      "List CPU pools on host",
-      "[-c|--cpus] [<CPU Pool>]",
-      "-c, --cpus                     Output list of CPUs used by a pool"
-    },
-    { "cpupool-destroy",
-      &main_cpupooldestroy, 0, 1,
-      "Deactivates a CPU pool",
-      "<CPU Pool>",
-    },
-    { "cpupool-rename",
-      &main_cpupoolrename, 0, 1,
-      "Renames a CPU pool",
-      "<CPU Pool> <new name>",
-    },
-    { "cpupool-cpu-add",
-      &main_cpupoolcpuadd, 0, 1,
-      "Adds a CPU to a CPU pool",
-      "<CPU Pool> <CPU nr>|node:<node nr>",
-    },
-    { "cpupool-cpu-remove",
-      &main_cpupoolcpuremove, 0, 1,
-      "Removes a CPU from a CPU pool",
-      "<CPU Pool> <CPU nr>|node:<node nr>",
-    },
-    { "cpupool-migrate",
-      &main_cpupoolmigrate, 0, 1,
-      "Moves a domain into a CPU pool",
-      "<Domain> <CPU Pool>",
-    },
-    { "cpupool-numa-split",
-      &main_cpupoolnumasplit, 0, 1,
-      "Splits up the machine into one CPU pool per NUMA node",
-      "",
-    },
-    { "getenforce",
-      &main_getenforce, 0, 0,
-      "Returns the current enforcing mode of the Flask Xen security module",
-      "",
-    },
-    { "setenforce",
-      &main_setenforce, 0, 1,
-      "Sets the current enforcing mode of the Flask Xen security module",
-      "<1|0|Enforcing|Permissive>",
-    },
-    { "loadpolicy",
-      &main_loadpolicy, 0, 1,
-      "Loads a new policy int the Flask Xen security module",
-      "<policy file>",
-    },
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-    { "remus",
-      &main_remus, 0, 1,
-      "Enable Remus HA for domain",
-      "[options] <Domain> [<host>]",
-      "-i MS                   Checkpoint domain memory every MS milliseconds (def. 200ms).\n"
-      "-u                      Disable memory checkpoint compression.\n"
-      "-s <sshcommand>         Use <sshcommand> instead of ssh.  String will be passed\n"
-      "                        to sh. If empty, run <host> instead of \n"
-      "                        ssh <host> xl migrate-receive -r [-e]\n"
-      "-e                      Do not wait in the background (on <host>) for the death\n"
-      "                        of the domain.\n"
-      "-N <netbufscript>       Use netbufscript to setup network buffering instead of the\n"
-      "                        default script (/etc/xen/scripts/remus-netbuf-setup).\n"
-      "-F                      Enable unsafe configurations [-b|-n|-d flags]. Use this option\n"
-      "                        with caution as failover may not work as intended.\n"
-      "-b                      Replicate memory checkpoints to /dev/null (blackhole).\n"
-      "                        Works only in unsafe mode.\n"
-      "-n                      Disable network output buffering. Works only in unsafe mode.\n"
-      "-d                      Disable disk replication. Works only in unsafe mode.\n"
-      "-c                      Enable COLO HA. It is conflict with -i and -b, and memory\n"
-      "                        checkpoint must be disabled"
-    },
-#endif
-    { "devd",
-      &main_devd, 0, 1,
-      "Daemon that listens for devices and launches backends",
-      "[options]",
-      "-F                      Run in the foreground.\n"
-      "-p, --pidfile [FILE]    Write PID to pidfile when daemonizing.",
-    },
-#ifdef LIBXL_HAVE_PSR_CMT
-    { "psr-hwinfo",
-      &main_psr_hwinfo, 0, 1,
-      "Show hardware information for Platform Shared Resource",
-      "[options]",
-      "-m, --cmt       Show Cache Monitoring Technology (CMT) hardware info\n"
-      "-a, --cat       Show Cache Allocation Technology (CAT) hardware info\n"
-    },
-    { "psr-cmt-attach",
-      &main_psr_cmt_attach, 0, 1,
-      "Attach Cache Monitoring Technology service to a domain",
-      "<Domain>",
-    },
-    { "psr-cmt-detach",
-      &main_psr_cmt_detach, 0, 1,
-      "Detach Cache Monitoring Technology service from a domain",
-      "<Domain>",
-    },
-    { "psr-cmt-show",
-      &main_psr_cmt_show, 0, 1,
-      "Show Cache Monitoring Technology information",
-      "<PSR-CMT-Type> <Domain>",
-      "Available monitor types:\n"
-      "\"cache-occupancy\":         Show L3 cache occupancy(KB)\n"
-      "\"total-mem-bandwidth\":     Show total memory bandwidth(KB/s)\n"
-      "\"local-mem-bandwidth\":     Show local memory bandwidth(KB/s)\n",
-    },
-#endif
-#ifdef LIBXL_HAVE_PSR_CAT
-    { "psr-cat-cbm-set",
-      &main_psr_cat_cbm_set, 0, 1,
-      "Set cache capacity bitmasks(CBM) for a domain",
-      "[options] <Domain> <CBM>",
-      "-s <socket>       Specify the socket to process, otherwise all sockets are processed\n"
-      "-c                Set code CBM if CDP is supported\n"
-      "-d                Set data CBM if CDP is supported\n"
-    },
-    { "psr-cat-show",
-      &main_psr_cat_show, 0, 1,
-      "Show Cache Allocation Technology information",
-      "<Domain>",
-    },
-
-#endif
-    { "usbctrl-attach",
-      &main_usbctrl_attach, 0, 1,
-      "Create a virtual USB controller for a domain",
-      "<Domain> [type=pv] [version=<version>] [ports=<number>]",
-    },
-    { "usbctrl-detach",
-      &main_usbctrl_detach, 0, 1,
-      "Remove the virtual USB controller specified by <DevId> for a domain",
-      "<Domain> <DevId>",
-    },
-    { "usbdev-attach",
-      &main_usbdev_attach, 0, 1,
-      "Attach a USB device to a domain",
-      "<Domain> hostbus=<busnum> hostaddr=<devnum> [controller=<DevId> [port=<port>]]",
-    },
-    { "usbdev-detach",
-      &main_usbdev_detach, 0, 1,
-      "Detach a USB device from a domain",
-      "<Domain> <controller> <port>",
-    },
-    { "usb-list",
-      &main_usblist, 0, 0,
-      "List information about all USB controllers and devices for a domain",
-      "<Domain>",
-    },
-    { "qemu-monitor-command",
-      &main_qemu_monitor_command, 0, 1,
-      "Issue a qemu monitor command to the device model of a domain",
-      "<Domain> <Command>",
-    },
-};
-
-int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);
-
-/* Look up a command in the table, allowing unambiguous truncation */
-struct cmd_spec *cmdtable_lookup(const char *s)
-{
-    struct cmd_spec *cmd = NULL;
-    size_t len;
-    int i, count = 0;
-
-    if (!s)
-        return NULL;
-    len = strlen(s);
-    for (i = 0; i < cmdtable_len; i++) {
-        if (!strncmp(s, cmd_table[i].cmd_name, len)) {
-            cmd = &cmd_table[i];
-            /* Take an exact match, even if it also prefixes another command */
-            if (len == strlen(cmd->cmd_name))
-                return cmd;
-            count++;
-        }
-    }
-    return (count == 1) ? cmd : NULL;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxl/xl_sxp.c b/tools/libxl/xl_sxp.c
deleted file mode 100644 (file)
index a8c127b..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2009      Citrix Ltd.
- * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
- * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
- *
- * 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.
- */
-
-/*
- * Legacy SXP output handling
- */
-
-#include "libxl_osdeps.h"
-
-#include <stdlib.h>
-#include <inttypes.h>
-
-#include "libxl.h"
-#include "libxl_utils.h"
-#include "xl.h"
-
-/* In general you should not add new output to this function since it
- * is intended only for legacy use.
- */
-void printf_info_sexp(int domid, libxl_domain_config *d_config, FILE *fh)
-{
-    int i;
-    libxl_dominfo info;
-
-    libxl_domain_create_info *c_info = &d_config->c_info;
-    libxl_domain_build_info *b_info = &d_config->b_info;
-
-    fprintf(fh, "(domain\n\t(domid %d)\n", domid);
-    fprintf(fh, "\t(create_info)\n");
-    fprintf(fh, "\t(hvm %d)\n", c_info->type == LIBXL_DOMAIN_TYPE_HVM);
-    fprintf(fh, "\t(hap %s)\n", libxl_defbool_to_string(c_info->hap));
-    fprintf(fh, "\t(oos %s)\n", libxl_defbool_to_string(c_info->oos));
-    fprintf(fh, "\t(ssidref %d)\n", c_info->ssidref);
-    fprintf(fh, "\t(name %s)\n", c_info->name);
-
-    /* retrieve the UUID from dominfo, since it is probably generated
-     * during parsing and thus does not match the real one
-     */
-    if (libxl_domain_info(ctx, &info, domid) == 0) {
-        fprintf(fh, "\t(uuid " LIBXL_UUID_FMT ")\n", LIBXL_UUID_BYTES(info.uuid));
-    } else {
-        fprintf(fh, "\t(uuid <unknown>)\n");
-    }
-    if (c_info->pool_name)
-        fprintf(fh, "\t(cpupool %s)\n", c_info->pool_name);
-    if (c_info->xsdata)
-        fprintf(fh, "\t(xsdata contains data)\n");
-    else
-        fprintf(fh, "\t(xsdata (null))\n");
-    if (c_info->platformdata)
-        fprintf(fh, "\t(platformdata contains data)\n");
-    else
-        fprintf(fh, "\t(platformdata (null))\n");
-
-
-    fprintf(fh, "\t(build_info)\n");
-    fprintf(fh, "\t(max_vcpus %d)\n", b_info->max_vcpus);
-    fprintf(fh, "\t(tsc_mode %s)\n", libxl_tsc_mode_to_string(b_info->tsc_mode));
-    fprintf(fh, "\t(max_memkb %"PRId64")\n", b_info->max_memkb);
-    fprintf(fh, "\t(target_memkb %"PRId64")\n", b_info->target_memkb);
-    fprintf(fh, "\t(nomigrate %s)\n",
-           libxl_defbool_to_string(b_info->disable_migrate));
-
-    if (c_info->type == LIBXL_DOMAIN_TYPE_PV && b_info->u.pv.bootloader) {
-        fprintf(fh, "\t(bootloader %s)\n", b_info->u.pv.bootloader);
-        if (b_info->u.pv.bootloader_args) {
-            fprintf(fh, "\t(bootloader_args");
-            for (i=0; b_info->u.pv.bootloader_args[i]; i++)
-                fprintf(fh, " %s", b_info->u.pv.bootloader_args[i]);
-            fprintf(fh, ")\n");
-        }
-    }
-
-    fprintf(fh, "\t(image\n");
-    switch (c_info->type) {
-    case LIBXL_DOMAIN_TYPE_HVM:
-        fprintf(fh, "\t\t(hvm\n");
-        fprintf(fh, "\t\t\t(firmware %s)\n", b_info->u.hvm.firmware);
-        fprintf(fh, "\t\t\t(video_memkb %"PRId64")\n", b_info->video_memkb);
-        fprintf(fh, "\t\t\t(shadow_memkb %"PRId64")\n", b_info->shadow_memkb);
-        fprintf(fh, "\t\t\t(pae %s)\n", libxl_defbool_to_string(b_info->u.hvm.pae));
-        fprintf(fh, "\t\t\t(apic %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.apic));
-        fprintf(fh, "\t\t\t(acpi %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.acpi));
-        fprintf(fh, "\t\t\t(nx %s)\n", libxl_defbool_to_string(b_info->u.hvm.nx));
-        fprintf(fh, "\t\t\t(viridian %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.viridian));
-        fprintf(fh, "\t\t\t(hpet %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.hpet));
-        fprintf(fh, "\t\t\t(vpt_align %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.vpt_align));
-        fprintf(fh, "\t\t\t(timer_mode %s)\n",
-               libxl_timer_mode_to_string(b_info->u.hvm.timer_mode));
-        fprintf(fh, "\t\t\t(nestedhvm %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.nested_hvm));
-        fprintf(fh, "\t\t\t(stdvga %s)\n", b_info->u.hvm.vga.kind ==
-                                      LIBXL_VGA_INTERFACE_TYPE_STD ?
-                                      "True" : "False");
-        fprintf(fh, "\t\t\t(vnc %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.vnc.enable));
-        fprintf(fh, "\t\t\t(vnclisten %s)\n", b_info->u.hvm.vnc.listen);
-        fprintf(fh, "\t\t\t(vncdisplay %d)\n", b_info->u.hvm.vnc.display);
-        fprintf(fh, "\t\t\t(vncunused %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.vnc.findunused));
-        fprintf(fh, "\t\t\t(keymap %s)\n", b_info->u.hvm.keymap);
-        fprintf(fh, "\t\t\t(sdl %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.sdl.enable));
-        fprintf(fh, "\t\t\t(opengl %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.sdl.opengl));
-        fprintf(fh, "\t\t\t(nographic %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.nographic));
-        fprintf(fh, "\t\t\t(spice %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.spice.enable));
-        fprintf(fh, "\t\t\t(spiceport %d)\n", b_info->u.hvm.spice.port);
-        fprintf(fh, "\t\t\t(spicetls_port %d)\n", b_info->u.hvm.spice.tls_port);
-        fprintf(fh, "\t\t\t(spicehost %s)\n", b_info->u.hvm.spice.host);
-        fprintf(fh, "\t\t\t(spicedisable_ticketing %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.spice.disable_ticketing));
-        fprintf(fh, "\t\t\t(spiceagent_mouse %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.spice.agent_mouse));
-
-        fprintf(fh, "\t\t\t(device_model %s)\n", b_info->device_model ? : "default");
-        fprintf(fh, "\t\t\t(gfx_passthru %s)\n",
-               libxl_defbool_to_string(b_info->u.hvm.gfx_passthru));
-        fprintf(fh, "\t\t\t(serial %s)\n", b_info->u.hvm.serial);
-        fprintf(fh, "\t\t\t(boot %s)\n", b_info->u.hvm.boot);
-        fprintf(fh, "\t\t\t(usb %s)\n", libxl_defbool_to_string(b_info->u.hvm.usb));
-        fprintf(fh, "\t\t\t(usbdevice %s)\n", b_info->u.hvm.usbdevice);
-        fprintf(fh, "\t\t)\n");
-        break;
-    case LIBXL_DOMAIN_TYPE_PV:
-        fprintf(fh, "\t\t(linux %d)\n", 0);
-        fprintf(fh, "\t\t\t(kernel %s)\n", b_info->kernel);
-        fprintf(fh, "\t\t\t(cmdline %s)\n", b_info->cmdline);
-        fprintf(fh, "\t\t\t(ramdisk %s)\n", b_info->ramdisk);
-        fprintf(fh, "\t\t\t(e820_host %s)\n",
-               libxl_defbool_to_string(b_info->u.pv.e820_host));
-        fprintf(fh, "\t\t)\n");
-        break;
-    default:
-        fprintf(stderr, "Unknown domain type %d\n", c_info->type);
-        exit(1);
-    }
-    fprintf(fh, "\t)\n");
-
-    for (i = 0; i < d_config->num_disks; i++) {
-        fprintf(fh, "\t(device\n");
-        fprintf(fh, "\t\t(tap\n");
-        fprintf(fh, "\t\t\t(backend_domid %d)\n", d_config->disks[i].backend_domid);
-        fprintf(fh, "\t\t\t(frontend_domid %d)\n", domid);
-        fprintf(fh, "\t\t\t(physpath %s)\n", d_config->disks[i].pdev_path);
-        fprintf(fh, "\t\t\t(phystype %d)\n", d_config->disks[i].backend);
-        fprintf(fh, "\t\t\t(virtpath %s)\n", d_config->disks[i].vdev);
-        fprintf(fh, "\t\t\t(unpluggable %d)\n", d_config->disks[i].removable);
-        fprintf(fh, "\t\t\t(readwrite %d)\n", d_config->disks[i].readwrite);
-        fprintf(fh, "\t\t\t(is_cdrom %d)\n", d_config->disks[i].is_cdrom);
-        fprintf(fh, "\t\t)\n");
-        fprintf(fh, "\t)\n");
-    }
-
-    for (i = 0; i < d_config->num_nics; i++) {
-        fprintf(fh, "\t(device\n");
-        fprintf(fh, "\t\t(vif\n");
-        if (d_config->nics[i].ifname)
-            fprintf(fh, "\t\t\t(vifname %s)\n", d_config->nics[i].ifname);
-        fprintf(fh, "\t\t\t(backend_domid %d)\n", d_config->nics[i].backend_domid);
-        fprintf(fh, "\t\t\t(frontend_domid %d)\n", domid);
-        fprintf(fh, "\t\t\t(devid %d)\n", d_config->nics[i].devid);
-        fprintf(fh, "\t\t\t(mtu %d)\n", d_config->nics[i].mtu);
-        fprintf(fh, "\t\t\t(model %s)\n", d_config->nics[i].model);
-        fprintf(fh, "\t\t\t(mac %02x%02x%02x%02x%02x%02x)\n",
-               d_config->nics[i].mac[0], d_config->nics[i].mac[1],
-               d_config->nics[i].mac[2], d_config->nics[i].mac[3],
-               d_config->nics[i].mac[4], d_config->nics[i].mac[5]);
-        fprintf(fh, "\t\t)\n");
-        fprintf(fh, "\t)\n");
-    }
-
-    for (i = 0; i < d_config->num_pcidevs; i++) {
-        fprintf(fh, "\t(device\n");
-        fprintf(fh, "\t\t(pci\n");
-        fprintf(fh, "\t\t\t(pci dev %04x:%02x:%02x.%01x@%02x)\n",
-               d_config->pcidevs[i].domain, d_config->pcidevs[i].bus,
-               d_config->pcidevs[i].dev, d_config->pcidevs[i].func,
-               d_config->pcidevs[i].vdevfn);
-        fprintf(fh, "\t\t\t(opts msitranslate %d power_mgmt %d)\n",
-               d_config->pcidevs[i].msitranslate,
-               d_config->pcidevs[i].power_mgmt);
-        fprintf(fh, "\t\t)\n");
-        fprintf(fh, "\t)\n");
-    }
-
-    for (i = 0; i < d_config->num_vfbs; i++) {
-        fprintf(fh, "\t(device\n");
-        fprintf(fh, "\t\t(vfb\n");
-        fprintf(fh, "\t\t\t(backend_domid %d)\n", d_config->vfbs[i].backend_domid);
-        fprintf(fh, "\t\t\t(frontend_domid %d)\n", domid);
-        fprintf(fh, "\t\t\t(devid %d)\n", d_config->vfbs[i].devid);
-        fprintf(fh, "\t\t\t(vnc %s)\n",
-               libxl_defbool_to_string(d_config->vfbs[i].vnc.enable));
-        fprintf(fh, "\t\t\t(vnclisten %s)\n", d_config->vfbs[i].vnc.listen);
-        fprintf(fh, "\t\t\t(vncdisplay %d)\n", d_config->vfbs[i].vnc.display);
-        fprintf(fh, "\t\t\t(vncunused %s)\n",
-               libxl_defbool_to_string(d_config->vfbs[i].vnc.findunused));
-        fprintf(fh, "\t\t\t(keymap %s)\n", d_config->vfbs[i].keymap);
-        fprintf(fh, "\t\t\t(sdl %s)\n",
-               libxl_defbool_to_string(d_config->vfbs[i].sdl.enable));
-        fprintf(fh, "\t\t\t(opengl %s)\n",
-               libxl_defbool_to_string(d_config->vfbs[i].sdl.opengl));
-        fprintf(fh, "\t\t\t(display %s)\n", d_config->vfbs[i].sdl.display);
-        fprintf(fh, "\t\t\t(xauthority %s)\n", d_config->vfbs[i].sdl.xauthority);
-        fprintf(fh, "\t\t)\n");
-        fprintf(fh, "\t)\n");
-    }
-    fprintf(fh, ")\n");
-}
-
-
-/*
- * Local variables:
- * mode: C
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/xl/Makefile b/tools/xl/Makefile
new file mode 100644 (file)
index 0000000..d4b862c
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# tools/xl/Makefile
+#
+
+XEN_ROOT = $(CURDIR)/../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+CFLAGS += -Werror -Wno-format-zero-length -Wmissing-declarations \
+       -Wno-declaration-after-statement -Wformat-nonliteral
+CFLAGS += -I. -fPIC
+
+CFLAGS += $(PTHREAD_CFLAGS)
+LDFLAGS += $(PTHREAD_LDFLAGS)
+
+CFLAGS_XL += $(CFLAGS_libxenlight)
+CFLAGS_XL += -Wshadow
+
+XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o
+$(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
+$(XL_OBJS): CFLAGS += $(CFLAGS_XL)
+$(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
+
+# libxenlight should be built before building xl
+.PHONY: libxl
+libxl:
+       $(MAKE) -C $(XEN_ROOT)/tools/libxl
+$(XL_OBJS): libxl
+
+.PHONY: all
+all: xl
+
+xl: $(XL_OBJS)
+       $(CC) $(LDFLAGS) -o $@ $(XL_OBJS) $(LDLIBS_libxlutil) $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) -lyajl $(APPEND_LDFLAGS)
+
+.PHONY: install
+install: all
+       $(INSTALL_DIR) $(DESTDIR)$(sbindir)
+       $(INSTALL_DIR) $(DESTDIR)$(BASH_COMPLETION_DIR)
+       $(INSTALL_PROG) xl $(DESTDIR)$(sbindir)
+       $(INSTALL_DATA) bash-completion $(DESTDIR)$(BASH_COMPLETION_DIR)/xl.sh
+
+.PHONY: clean
+clean:
+       $(RM) -f *.o xl $(DEPS)
+
+distclean: clean
+
+
+-include $(DEPS)
diff --git a/tools/xl/bash-completion b/tools/xl/bash-completion
new file mode 100644 (file)
index 0000000..b7cd6b3
--- /dev/null
@@ -0,0 +1,20 @@
+# Copy this file to /etc/bash_completion.d/xl.sh
+
+_xl()
+{
+       local IFS=$'\n,'
+
+       local cur opts xl
+       COMPREPLY=()
+       cur="${COMP_WORDS[COMP_CWORD]}"
+       xl=xl
+
+       if [[ $COMP_CWORD == 1 ]] ; then
+               opts=`${xl} help 2>/dev/null | sed '1,4d' | awk '/^ [^ ]/ {print $1}' | sed 's/$/ ,/g'` && COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+               return 0
+       fi
+
+       return 0
+}
+
+complete -F _xl -o nospace -o default xl
diff --git a/tools/xl/xl.c b/tools/xl/xl.c
new file mode 100644 (file)
index 0000000..a272258
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+ * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <regex.h>
+
+#include "libxl.h"
+#include "libxl_utils.h"
+#include "libxlutil.h"
+#include "xl.h"
+
+xentoollog_logger_stdiostream *logger;
+int dryrun_only;
+int force_execution;
+int autoballoon = -1;
+char *blkdev_start;
+int run_hotplug_scripts = 1;
+char *lockfile;
+char *default_vifscript = NULL;
+char *default_bridge = NULL;
+char *default_gatewaydev = NULL;
+char *default_vifbackend = NULL;
+char *default_remus_netbufscript = NULL;
+char *default_colo_proxy_script = NULL;
+enum output_format default_output_format = OUTPUT_FORMAT_JSON;
+int claim_mode = 1;
+bool progress_use_cr = 0;
+
+xentoollog_level minmsglevel = minmsglevel_default;
+
+/* Get autoballoon option based on presence of dom0_mem Xen command
+   line option. */
+static int auto_autoballoon(void)
+{
+    const libxl_version_info *info;
+    regex_t regex;
+    int ret;
+
+    info = libxl_get_version_info(ctx);
+    if (!info)
+        return 1; /* default to on */
+
+    ret = regcomp(&regex,
+                  "(^| )dom0_mem=((|min:|max:)[0-9]+[bBkKmMgG]?,?)+($| )",
+                  REG_NOSUB | REG_EXTENDED);
+    if (ret)
+        return 1;
+
+    ret = regexec(&regex, info->commandline, 0, NULL, 0);
+    regfree(&regex);
+    return ret == REG_NOMATCH;
+}
+
+static void parse_global_config(const char *configfile,
+                              const char *configfile_data,
+                              int configfile_len)
+{
+    long l;
+    XLU_Config *config;
+    int e;
+    const char *buf;
+
+    config = xlu_cfg_init(stderr, configfile);
+    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);
+    }
+
+    if (!xlu_cfg_get_string(config, "autoballoon", &buf, 0)) {
+        if (!strcmp(buf, "on") || !strcmp(buf, "1"))
+            autoballoon = 1;
+        else if (!strcmp(buf, "off") || !strcmp(buf, "0"))
+            autoballoon = 0;
+        else if (!strcmp(buf, "auto"))
+            autoballoon = -1;
+        else
+            fprintf(stderr, "invalid autoballoon option");
+    }
+    if (autoballoon == -1)
+        autoballoon = auto_autoballoon();
+
+    if (!xlu_cfg_get_long (config, "run_hotplug_scripts", &l, 0))
+        run_hotplug_scripts = l;
+
+    if (!xlu_cfg_get_string (config, "lockfile", &buf, 0))
+        lockfile = strdup(buf);
+    else {
+        lockfile = strdup(XL_LOCK_FILE);
+    }
+
+    if (!lockfile) {
+        fprintf(stderr, "failed to allocate lockfile\n");
+        exit(1);
+    }
+
+    /*
+     * For global options that are related to a specific type of device
+     * we use the following nomenclature:
+     *
+     * <device type>.default.<option name>
+     *
+     * This allows us to keep the default options classified for the
+     * different device kinds.
+     */
+
+    if (!xlu_cfg_get_string (config, "vifscript", &buf, 0)) {
+        fprintf(stderr, "the global config option vifscript is deprecated, "
+                        "please switch to vif.default.script\n");
+        free(default_vifscript);
+        default_vifscript = strdup(buf);
+    }
+
+    if (!xlu_cfg_get_string (config, "vif.default.script", &buf, 0)) {
+        free(default_vifscript);
+        default_vifscript = strdup(buf);
+    }
+
+    if (!xlu_cfg_get_string (config, "defaultbridge", &buf, 0)) {
+        fprintf(stderr, "the global config option defaultbridge is deprecated, "
+                        "please switch to vif.default.bridge\n");
+        free(default_bridge);
+        default_bridge = strdup(buf);
+    }
+
+    if (!xlu_cfg_get_string (config, "vif.default.bridge", &buf, 0)) {
+        free(default_bridge);
+        default_bridge = strdup(buf);
+    }
+
+    if (!xlu_cfg_get_string (config, "vif.default.gatewaydev", &buf, 0))
+        default_gatewaydev = strdup(buf);
+
+    if (!xlu_cfg_get_string (config, "vif.default.backend", &buf, 0))
+        default_vifbackend = strdup(buf);
+
+    if (!xlu_cfg_get_string (config, "output_format", &buf, 0)) {
+        if (!strcmp(buf, "json"))
+            default_output_format = OUTPUT_FORMAT_JSON;
+        else if (!strcmp(buf, "sxp"))
+            default_output_format = OUTPUT_FORMAT_SXP;
+        else {
+            fprintf(stderr, "invalid default output format \"%s\"\n", buf);
+        }
+    }
+    if (!xlu_cfg_get_string (config, "blkdev_start", &buf, 0))
+        blkdev_start = strdup(buf);
+
+    if (!xlu_cfg_get_long (config, "claim_mode", &l, 0))
+        claim_mode = l;
+
+    xlu_cfg_replace_string (config, "remus.default.netbufscript",
+        &default_remus_netbufscript, 0);
+    xlu_cfg_replace_string (config, "colo.default.proxyscript",
+        &default_colo_proxy_script, 0);
+
+    xlu_cfg_destroy(config);
+}
+
+void postfork(void)
+{
+    libxl_postfork_child_noexec(ctx); /* in case we don't exit/exec */
+    ctx = 0;
+
+    xl_ctx_alloc();
+}
+
+pid_t xl_fork(xlchildnum child, const char *description) {
+    xlchild *ch = &children[child];
+    int i;
+
+    assert(!ch->pid);
+    ch->reaped = 0;
+    ch->description = description;
+
+    ch->pid = fork();
+    if (ch->pid == -1) {
+        perror("fork failed");
+        exit(-1);
+    }
+
+    if (!ch->pid) {
+        /* We are in the child now.  So all these children are not ours. */
+        for (i=0; i<child_max; i++)
+            children[i].pid = 0;
+    }
+
+    return ch->pid;
+}
+
+pid_t xl_waitpid(xlchildnum child, int *status, int flags)
+{
+    xlchild *ch = &children[child];
+    pid_t got = ch->pid;
+    assert(got);
+    if (ch->reaped) {
+        *status = ch->status;
+        ch->pid = 0;
+        return got;
+    }
+    for (;;) {
+        got = waitpid(ch->pid, status, flags);
+        if (got < 0 && errno == EINTR) continue;
+        if (got > 0) {
+            assert(got == ch->pid);
+            ch->pid = 0;
+        }
+        return got;
+    }
+}
+
+int xl_child_pid(xlchildnum child)
+{
+    xlchild *ch = &children[child];
+    return ch->pid;
+}
+
+void xl_report_child_exitstatus(xentoollog_level level,
+                                xlchildnum child, pid_t pid, int status)
+{
+    libxl_report_child_exitstatus(ctx, level, children[child].description,
+                                  pid, status);
+}
+
+static int xl_reaped_callback(pid_t got, int status, void *user)
+{
+    int i;
+    assert(got);
+    for (i=0; i<child_max; i++) {
+        xlchild *ch = &children[i];
+        if (ch->pid == got) {
+            ch->reaped = 1;
+            ch->status = status;
+            return 0;
+        }
+    }
+    return ERROR_UNKNOWN_CHILD;
+}
+
+static const libxl_childproc_hooks childproc_hooks = {
+    .chldowner = libxl_sigchld_owner_libxl,
+    .reaped_callback = xl_reaped_callback,
+};
+
+void xl_ctx_alloc(void) {
+    if (libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, (xentoollog_logger*)logger)) {
+        fprintf(stderr, "cannot init xl context\n");
+        exit(1);
+    }
+
+    libxl_childproc_setmode(ctx, &childproc_hooks, 0);
+}
+
+static void xl_ctx_free(void)
+{
+    if (ctx) {
+        libxl_ctx_free(ctx);
+        ctx = NULL;
+    }
+    if (logger) {
+        xtl_logger_destroy((xentoollog_logger*)logger);
+        logger = NULL;
+    }
+    if (lockfile) {
+        free(lockfile);
+        lockfile = NULL;
+    }
+}
+
+int main(int argc, char **argv)
+{
+    int opt = 0;
+    char *cmd = 0;
+    struct cmd_spec *cspec;
+    int ret;
+    void *config_data = 0;
+    int config_len = 0;
+
+    while ((opt = getopt(argc, argv, "+vftN")) >= 0) {
+        switch (opt) {
+        case 'v':
+            if (minmsglevel > 0) minmsglevel--;
+            break;
+        case 'N':
+            dryrun_only = 1;
+            break;
+        case 'f':
+            force_execution = 1;
+            break;
+        case 't':
+            progress_use_cr = 1;
+            break;
+        default:
+            fprintf(stderr, "unknown global option\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    cmd = argv[optind];
+
+    if (!cmd) {
+        help(NULL);
+        exit(EXIT_FAILURE);
+    }
+    opterr = 0;
+
+    logger = xtl_createlogger_stdiostream(stderr, minmsglevel,
+        (progress_use_cr ? XTL_STDIOSTREAM_PROGRESS_USE_CR : 0));
+    if (!logger) exit(EXIT_FAILURE);
+
+    atexit(xl_ctx_free);
+
+    xl_ctx_alloc();
+
+    ret = libxl_read_file_contents(ctx, XL_GLOBAL_CONFIG,
+            &config_data, &config_len);
+    if (ret)
+        fprintf(stderr, "Failed to read config file: %s: %s\n",
+                XL_GLOBAL_CONFIG, strerror(errno));
+    parse_global_config(XL_GLOBAL_CONFIG, config_data, config_len);
+    free(config_data);
+
+    /* Reset options for per-command use of getopt. */
+    argv += optind;
+    argc -= optind;
+    optind = 1;
+
+    cspec = cmdtable_lookup(cmd);
+    if (cspec) {
+        if (dryrun_only && !cspec->can_dryrun) {
+            fprintf(stderr, "command does not implement -N (dryrun) option\n");
+            ret = EXIT_FAILURE;
+            goto xit;
+        }
+        ret = cspec->cmd_impl(argc, argv);
+    } else if (!strcmp(cmd, "help")) {
+        help(argv[1]);
+        ret = EXIT_SUCCESS;
+    } else {
+        fprintf(stderr, "command not implemented\n");
+        ret = EXIT_FAILURE;
+    }
+
+ xit:
+    return ret;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl.h b/tools/xl/xl.h
new file mode 100644 (file)
index 0000000..0a8c813
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Author Yang Hongyang <yanghy@cn.fujitsu.com>
+ *
+ * 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.
+ */
+
+#ifndef XL_H
+#define XL_H
+
+#include <assert.h>
+
+#include "_paths.h"
+#include "xentoollog.h"
+
+struct cmd_spec {
+    char *cmd_name;
+    int (*cmd_impl)(int argc, char **argv);
+    int can_dryrun;
+    int modifies;
+    char *cmd_desc;
+    char *cmd_usage;
+    char *cmd_option;
+};
+
+/*
+ * The xl process should always return either EXIT_SUCCESS or
+ * EXIT_FAILURE. main_* functions, implementing the various xl
+ * commands, can be treated as main() as if they are returning
+ * a process exit status and not a function return value.
+ */
+
+int main_vcpulist(int argc, char **argv);
+int main_info(int argc, char **argv);
+int main_sharing(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_vncviewer(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_pciassignable_add(int argc, char **argv);
+int main_pciassignable_remove(int argc, char **argv);
+int main_pciassignable_list(int argc, char **argv);
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+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);
+#endif
+int main_dump_core(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_shutdown(int argc, char **argv);
+int main_reboot(int argc, char **argv);
+int main_list(int argc, char **argv);
+int main_vm_list(int argc, char **argv);
+int main_create(int argc, char **argv);
+int main_config_update(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_memmax(int argc, char **argv);
+int main_memset(int argc, char **argv);
+int main_sched_credit(int argc, char **argv);
+int main_sched_credit2(int argc, char **argv);
+int main_sched_rtds(int argc, char **argv);
+int main_domid(int argc, char **argv);
+int main_domname(int argc, char **argv);
+int main_rename(int argc, char **argv);
+int main_trigger(int argc, char **argv);
+int main_sysrq(int argc, char **argv);
+int main_debug_keys(int argc, char **argv);
+int main_dmesg(int argc, char **argv);
+int main_top(int argc, char **argv);
+int main_networkattach(int argc, char **argv);
+int main_networklist(int argc, char **argv);
+int main_networkdetach(int argc, char **argv);
+int main_channellist(int argc, char **argv);
+int main_blockattach(int argc, char **argv);
+int main_blocklist(int argc, char **argv);
+int main_blockdetach(int argc, char **argv);
+int main_vtpmattach(int argc, char **argv);
+int main_vtpmlist(int argc, char **argv);
+int main_vtpmdetach(int argc, char **argv);
+int main_usbctrl_attach(int argc, char **argv);
+int main_usbctrl_detach(int argc, char **argv);
+int main_usbdev_attach(int argc, char **argv);
+int main_usbdev_detach(int argc, char **argv);
+int main_usblist(int argc, char **argv);
+int main_uptime(int argc, char **argv);
+int main_claims(int argc, char **argv);
+int main_tmem_list(int argc, char **argv);
+int main_tmem_freeze(int argc, char **argv);
+int main_tmem_thaw(int argc, char **argv);
+int main_tmem_set(int argc, char **argv);
+int main_tmem_shared_auth(int argc, char **argv);
+int main_tmem_freeable(int argc, char **argv);
+int main_network2attach(int argc, char **argv);
+int main_network2list(int argc, char **argv);
+int main_network2detach(int argc, char **argv);
+int main_cpupoolcreate(int argc, char **argv);
+int main_cpupoollist(int argc, char **argv);
+int main_cpupooldestroy(int argc, char **argv);
+int main_cpupoolrename(int argc, char **argv);
+int main_cpupoolcpuadd(int argc, char **argv);
+int main_cpupoolcpuremove(int argc, char **argv);
+int main_cpupoolmigrate(int argc, char **argv);
+int main_cpupoolnumasplit(int argc, char **argv);
+int main_getenforce(int argc, char **argv);
+int main_setenforce(int argc, char **argv);
+int main_loadpolicy(int argc, char **argv);
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+int main_remus(int argc, char **argv);
+#endif
+int main_devd(int argc, char **argv);
+#ifdef LIBXL_HAVE_PSR_CMT
+int main_psr_hwinfo(int argc, char **argv);
+int main_psr_cmt_attach(int argc, char **argv);
+int main_psr_cmt_detach(int argc, char **argv);
+int main_psr_cmt_show(int argc, char **argv);
+#endif
+#ifdef LIBXL_HAVE_PSR_CAT
+int main_psr_cat_cbm_set(int argc, char **argv);
+int main_psr_cat_show(int argc, char **argv);
+#endif
+int main_qemu_monitor_command(int argc, char **argv);
+
+void help(const char *command);
+
+extern struct cmd_spec cmd_table[];
+extern int cmdtable_len;
+/* Look up a command in the table, allowing unambiguous truncation */
+struct cmd_spec *cmdtable_lookup(const char *s);
+
+extern libxl_ctx *ctx;
+extern xentoollog_logger_stdiostream *logger;
+
+void xl_ctx_alloc(void);
+
+/* child processes */
+
+typedef struct {
+    /* every struct like this must be in XLCHILD_LIST */
+    pid_t pid; /* 0: not in use */
+    int reaped; /* valid iff pid!=0 */
+    int status; /* valid iff reaped */
+    const char *description; /* valid iff pid!=0 */
+} xlchild;
+
+typedef enum {
+    child_console, child_waitdaemon, child_migration, child_vncviewer,
+    child_max
+} xlchildnum;
+
+extern xlchild children[child_max];
+
+pid_t xl_fork(xlchildnum, const char *description);
+    /* like fork, but prints and dies if it fails */
+void postfork(void); /* needed only if we aren't going to exec right away */
+
+/* Handles EINTR.  Clears out the xlchild so it can be reused. */
+pid_t xl_waitpid(xlchildnum, int *status, int flags);
+
+int xl_child_pid(xlchildnum); /* returns 0 if child struct is not in use */
+
+void xl_report_child_exitstatus(xentoollog_level level,
+                                xlchildnum child, pid_t pid, int status);
+    /* like libxl_report_child_exitstatus, but uses children[].description */
+
+int child_report(xlchildnum child);
+    /* waits and expects child to exit status 0.
+     * otherwise, logs and returns ERROR_FAIL */
+
+/* global options */
+extern int autoballoon;
+extern int run_hotplug_scripts;
+extern int dryrun_only;
+extern int claim_mode;
+extern bool progress_use_cr;
+extern xentoollog_level minmsglevel;
+#define minmsglevel_default XTL_PROGRESS
+extern char *lockfile;
+extern char *default_vifscript;
+extern char *default_bridge;
+extern char *default_gatewaydev;
+extern char *default_vifbackend;
+extern char *default_remus_netbufscript;
+extern char *default_colo_proxy_script;
+extern char *blkdev_start;
+
+enum output_format {
+    OUTPUT_FORMAT_JSON,
+    OUTPUT_FORMAT_SXP,
+};
+extern enum output_format default_output_format;
+
+typedef enum {
+    DOMAIN_RESTART_NONE = 0,     /* No domain restart */
+    DOMAIN_RESTART_NORMAL,       /* Domain should be restarted */
+    DOMAIN_RESTART_RENAME,       /* Domain should be renamed and restarted */
+    DOMAIN_RESTART_SOFT_RESET,   /* Soft reset should be performed */
+} domain_restart_type;
+
+extern void printf_info_sexp(int domid, libxl_domain_config *d_config, FILE *fh);
+
+#define XL_GLOBAL_CONFIG XEN_CONFIG_DIR "/xl.conf"
+#define XL_LOCK_FILE XEN_LOCK_DIR "/xl"
+
+#endif /* XL_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
new file mode 100644 (file)
index 0000000..0add5dc
--- /dev/null
@@ -0,0 +1,9642 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+ * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/utsname.h> /* for utsname in xl info */
+#include <xentoollog.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <xen/hvm/e820.h>
+
+#include "libxl.h"
+#include "libxl_utils.h"
+#include "libxl_json.h"
+#include "libxlutil.h"
+#include "xl.h"
+
+/* For calls which return an errno on failure */
+#define CHK_ERRNOVAL( call ) ({                                         \
+        int chk_errnoval = (call);                                      \
+        if (chk_errnoval < 0)                                           \
+            abort();                                                    \
+        else if (chk_errnoval > 0) {                                    \
+            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
+                    __FILE__,__LINE__, strerror(chk_errnoval), #call);  \
+            exit(EXIT_FAILURE);                                         \
+        }                                                               \
+    })
+
+/* For calls which return -1 and set errno on failure */
+#define CHK_SYSCALL( call ) ({                                          \
+        if ((call) == -1) {                                             \
+            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
+                    __FILE__,__LINE__, strerror(errno), #call);         \
+            exit(EXIT_FAILURE);                                         \
+        }                                                               \
+    })
+
+#define MUST( call ) ({                                                 \
+        int must_rc = (call);                                           \
+        if (must_rc < 0) {                                                  \
+            fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
+                    __FILE__,__LINE__, must_rc, #call);                 \
+            exit(EXIT_FAILURE);                                         \
+        }                                                               \
+    })
+
+#define STR_HAS_PREFIX( a, b )  \
+    ( strncmp(a, b, strlen(b)) == 0 )
+#define STR_SKIP_PREFIX( a, b ) \
+    ( STR_HAS_PREFIX(a, b) ? ((a) += strlen(b), 1) : 0 )
+
+
+int logfile = 2;
+
+/* every libxl action in xl uses this same libxl context */
+libxl_ctx *ctx;
+
+xlchild children[child_max];
+
+#define INVALID_DOMID ~0
+static const char *common_domname;
+static int fd_lock = -1;
+
+static const char savefileheader_magic[32]=
+    "Xen saved domain, xl format\n \0 \r";
+
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+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";
+#endif
+
+  /* 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
+   */
+
+#define XL_MANDATORY_FLAG_JSON (1U << 0) /* config data is in JSON format */
+#define XL_MANDATORY_FLAG_STREAMv2 (1U << 1) /* stream is v2 */
+#define XL_MANDATORY_FLAG_ALL  (XL_MANDATORY_FLAG_JSON |        \
+                                XL_MANDATORY_FLAG_STREAMv2)
+
+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 */
+};
+
+
+static const char *action_on_shutdown_names[] = {
+    [LIBXL_ACTION_ON_SHUTDOWN_DESTROY] = "destroy",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_RESTART] = "restart",
+    [LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME] = "rename-restart",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_PRESERVE] = "preserve",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY] = "coredump-destroy",
+    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART] = "coredump-restart",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET] = "soft-reset",
+};
+
+/* 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)
+
+struct domain_create {
+    int debug;
+    int daemonize;
+    int monitor; /* handle guest reboots etc */
+    int paused;
+    int dryrun;
+    int quiet;
+    int vnc;
+    int vncautopass;
+    int console_autoconnect;
+    int checkpointed_stream;
+    const char *config_file;
+    char *extra_config; /* extra config string */
+    const char *restore_file;
+    char *colo_proxy_script;
+    int migrate_fd; /* -1 means none */
+    int send_back_fd; /* -1 means none */
+    char **migration_domname_r; /* from malloc */
+};
+
+
+static uint32_t find_domain(const char *p) __attribute__((warn_unused_result));
+static uint32_t find_domain(const char *p)
+{
+    uint32_t domid;
+    int rc;
+
+    rc = libxl_domain_qualifier_to_domid(ctx, p, &domid);
+    if (rc) {
+        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
+        exit(EXIT_FAILURE);
+    }
+    common_domname = libxl_domid_to_name(ctx, domid);
+    return domid;
+}
+
+int child_report(xlchildnum child)
+{
+    int status;
+    pid_t got = xl_waitpid(child, &status, 0);
+    if (got < 0) {
+        fprintf(stderr, "xl: warning, failed to waitpid for %s: %s\n",
+                children[child].description, strerror(errno));
+        return ERROR_FAIL;
+    } else if (status) {
+        xl_report_child_exitstatus(XTL_ERROR, child, got, status);
+        return ERROR_FAIL;
+    } else {
+        return 0;
+    }
+}
+
+static void console_child_report(xlchildnum child)
+{
+    if (xl_child_pid(child))
+        child_report(child);
+}
+
+static int vncviewer(uint32_t domid, int autopass)
+{
+    libxl_vncviewer_exec(ctx, domid, autopass);
+    fprintf(stderr, "Unable to execute vncviewer\n");
+    return 1;
+}
+
+static void autoconnect_vncviewer(uint32_t domid, int autopass)
+{
+   console_child_report(child_vncviewer);
+
+    pid_t pid = xl_fork(child_vncviewer, "vncviewer child");
+    if (pid)
+        return;
+
+    postfork();
+
+    sleep(1);
+    vncviewer(domid, autopass);
+    _exit(EXIT_FAILURE);
+}
+
+static int acquire_lock(void)
+{
+    int rc;
+    struct flock fl;
+
+    /* lock already acquired */
+    if (fd_lock >= 0)
+        return ERROR_INVAL;
+
+    fl.l_type = F_WRLCK;
+    fl.l_whence = SEEK_SET;
+    fl.l_start = 0;
+    fl.l_len = 0;
+    fd_lock = open(lockfile, O_WRONLY|O_CREAT, S_IWUSR);
+    if (fd_lock < 0) {
+        fprintf(stderr, "cannot open the lockfile %s errno=%d\n", lockfile, errno);
+        return ERROR_FAIL;
+    }
+    if (fcntl(fd_lock, F_SETFD, FD_CLOEXEC) < 0) {
+        close(fd_lock);
+        fprintf(stderr, "cannot set cloexec to lockfile %s errno=%d\n", lockfile, errno);
+        return ERROR_FAIL;
+    }
+get_lock:
+    rc = fcntl(fd_lock, F_SETLKW, &fl);
+    if (rc < 0 && errno == EINTR)
+        goto get_lock;
+    if (rc < 0) {
+        fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
+        rc = ERROR_FAIL;
+    } else
+        rc = 0;
+    return rc;
+}
+
+static int release_lock(void)
+{
+    int rc;
+    struct flock fl;
+
+    /* lock not acquired */
+    if (fd_lock < 0)
+        return ERROR_INVAL;
+
+release_lock:
+    fl.l_type = F_UNLCK;
+    fl.l_whence = SEEK_SET;
+    fl.l_start = 0;
+    fl.l_len = 0;
+
+    rc = fcntl(fd_lock, F_SETLKW, &fl);
+    if (rc < 0 && errno == EINTR)
+        goto release_lock;
+    if (rc < 0) {
+        fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
+        rc = ERROR_FAIL;
+    } else
+        rc = 0;
+    close(fd_lock);
+    fd_lock = -1;
+
+    return 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 *xcalloc(size_t n, size_t sz) __attribute__((unused));
+static void *xcalloc(size_t n, size_t sz) {
+    void *r = calloc(n, sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to calloc %zu bytes.\n", sz*n);
+        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 char *xstrdup(const char *x)
+{
+    char *r;
+    r = strdup(x);
+    if (!r) {
+        fprintf(stderr, "xl: Unable to strdup a string of length %zu.\n",
+                strlen(x));
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+#define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
+    ({                                                                  \
+        typeof((count)) array_extend_old_count = (count);               \
+        (count)++;                                                      \
+        (array) = xrealloc((array), sizeof(*array) * (count));          \
+        (initfn)(&(array)[array_extend_old_count]);                     \
+        more;                                                           \
+        &(array)[array_extend_old_count];                               \
+    })
+
+#define ARRAY_EXTEND_INIT(array,count,initfn)                           \
+    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), ({                \
+        (array)[array_extend_old_count].devid = array_extend_old_count; \
+        }))
+
+#define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
+    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
+
+#define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
+
+static void dolog(const char *file, int line, const char *func, char *fmt, ...)
+     __attribute__((format(printf,4,5)));
+
+static void dolog(const char *file, int line, const char *func, char *fmt, ...)
+{
+    va_list ap;
+    char *s = NULL;
+    int rc;
+
+    va_start(ap, fmt);
+    rc = vasprintf(&s, fmt, ap);
+    va_end(ap);
+    if (rc >= 0)
+        /* we ignore write errors since we have no way to report them;
+         * the alternative would be to abort the whole program */
+        libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
+    free(s);
+}
+
+static void xvasprintf(char **strp, const char *fmt, va_list ap)
+    __attribute__((format(printf,2,0)));
+static void xvasprintf(char **strp, const char *fmt, va_list ap)
+{
+    int r = vasprintf(strp, fmt, ap);
+    if (r == -1) {
+        perror("asprintf failed");
+        exit(EXIT_FAILURE);
+    }
+}
+
+static void xasprintf(char **strp, const char *fmt, ...)
+    __attribute__((format(printf,2,3)));
+static void xasprintf(char **strp, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    xvasprintf(strp, fmt, ap);
+    va_end(ap);
+}
+
+static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
+                                            libxl_domain_config *d_config)
+{
+    yajl_gen_status s;
+
+    s = yajl_gen_map_open(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_string(hand, (const unsigned char *)"domid",
+                        sizeof("domid")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    if (domid != -1)
+        s = yajl_gen_integer(hand, domid);
+    else
+        s = yajl_gen_null(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_string(hand, (const unsigned char *)"config",
+                        sizeof("config")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    s = libxl_domain_config_gen_json(hand, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_map_close(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+out:
+    return s;
+}
+
+static void flush_stream(FILE *fh)
+{
+    const char *fh_name =
+        fh == stdout ? "stdout" :
+        fh == stderr ? "stderr" :
+        (abort(), (const char*)0);
+
+    if (ferror(fh) || fflush(fh)) {
+        perror(fh_name);
+        exit(EXIT_FAILURE);
+    }
+}
+
+static void printf_info(enum output_format output_format,
+                        int domid,
+                        libxl_domain_config *d_config, FILE *fh)
+{
+    if (output_format == OUTPUT_FORMAT_SXP)
+        return printf_info_sexp(domid, d_config, fh);
+
+    const char *buf;
+    libxl_yajl_length len = 0;
+    yajl_gen_status s;
+    yajl_gen hand;
+
+    hand = libxl_yajl_gen_alloc(NULL);
+    if (!hand) {
+        fprintf(stderr, "unable to allocate JSON generator\n");
+        return;
+    }
+
+    s = printf_info_one_json(hand, domid, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    fputs(buf, fh);
+
+out:
+    yajl_gen_free(hand);
+
+    if (s != yajl_gen_status_ok)
+        fprintf(stderr,
+                "unable to format domain config as JSON (YAJL:%d)\n", s);
+
+    flush_stream(fh);
+}
+
+static int do_daemonize(char *name, const char *pidfile)
+{
+    char *fullname;
+    pid_t child1;
+    int nullfd, ret = 0;
+
+    child1 = xl_fork(child_waitdaemon, "domain monitoring daemonizing child");
+    if (child1) {
+        ret = child_report(child_waitdaemon);
+        if (ret) goto out;
+        ret = 1;
+        goto out;
+    }
+
+    postfork();
+
+    ret = libxl_create_logfile(ctx, name, &fullname);
+    if (ret) {
+        LOG("failed to open logfile %s: %s",fullname,strerror(errno));
+        exit(-1);
+    }
+
+    CHK_SYSCALL(logfile = open(fullname, O_WRONLY|O_CREAT|O_APPEND, 0644));
+    free(fullname);
+    assert(logfile >= 3);
+
+    CHK_SYSCALL(nullfd = open("/dev/null", O_RDONLY));
+    assert(nullfd >= 3);
+
+    dup2(nullfd, 0);
+    dup2(logfile, 1);
+    dup2(logfile, 2);
+
+    close(nullfd);
+
+    CHK_SYSCALL(daemon(0, 1));
+
+    if (pidfile) {
+        int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
+        char *pid = NULL;
+
+        if (fd == -1) {
+            perror("Unable to open pidfile");
+            exit(1);
+        }
+
+        if (asprintf(&pid, "%ld\n", (long)getpid()) == -1) {
+            perror("Formatting pid");
+            exit(1);
+        }
+
+        if (write(fd, pid, strlen(pid)) < 0) {
+            perror("Writing pid");
+            exit(1);
+        }
+
+        if (close(fd) < 0) {
+            perror("Closing pidfile");
+            exit(1);
+        }
+
+        free(pid);
+    }
+
+out:
+    return ret;
+}
+
+static int parse_action_on_shutdown(const char *buf, libxl_action_on_shutdown *a)
+{
+    int i;
+    const char *n;
+
+    for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
+        n = action_on_shutdown_names[i];
+
+        if (!n) continue;
+
+        if (strcmp(buf, n) == 0) {
+            *a = i;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+#define DSTATE_INITIAL   0
+#define DSTATE_TAP       1
+#define DSTATE_PHYSPATH  2
+#define DSTATE_VIRTPATH  3
+#define DSTATE_VIRTTYPE  4
+#define DSTATE_RW        5
+#define DSTATE_TERMINAL  6
+
+static void parse_disk_config_multistring(XLU_Config **config,
+                                          int nspecs, const char *const *specs,
+                                          libxl_device_disk *disk)
+{
+    int e;
+
+    libxl_device_disk_init(disk);
+
+    if (!*config) {
+        *config = xlu_cfg_init(stderr, "command line");
+        if (!*config) { perror("xlu_cfg_init"); exit(-1); }
+    }
+
+    e = xlu_disk_parse(*config, nspecs, specs, disk);
+    if (e == EINVAL) exit(EXIT_FAILURE);
+    if (e) {
+        fprintf(stderr,"xlu_disk_parse failed: %s\n",strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+}
+
+static void parse_disk_config(XLU_Config **config, const char *spec,
+                              libxl_device_disk *disk)
+{
+    parse_disk_config_multistring(config, 1, &spec, disk);
+}
+
+static void parse_vif_rate(XLU_Config **config, const char *rate,
+                           libxl_device_nic *nic)
+{
+    int e;
+
+    e = xlu_vif_parse_rate(*config, rate, nic);
+    if (e == EINVAL || e == EOVERFLOW) exit(EXIT_FAILURE);
+    if (e) {
+        fprintf(stderr,"xlu_vif_parse_rate failed: %s\n",strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+}
+
+static void set_default_nic_values(libxl_device_nic *nic)
+{
+
+    if (default_vifscript) {
+        free(nic->script);
+        nic->script = strdup(default_vifscript);
+    }
+
+    if (default_bridge) {
+        free(nic->bridge);
+        nic->bridge = strdup(default_bridge);
+    }
+
+    if (default_gatewaydev) {
+        free(nic->gatewaydev);
+        nic->gatewaydev = strdup(default_gatewaydev);
+    }
+
+    if (default_vifbackend) {
+        free(nic->backend_domname);
+        nic->backend_domname = strdup(default_vifbackend);
+    }
+}
+
+static void split_string_into_string_list(const char *str,
+                                          const char *delim,
+                                          libxl_string_list *psl)
+{
+    char *s, *saveptr;
+    const char *p;
+    libxl_string_list sl;
+
+    int i = 0, nr = 0;
+
+    s = strdup(str);
+    if (s == NULL) {
+        fprintf(stderr, "unable to allocate memory to split string\n");
+        exit(-1);
+    }
+
+    /* Count number of entries */
+    p = strtok_r(s, delim, &saveptr);
+    do {
+        nr++;
+    } while ((p = strtok_r(NULL, delim, &saveptr)));
+
+    free(s);
+
+    s = strdup(str);
+
+    sl = malloc((nr+1) * sizeof (char *));
+    if (sl == NULL) {
+        fprintf(stderr, "unable to allocate memory to split string\n");
+        exit(-1);
+    }
+
+    p = strtok_r(s, delim, &saveptr);
+    do {
+        assert(i < nr);
+        sl[i] = strdup(p);
+        i++;
+    } while ((p = strtok_r(NULL, delim, &saveptr)));
+    sl[i] = NULL;
+
+    *psl = sl;
+
+    free(s);
+}
+
+/* NB: this follows the interface used by <ctype.h>. See 'man 3 ctype'
+   and look for CTYPE in libxl_internal.h */
+typedef int (*char_predicate_t)(const int c);
+
+static void trim(char_predicate_t predicate, const char *input, char **output)
+{
+    const char *first, *after;
+
+    for (first = input;
+         *first && predicate((unsigned char)first[0]);
+         first++)
+        ;
+
+    for (after = first + strlen(first);
+         after > first && predicate((unsigned char)after[-1]);
+         after--)
+        ;
+
+    size_t len_nonnull = after - first;
+    char *result = xmalloc(len_nonnull + 1);
+
+    memcpy(result, first, len_nonnull);
+    result[len_nonnull] = 0;
+
+    *output = result;
+}
+
+static int split_string_into_pair(const char *str,
+                                  const char *delim,
+                                  char **a,
+                                  char **b)
+{
+    char *s, *p, *saveptr, *aa = NULL, *bb = NULL;
+    int rc = 0;
+
+    s = xstrdup(str);
+
+    p = strtok_r(s, delim, &saveptr);
+    if (p == NULL) {
+        rc = ERROR_INVAL;
+        goto out;
+    }
+    aa = xstrdup(p);
+    p = strtok_r(NULL, delim, &saveptr);
+    if (p == NULL) {
+        rc = ERROR_INVAL;
+        goto out;
+    }
+    bb = xstrdup(p);
+
+    *a = aa;
+    aa = NULL;
+    *b = bb;
+    bb = NULL;
+out:
+    free(s);
+    free(aa);
+    free(bb);
+    return rc;
+}
+
+static int parse_range(const char *str, unsigned long *a, unsigned long *b)
+{
+    const char *nstr;
+    char *endptr;
+
+    *a = *b = strtoul(str, &endptr, 10);
+    if (endptr == str || *a == ULONG_MAX)
+        return 1;
+
+    if (*endptr == '-') {
+        nstr = endptr + 1;
+
+        *b = strtoul(nstr, &endptr, 10);
+        if (endptr == nstr || *b == ULONG_MAX || *b < *a)
+            return 1;
+    }
+
+    /* Valid value or range so far, but we also don't want junk after that */
+    if (*endptr != '\0')
+        return 1;
+
+    return 0;
+}
+
+/*
+ * Add or removes a specific set of cpus (specified in str, either as
+ * single cpus or as entire NUMA nodes) to/from cpumap.
+ */
+static int update_cpumap_range(const char *str, libxl_bitmap *cpumap)
+{
+    unsigned long ida, idb;
+    libxl_bitmap node_cpumap;
+    bool is_not = false, is_nodes = false;
+    int rc = 0;
+
+    libxl_bitmap_init(&node_cpumap);
+
+    rc = libxl_node_bitmap_alloc(ctx, &node_cpumap, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
+        goto out;
+    }
+
+    /* Are we adding or removing cpus/nodes? */
+    if (STR_SKIP_PREFIX(str, "^")) {
+        is_not = true;
+    }
+
+    /* Are we dealing with cpus or full nodes? */
+    if (STR_SKIP_PREFIX(str, "node:") || STR_SKIP_PREFIX(str, "nodes:")) {
+        is_nodes = true;
+    }
+
+    if (strcmp(str, "all") == 0) {
+        /* We do not accept "^all" or "^nodes:all" */
+        if (is_not) {
+            fprintf(stderr, "Can't combine \"^\" and \"all\".\n");
+            rc = ERROR_INVAL;
+        } else
+            libxl_bitmap_set_any(cpumap);
+        goto out;
+    }
+
+    rc = parse_range(str, &ida, &idb);
+    if (rc) {
+        fprintf(stderr, "Invalid pcpu range: %s.\n", str);
+        goto out;
+    }
+
+    /* Add or remove the specified cpus in the range */
+    while (ida <= idb) {
+        if (is_nodes) {
+            /* Add/Remove all the cpus of a NUMA node */
+            int i;
+
+            rc = libxl_node_to_cpumap(ctx, ida, &node_cpumap);
+            if (rc) {
+                fprintf(stderr, "libxl_node_to_cpumap failed.\n");
+                goto out;
+            }
+
+            /* Add/Remove all the cpus in the node cpumap */
+            libxl_for_each_set_bit(i, node_cpumap) {
+                is_not ? libxl_bitmap_reset(cpumap, i) :
+                         libxl_bitmap_set(cpumap, i);
+            }
+        } else {
+            /* Add/Remove this cpu */
+            is_not ? libxl_bitmap_reset(cpumap, ida) :
+                     libxl_bitmap_set(cpumap, ida);
+        }
+        ida++;
+    }
+
+ out:
+    libxl_bitmap_dispose(&node_cpumap);
+    return rc;
+}
+
+/*
+ * Takes a string representing a set of cpus (specified either as
+ * single cpus or as eintire NUMA nodes) and turns it into the
+ * corresponding libxl_bitmap (in cpumap).
+ */
+static int cpurange_parse(const char *cpu, libxl_bitmap *cpumap)
+{
+    char *ptr, *saveptr = NULL, *buf = xstrdup(cpu);
+    int rc = 0;
+
+    for (ptr = strtok_r(buf, ",", &saveptr); ptr;
+         ptr = strtok_r(NULL, ",", &saveptr)) {
+        rc = update_cpumap_range(ptr, cpumap);
+        if (rc)
+            break;
+    }
+    free(buf);
+
+    return rc;
+}
+
+static void parse_top_level_vnc_options(XLU_Config *config,
+                                        libxl_vnc_info *vnc)
+{
+    long l;
+
+    xlu_cfg_get_defbool(config, "vnc", &vnc->enable, 0);
+    xlu_cfg_replace_string (config, "vnclisten", &vnc->listen, 0);
+    xlu_cfg_replace_string (config, "vncpasswd", &vnc->passwd, 0);
+    if (!xlu_cfg_get_long (config, "vncdisplay", &l, 0))
+        vnc->display = l;
+    xlu_cfg_get_defbool(config, "vncunused", &vnc->findunused, 0);
+}
+
+static void parse_top_level_sdl_options(XLU_Config *config,
+                                        libxl_sdl_info *sdl)
+{
+    xlu_cfg_get_defbool(config, "sdl", &sdl->enable, 0);
+    xlu_cfg_get_defbool(config, "opengl", &sdl->opengl, 0);
+    xlu_cfg_replace_string (config, "display", &sdl->display, 0);
+    xlu_cfg_replace_string (config, "xauthority", &sdl->xauthority, 0);
+}
+
+static char *parse_cmdline(XLU_Config *config)
+{
+    char *cmdline = NULL;
+    const char *root = NULL, *extra = NULL, *buf = NULL;
+
+    xlu_cfg_get_string (config, "cmdline", &buf, 0);
+    xlu_cfg_get_string (config, "root", &root, 0);
+    xlu_cfg_get_string (config, "extra", &extra, 0);
+
+    if (buf) {
+        cmdline = strdup(buf);
+        if (root || extra)
+            fprintf(stderr, "Warning: ignoring root= and extra= "
+                    "in favour of cmdline=\n");
+    } else {
+        if (root && extra) {
+            xasprintf(&cmdline, "root=%s %s", root, extra);
+        } else if (root) {
+            xasprintf(&cmdline, "root=%s", root);
+        } else if (extra) {
+            cmdline = strdup(extra);
+        }
+    }
+
+    if ((buf || root || extra) && !cmdline) {
+        fprintf(stderr, "Failed to allocate memory for cmdline\n");
+        exit(EXIT_FAILURE);
+    }
+
+    return cmdline;
+}
+
+static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
+                                XLU_ConfigList *cpus, const char *buf,
+                                int num_cpus, bool is_hard)
+{
+    libxl_bitmap *vcpu_affinity_array;
+
+    /*
+     * If we are here, and buf is !NULL, we're dealing with a string. What
+     * we do in this case is parse it, and copy the result in _all_ (up to
+     * b_info->max_vcpus) the elements of the vcpu affinity array.
+     *
+     * If buf is NULL, we have a list, and what we do is putting in the
+     * i-eth element of the vcpu affinity array the result of the parsing
+     * of the i-eth entry of the list. If there are more vcpus than
+     * entries, it is fine to just not touch the last array elements.
+     */
+
+    /* Silently ignore values corresponding to non existing vcpus */
+    if (buf || num_cpus > b_info->max_vcpus)
+        num_cpus = b_info->max_vcpus;
+
+    if (is_hard) {
+        b_info->num_vcpu_hard_affinity = num_cpus;
+        b_info->vcpu_hard_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
+        vcpu_affinity_array = b_info->vcpu_hard_affinity;
+    } else {
+        b_info->num_vcpu_soft_affinity = num_cpus;
+        b_info->vcpu_soft_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
+        vcpu_affinity_array = b_info->vcpu_soft_affinity;
+    }
+
+    if (!buf) {
+        int j = 0;
+
+        while ((buf = xlu_cfg_get_listitem(cpus, j)) != NULL && j < num_cpus) {
+            libxl_bitmap_init(&vcpu_affinity_array[j]);
+            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[j], 0)) {
+                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", j);
+                exit(EXIT_FAILURE);
+            }
+
+            if (cpurange_parse(buf, &vcpu_affinity_array[j]))
+                exit(EXIT_FAILURE);
+
+            j++;
+        }
+
+        /* We have a list of cpumaps, disable automatic placement */
+        libxl_defbool_set(&b_info->numa_placement, false);
+    } else {
+        int i;
+
+        libxl_bitmap_init(&vcpu_affinity_array[0]);
+        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[0], 0)) {
+            fprintf(stderr, "Unable to allocate cpumap for vcpu 0\n");
+            exit(EXIT_FAILURE);
+        }
+
+        if (cpurange_parse(buf, &vcpu_affinity_array[0]))
+            exit(EXIT_FAILURE);
+
+        for (i = 1; i < b_info->max_vcpus; i++) {
+            libxl_bitmap_init(&vcpu_affinity_array[i]);
+            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[i], 0)) {
+                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", i);
+                exit(EXIT_FAILURE);
+            }
+            libxl_bitmap_copy(ctx, &vcpu_affinity_array[i],
+                              &vcpu_affinity_array[0]);
+        }
+
+        libxl_defbool_set(&b_info->numa_placement, false);
+    }
+}
+
+static unsigned long parse_ulong(const char *str)
+{
+    char *endptr;
+    unsigned long val;
+
+    val = strtoul(str, &endptr, 10);
+    if (endptr == str || val == ULONG_MAX) {
+        fprintf(stderr, "xl: failed to convert \"%s\" to number\n", str);
+        exit(EXIT_FAILURE);
+    }
+    return val;
+}
+
+static void replace_string(char **str, const char *val)
+{
+    free(*str);
+    *str = xstrdup(val);
+}
+
+static int match_option_size(const char *prefix, size_t len,
+        char *arg, char **argopt)
+{
+    int rc = strncmp(prefix, arg, len);
+    if (!rc) *argopt = arg+len;
+    return !rc;
+}
+#define MATCH_OPTION(prefix, arg, oparg) \
+    match_option_size((prefix "="), sizeof((prefix)), (arg), &(oparg))
+
+/* Parses network data and adds info into nic
+ * Returns 1 if the input token does not match one of the keys
+ * or parsed values are not correct. Successful parse returns 0 */
+static int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
+{
+    char *endptr, *oparg;
+    int i;
+    unsigned int val;
+
+    if (MATCH_OPTION("type", token, oparg)) {
+        if (!strcmp("vif", oparg)) {
+            nic->nictype = LIBXL_NIC_TYPE_VIF;
+        } else if (!strcmp("ioemu", oparg)) {
+            nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
+        } else {
+            fprintf(stderr, "Invalid parameter `type'.\n");
+            return 1;
+        }
+    } else if (MATCH_OPTION("mac", token, oparg)) {
+        for (i = 0; i < 6; i++) {
+            val = strtoul(oparg, &endptr, 16);
+            if ((oparg == endptr) || (val > 255)) {
+                fprintf(stderr, "Invalid parameter `mac'.\n");
+                return 1;
+            }
+            nic->mac[i] = val;
+            oparg = endptr + 1;
+        }
+    } else if (MATCH_OPTION("bridge", token, oparg)) {
+        replace_string(&nic->bridge, oparg);
+    } else if (MATCH_OPTION("netdev", token, oparg)) {
+        fprintf(stderr, "the netdev parameter is deprecated, "
+                        "please use gatewaydev instead\n");
+        replace_string(&nic->gatewaydev, oparg);
+    } else if (MATCH_OPTION("gatewaydev", token, oparg)) {
+        replace_string(&nic->gatewaydev, oparg);
+    } else if (MATCH_OPTION("ip", token, oparg)) {
+        replace_string(&nic->ip, oparg);
+    } else if (MATCH_OPTION("script", token, oparg)) {
+        replace_string(&nic->script, oparg);
+    } else if (MATCH_OPTION("backend", token, oparg)) {
+        replace_string(&nic->backend_domname, oparg);
+    } else if (MATCH_OPTION("vifname", token, oparg)) {
+        replace_string(&nic->ifname, oparg);
+    } else if (MATCH_OPTION("model", token, oparg)) {
+        replace_string(&nic->model, oparg);
+    } else if (MATCH_OPTION("rate", token, oparg)) {
+        parse_vif_rate(config, oparg, nic);
+    } else if (MATCH_OPTION("forwarddev", token, oparg)) {
+        replace_string(&nic->coloft_forwarddev, oparg);
+    } else if (MATCH_OPTION("accel", token, oparg)) {
+        fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
+    } else if (MATCH_OPTION("devid", token, oparg)) {
+        nic->devid = parse_ulong(oparg);
+    } else {
+        fprintf(stderr, "unrecognized argument `%s'\n", token);
+        return 1;
+    }
+    return 0;
+}
+
+static void parse_vnuma_config(const XLU_Config *config,
+                               libxl_domain_build_info *b_info)
+{
+    libxl_physinfo physinfo;
+    uint32_t nr_nodes;
+    XLU_ConfigList *vnuma;
+    int i, j, len, num_vnuma;
+    unsigned long max_vcpus = 0, max_memkb = 0;
+    /* Temporary storage for parsed vcpus information to avoid
+     * parsing config twice. This array has num_vnuma elements.
+     */
+    libxl_bitmap *vcpu_parsed;
+
+    libxl_physinfo_init(&physinfo);
+    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+        libxl_physinfo_dispose(&physinfo);
+        fprintf(stderr, "libxl_get_physinfo failed\n");
+        exit(EXIT_FAILURE);
+    }
+
+    nr_nodes = physinfo.nr_nodes;
+    libxl_physinfo_dispose(&physinfo);
+
+    if (xlu_cfg_get_list(config, "vnuma", &vnuma, &num_vnuma, 1))
+        return;
+
+    if (!num_vnuma)
+        return;
+
+    b_info->num_vnuma_nodes = num_vnuma;
+    b_info->vnuma_nodes = xcalloc(num_vnuma, sizeof(libxl_vnode_info));
+    vcpu_parsed = xcalloc(num_vnuma, sizeof(libxl_bitmap));
+    for (i = 0; i < num_vnuma; i++) {
+        libxl_bitmap_init(&vcpu_parsed[i]);
+        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_parsed[i], b_info->max_vcpus)) {
+            fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
+        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
+
+        libxl_vnode_info_init(p);
+        p->distances = xcalloc(b_info->num_vnuma_nodes,
+                               sizeof(*p->distances));
+        p->num_distances = b_info->num_vnuma_nodes;
+    }
+
+    for (i = 0; i < num_vnuma; i++) {
+        XLU_ConfigValue *vnode_spec, *conf_option;
+        XLU_ConfigList *vnode_config_list;
+        int conf_count;
+        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
+
+        vnode_spec = xlu_cfg_get_listitem2(vnuma, i);
+        assert(vnode_spec);
+
+        xlu_cfg_value_get_list(config, vnode_spec, &vnode_config_list, 0);
+        if (!vnode_config_list) {
+            fprintf(stderr, "xl: cannot get vnode config option list\n");
+            exit(EXIT_FAILURE);
+        }
+
+        for (conf_count = 0;
+             (conf_option =
+              xlu_cfg_get_listitem2(vnode_config_list, conf_count));
+             conf_count++) {
+
+            if (xlu_cfg_value_type(conf_option) == XLU_STRING) {
+                char *buf, *option_untrimmed, *value_untrimmed;
+                char *option, *value;
+                unsigned long val;
+
+                xlu_cfg_value_get_string(config, conf_option, &buf, 0);
+
+                if (!buf) continue;
+
+                if (split_string_into_pair(buf, "=",
+                                           &option_untrimmed,
+                                           &value_untrimmed)) {
+                    fprintf(stderr, "xl: failed to split \"%s\" into pair\n",
+                            buf);
+                    exit(EXIT_FAILURE);
+                }
+                trim(isspace, option_untrimmed, &option);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp("pnode", option)) {
+                    val = parse_ulong(value);
+                    if (val >= nr_nodes) {
+                        fprintf(stderr,
+                                "xl: invalid pnode number: %lu\n", val);
+                        exit(EXIT_FAILURE);
+                    }
+                    p->pnode = val;
+                    libxl_defbool_set(&b_info->numa_placement, false);
+                } else if (!strcmp("size", option)) {
+                    val = parse_ulong(value);
+                    p->memkb = val << 10;
+                    max_memkb += p->memkb;
+                } else if (!strcmp("vcpus", option)) {
+                    libxl_string_list cpu_spec_list;
+                    unsigned long s, e;
+
+                    split_string_into_string_list(value, ",", &cpu_spec_list);
+                    len = libxl_string_list_length(&cpu_spec_list);
+
+                    for (j = 0; j < len; j++) {
+                        parse_range(cpu_spec_list[j], &s, &e);
+                        for (; s <= e; s++) {
+                            /*
+                             * Note that if we try to set a bit beyond
+                             * the size of bitmap, libxl_bitmap_set
+                             * has no effect. The resulted bitmap
+                             * doesn't reflect what user wants. The
+                             * fallout is dealt with later after
+                             * parsing.
+                             */
+                            libxl_bitmap_set(&vcpu_parsed[i], s);
+                            max_vcpus++;
+                        }
+                    }
+
+                    libxl_string_list_dispose(&cpu_spec_list);
+                } else if (!strcmp("vdistances", option)) {
+                    libxl_string_list vdist;
+
+                    split_string_into_string_list(value, ",", &vdist);
+                    len = libxl_string_list_length(&vdist);
+
+                    for (j = 0; j < len; j++) {
+                        val = parse_ulong(vdist[j]);
+                        p->distances[j] = val;
+                    }
+                    libxl_string_list_dispose(&vdist);
+                }
+                free(option);
+                free(value);
+                free(option_untrimmed);
+                free(value_untrimmed);
+            }
+        }
+    }
+
+    /* User has specified maxvcpus= */
+    if (b_info->max_vcpus != 0) {
+        if (b_info->max_vcpus != max_vcpus) {
+            fprintf(stderr, "xl: vnuma vcpus and maxvcpus= mismatch\n");
+            exit(EXIT_FAILURE);
+        }
+    } else {
+        int host_cpus = libxl_get_online_cpus(ctx);
+
+        if (host_cpus < 0) {
+            fprintf(stderr, "Failed to get online cpus\n");
+            exit(EXIT_FAILURE);
+        }
+
+        if (host_cpus < max_vcpus) {
+            fprintf(stderr, "xl: vnuma specifies more vcpus than pcpus, "\
+                    "use maxvcpus= to override this check.\n");
+            exit(EXIT_FAILURE);
+        }
+
+        b_info->max_vcpus = max_vcpus;
+    }
+
+    /* User has specified maxmem= */
+    if (b_info->max_memkb != LIBXL_MEMKB_DEFAULT &&
+        b_info->max_memkb != max_memkb) {
+        fprintf(stderr, "xl: maxmem and vnuma memory size mismatch\n");
+        exit(EXIT_FAILURE);
+    } else
+        b_info->max_memkb = max_memkb;
+
+    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
+        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
+
+        libxl_bitmap_copy_alloc(ctx, &p->vcpus, &vcpu_parsed[i]);
+        libxl_bitmap_dispose(&vcpu_parsed[i]);
+    }
+
+    free(vcpu_parsed);
+}
+
+/* Parses usbctrl data and adds info into usbctrl
+ * Returns 1 if the input token does not match one of the keys
+ * or parsed values are not correct. Successful parse returns 0 */
+static int parse_usbctrl_config(libxl_device_usbctrl *usbctrl, char *token)
+{
+    char *oparg;
+
+    if (MATCH_OPTION("type", token, oparg)) {
+        if (libxl_usbctrl_type_from_string(oparg, &usbctrl->type)) {
+            fprintf(stderr, "Invalid usb controller type '%s'\n", oparg);
+            return 1;
+        }
+    } else if (MATCH_OPTION("version", token, oparg)) {
+        usbctrl->version = atoi(oparg);
+    } else if (MATCH_OPTION("ports", token, oparg)) {
+        usbctrl->ports = atoi(oparg);
+    } else {
+        fprintf(stderr, "Unknown string `%s' in usbctrl spec\n", token);
+        return 1;
+    }
+
+    return 0;
+}
+
+/* Parses usbdev data and adds info into usbdev
+ * Returns 1 if the input token does not match one of the keys
+ * or parsed values are not correct. Successful parse returns 0 */
+static int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token)
+{
+    char *oparg;
+
+    if (MATCH_OPTION("type", token, oparg)) {
+        if (libxl_usbdev_type_from_string(oparg, &usbdev->type)) {
+            fprintf(stderr, "Invalid usb device type: %s\n", optarg);
+            return 1;
+        }
+    } else if (MATCH_OPTION("hostbus", token, oparg)) {
+        usbdev->u.hostdev.hostbus = strtoul(oparg, NULL, 0);
+    } else if (MATCH_OPTION("hostaddr", token, oparg)) {
+        usbdev->u.hostdev.hostaddr = strtoul(oparg, NULL, 0);
+    } else if (MATCH_OPTION("controller", token, oparg)) {
+        usbdev->ctrl = atoi(oparg);
+    } else if (MATCH_OPTION("port", token, oparg)) {
+        usbdev->port = atoi(oparg);
+    } else {
+        fprintf(stderr, "Unknown string `%s' in usbdev spec\n", token);
+        return 1;
+    }
+
+    return 0;
+}
+
+static void parse_config_data(const char *config_source,
+                              const char *config_data,
+                              int config_len,
+                              libxl_domain_config *d_config)
+{
+    const char *buf;
+    long l, vcpus = 0;
+    XLU_Config *config;
+    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
+                   *usbctrls, *usbdevs;
+    XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
+    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
+    int pci_power_mgmt = 0;
+    int pci_msitranslate = 0;
+    int pci_permissive = 0;
+    int pci_seize = 0;
+    int i, e;
+    char *kernel_basename;
+
+    libxl_domain_create_info *c_info = &d_config->c_info;
+    libxl_domain_build_info *b_info = &d_config->b_info;
+
+    config= xlu_cfg_init(stderr, config_source);
+    if (!config) {
+        fprintf(stderr, "Failed to allocate for configuration\n");
+        exit(1);
+    }
+
+    e= xlu_cfg_readdata(config, config_data, config_len);
+    if (e) {
+        fprintf(stderr, "Failed to parse config: %s\n", strerror(e));
+        exit(1);
+    }
+
+    if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0))
+        xlu_cfg_replace_string(config, "init_seclabel",
+                               &c_info->ssid_label, 0);
+
+    if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) {
+        if (c_info->ssid_label)
+            xlu_cfg_replace_string(config, "seclabel",
+                                   &b_info->exec_ssid_label, 0);
+        else
+            xlu_cfg_replace_string(config, "seclabel",
+                                   &c_info->ssid_label, 0);
+    }
+
+    libxl_defbool_set(&c_info->run_hotplug_scripts, run_hotplug_scripts);
+    c_info->type = LIBXL_DOMAIN_TYPE_PV;
+    if (!xlu_cfg_get_string (config, "builder", &buf, 0) &&
+        !strncmp(buf, "hvm", strlen(buf)))
+        c_info->type = LIBXL_DOMAIN_TYPE_HVM;
+
+    xlu_cfg_get_defbool(config, "pvh", &c_info->pvh, 0);
+    xlu_cfg_get_defbool(config, "hap", &c_info->hap, 0);
+
+    if (xlu_cfg_replace_string (config, "name", &c_info->name, 0)) {
+        fprintf(stderr, "Domain name must be specified.\n");
+        exit(1);
+    }
+
+    if (!xlu_cfg_get_string (config, "uuid", &buf, 0) ) {
+        if ( libxl_uuid_from_string(&c_info->uuid, buf) ) {
+            fprintf(stderr, "Failed to parse UUID: %s\n", buf);
+            exit(1);
+        }
+    }else{
+        libxl_uuid_generate(&c_info->uuid);
+    }
+
+    xlu_cfg_get_defbool(config, "oos", &c_info->oos, 0);
+
+    if (!xlu_cfg_get_string (config, "pool", &buf, 0))
+        xlu_cfg_replace_string(config, "pool", &c_info->pool_name, 0);
+
+    libxl_domain_build_info_init_type(b_info, c_info->type);
+    if (blkdev_start)
+        b_info->blkdev_start = strdup(blkdev_start);
+
+    /* the following is the actual config parsing with overriding
+     * values in the structures */
+    if (!xlu_cfg_get_long (config, "cpu_weight", &l, 0))
+        b_info->sched_params.weight = l;
+    if (!xlu_cfg_get_long (config, "cap", &l, 0))
+        b_info->sched_params.cap = l;
+    if (!xlu_cfg_get_long (config, "period", &l, 0))
+        b_info->sched_params.period = l;
+    if (!xlu_cfg_get_long (config, "slice", &l, 0))
+        b_info->sched_params.slice = l;
+    if (!xlu_cfg_get_long (config, "latency", &l, 0))
+        b_info->sched_params.latency = l;
+    if (!xlu_cfg_get_long (config, "extratime", &l, 0))
+        b_info->sched_params.extratime = l;
+
+    if (!xlu_cfg_get_long (config, "memory", &l, 0))
+        b_info->target_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long (config, "maxmem", &l, 0))
+        b_info->max_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long (config, "vcpus", &l, 0)) {
+        vcpus = l;
+        if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, l)) {
+            fprintf(stderr, "Unable to allocate cpumap\n");
+            exit(1);
+        }
+        libxl_bitmap_set_none(&b_info->avail_vcpus);
+        while (l-- > 0)
+            libxl_bitmap_set((&b_info->avail_vcpus), l);
+    }
+
+    if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
+        b_info->max_vcpus = l;
+
+    parse_vnuma_config(config, b_info);
+
+    /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
+     * they are not set by user specified config option or vnuma.
+     */
+    if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
+        b_info->max_memkb = b_info->target_memkb;
+    if (b_info->max_vcpus == 0)
+        b_info->max_vcpus = vcpus;
+
+    if (b_info->max_vcpus < vcpus) {
+        fprintf(stderr, "xl: maxvcpus < vcpus\n");
+        exit(1);
+    }
+
+    buf = NULL;
+    if (!xlu_cfg_get_list (config, "cpus", &cpus, &num_cpus, 1) ||
+        !xlu_cfg_get_string (config, "cpus", &buf, 0))
+        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, /* is_hard */ true);
+
+    buf = NULL;
+    if (!xlu_cfg_get_list (config, "cpus_soft", &cpus, &num_cpus, 1) ||
+        !xlu_cfg_get_string (config, "cpus_soft", &buf, 0))
+        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, false);
+
+    libxl_defbool_set(&b_info->claim_mode, claim_mode);
+
+    if (xlu_cfg_get_string (config, "on_poweroff", &buf, 0))
+        buf = "destroy";
+    if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
+        fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    if (xlu_cfg_get_string (config, "on_reboot", &buf, 0))
+        buf = "restart";
+    if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
+        fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    if (xlu_cfg_get_string (config, "on_watchdog", &buf, 0))
+        buf = "destroy";
+    if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
+        fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+
+    if (xlu_cfg_get_string (config, "on_crash", &buf, 0))
+        buf = "destroy";
+    if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
+        fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    if (xlu_cfg_get_string (config, "on_soft_reset", &buf, 0))
+        buf = "soft-reset";
+    if (!parse_action_on_shutdown(buf, &d_config->on_soft_reset)) {
+        fprintf(stderr, "Unknown on_soft_reset action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    /* libxl_get_required_shadow_memory() must be called after final values
+     * (default or specified) for vcpus and memory are set, because the
+     * calculation depends on those values. */
+    b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l, 0)
+        ? l * 1024
+        : libxl_get_required_shadow_memory(b_info->max_memkb,
+                                           b_info->max_vcpus);
+
+    xlu_cfg_get_defbool(config, "nomigrate", &b_info->disable_migrate, 0);
+
+    if (!xlu_cfg_get_long(config, "tsc_mode", &l, 1)) {
+        const char *s = libxl_tsc_mode_to_string(l);
+        fprintf(stderr, "WARNING: specifying \"tsc_mode\" as an integer is deprecated. "
+                "Please use the named parameter variant. %s%s%s\n",
+                s ? "e.g. tsc_mode=\"" : "",
+                s ? s : "",
+                s ? "\"" : "");
+
+        if (l < LIBXL_TSC_MODE_DEFAULT ||
+            l > LIBXL_TSC_MODE_NATIVE_PARAVIRT) {
+            fprintf(stderr, "ERROR: invalid value %ld for \"tsc_mode\"\n", l);
+            exit (1);
+        }
+        b_info->tsc_mode = l;
+    } else if (!xlu_cfg_get_string(config, "tsc_mode", &buf, 0)) {
+        fprintf(stderr, "got a tsc mode string: \"%s\"\n", buf);
+        if (libxl_tsc_mode_from_string(buf, &b_info->tsc_mode)) {
+            fprintf(stderr, "ERROR: invalid value \"%s\" for \"tsc_mode\"\n",
+                    buf);
+            exit (1);
+        }
+    }
+
+    if (!xlu_cfg_get_long(config, "rtc_timeoffset", &l, 0))
+        b_info->rtc_timeoffset = l;
+
+    if (!xlu_cfg_get_long(config, "vncviewer", &l, 0))
+        fprintf(stderr, "WARNING: ignoring \"vncviewer\" option. "
+                "Use \"-V\" option of \"xl create\" to automatically spawn vncviewer.\n");
+
+    xlu_cfg_get_defbool(config, "localtime", &b_info->localtime, 0);
+
+    if (!xlu_cfg_get_long (config, "videoram", &l, 0))
+        b_info->video_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long(config, "max_event_channels", &l, 0))
+        b_info->event_channels = l;
+
+    xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0);
+    xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0);
+    xlu_cfg_replace_string (config, "device_tree", &b_info->device_tree, 0);
+    b_info->cmdline = parse_cmdline(config);
+
+    xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);
+    xlu_cfg_get_defbool(config, "acpi", &b_info->acpi, 0);
+
+    switch(b_info->type) {
+    case LIBXL_DOMAIN_TYPE_HVM:
+        kernel_basename = libxl_basename(b_info->kernel);
+        if (!strcmp(kernel_basename, "hvmloader")) {
+            fprintf(stderr, "WARNING: you seem to be using \"kernel\" "
+                    "directive to override HVM guest firmware. Ignore "
+                    "that. Use \"firmware_override\" instead if you "
+                    "really want a non-default firmware\n");
+            b_info->kernel = NULL;
+        }
+        free(kernel_basename);
+
+        xlu_cfg_replace_string (config, "firmware_override",
+                                &b_info->u.hvm.firmware, 0);
+        xlu_cfg_replace_string (config, "bios_path_override",
+                                &b_info->u.hvm.system_firmware, 0);
+        if (!xlu_cfg_get_string(config, "bios", &buf, 0)) {
+            if (libxl_bios_type_from_string(buf, &b_info->u.hvm.bios)) {
+                fprintf(stderr, "ERROR: invalid value \"%s\" for \"bios\"\n",
+                    buf);
+                exit (1);
+            }
+        } else if (b_info->u.hvm.system_firmware)
+            fprintf(stderr, "WARNING: "
+                    "bios_path_override given without specific bios name\n");
+
+        xlu_cfg_get_defbool(config, "pae", &b_info->u.hvm.pae, 0);
+        xlu_cfg_get_defbool(config, "apic", &b_info->u.hvm.apic, 0);
+        xlu_cfg_get_defbool(config, "acpi_s3", &b_info->u.hvm.acpi_s3, 0);
+        xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
+        xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
+        xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
+        xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
+
+        switch (xlu_cfg_get_list(config, "viridian",
+                                 &viridian, &num_viridian, 1))
+        {
+        case 0: /* Success */
+            if (num_viridian) {
+                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
+                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_disable,
+                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+            }
+            for (i = 0; i < num_viridian; i++) {
+                libxl_viridian_enlightenment v;
+
+                buf = xlu_cfg_get_listitem(viridian, i);
+                if (strcmp(buf, "all") == 0)
+                    libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
+                else if (strcmp(buf, "defaults") == 0)
+                    libxl_defbool_set(&b_info->u.hvm.viridian, true);
+                else {
+                    libxl_bitmap *s = &b_info->u.hvm.viridian_enable;
+                    libxl_bitmap *r = &b_info->u.hvm.viridian_disable;
+
+                    if (*buf == '!') {
+                        s = &b_info->u.hvm.viridian_disable;
+                        r = &b_info->u.hvm.viridian_enable;
+                        buf++;
+                    }
+
+                    e = libxl_viridian_enlightenment_from_string(buf, &v);
+                    if (e) {
+                        fprintf(stderr,
+                                "xl: unknown viridian enlightenment '%s'\n",
+                                buf);
+                        exit(-ERROR_FAIL);
+                    }
+
+                    libxl_bitmap_set(s, v);
+                    libxl_bitmap_reset(r, v);
+                }
+            }
+            break;
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 1);
+            break;
+        default:
+            fprintf(stderr,"xl: Unable to parse viridian enlightenments.\n");
+            exit(-ERROR_FAIL);
+        }
+
+        if (!xlu_cfg_get_long(config, "mmio_hole", &l, 0)) {
+            uint64_t mmio_hole_size;
+
+            b_info->u.hvm.mmio_hole_memkb = l * 1024;
+            mmio_hole_size = b_info->u.hvm.mmio_hole_memkb * 1024;
+            if (mmio_hole_size < HVM_BELOW_4G_MMIO_LENGTH ||
+                mmio_hole_size > HVM_BELOW_4G_MMIO_START) {
+                fprintf(stderr,
+                        "ERROR: invalid value %ld for \"mmio_hole\"\n", l);
+                exit (1);
+            }
+        }
+        if (!xlu_cfg_get_long(config, "timer_mode", &l, 1)) {
+            const char *s = libxl_timer_mode_to_string(l);
+            fprintf(stderr, "WARNING: specifying \"timer_mode\" as an integer is deprecated. "
+                    "Please use the named parameter variant. %s%s%s\n",
+                    s ? "e.g. timer_mode=\"" : "",
+                    s ? s : "",
+                    s ? "\"" : "");
+
+            if (l < LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS ||
+                l > LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING) {
+                fprintf(stderr, "ERROR: invalid value %ld for \"timer_mode\"\n", l);
+                exit (1);
+            }
+            b_info->u.hvm.timer_mode = l;
+        } else if (!xlu_cfg_get_string(config, "timer_mode", &buf, 0)) {
+            if (libxl_timer_mode_from_string(buf, &b_info->u.hvm.timer_mode)) {
+                fprintf(stderr, "ERROR: invalid value \"%s\" for \"timer_mode\"\n",
+                        buf);
+                exit (1);
+            }
+        }
+
+        xlu_cfg_get_defbool(config, "nestedhvm", &b_info->u.hvm.nested_hvm, 0);
+
+        xlu_cfg_get_defbool(config, "altp2mhvm", &b_info->u.hvm.altp2m, 0);
+
+        xlu_cfg_replace_string(config, "smbios_firmware",
+                               &b_info->u.hvm.smbios_firmware, 0);
+        xlu_cfg_replace_string(config, "acpi_firmware",
+                               &b_info->u.hvm.acpi_firmware, 0);
+
+        if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) {
+            if (!strcmp(buf, "generate")) {
+                e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);
+                if (e) {
+                    fprintf(stderr, "ERROR: failed to generate a VM Generation ID\n");
+                    exit(1);
+                }
+            } else if (!strcmp(buf, "none")) {
+                ;
+            } else {
+                    fprintf(stderr, "ERROR: \"ms_vm_genid\" option must be \"generate\" or \"none\"\n");
+                    exit(1);
+            }
+        }
+
+        if (!xlu_cfg_get_long (config, "rdm_mem_boundary", &l, 0))
+            b_info->u.hvm.rdm_mem_boundary_memkb = l * 1024;
+        break;
+    case LIBXL_DOMAIN_TYPE_PV:
+    {
+        xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader, 0);
+        switch (xlu_cfg_get_list_as_string_list(config, "bootloader_args",
+                                      &b_info->u.pv.bootloader_args, 1))
+        {
+
+        case 0: break; /* Success */
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            if (!xlu_cfg_get_string(config, "bootloader_args", &buf, 0)) {
+
+                fprintf(stderr, "WARNING: Specifying \"bootloader_args\""
+                        " as a string is deprecated. "
+                        "Please use a list of arguments.\n");
+                split_string_into_string_list(buf, " \t\n",
+                                              &b_info->u.pv.bootloader_args);
+            }
+            break;
+        default:
+            fprintf(stderr,"xl: Unable to parse bootloader_args.\n");
+            exit(-ERROR_FAIL);
+        }
+
+        if (!b_info->u.pv.bootloader && !b_info->kernel) {
+            fprintf(stderr, "Neither kernel nor bootloader specified\n");
+            exit(1);
+        }
+
+        break;
+    }
+    default:
+        abort();
+    }
+
+    if (!xlu_cfg_get_list(config, "ioports", &ioports, &num_ioports, 0)) {
+        b_info->num_ioports = num_ioports;
+        b_info->ioports = calloc(num_ioports, sizeof(*b_info->ioports));
+        if (b_info->ioports == NULL) {
+            fprintf(stderr, "unable to allocate memory for ioports\n");
+            exit(-1);
+        }
+
+        for (i = 0; i < num_ioports; i++) {
+            const char *buf2;
+            char *ep;
+            uint32_t start, end;
+            unsigned long ul;
+
+            buf = xlu_cfg_get_listitem (ioports, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Unable to get element #%d in ioport list\n", i);
+                exit(1);
+            }
+            ul = strtoul(buf, &ep, 16);
+            if (ep == buf) {
+                fprintf(stderr, "xl: Invalid argument parsing ioport: %s\n",
+                        buf);
+                exit(1);
+            }
+            if (ul >= UINT32_MAX) {
+                fprintf(stderr, "xl: ioport %lx too big\n", ul);
+                exit(1);
+            }
+            start = end = ul;
+
+            if (*ep == '-') {
+                buf2 = ep + 1;
+                ul = strtoul(buf2, &ep, 16);
+                if (ep == buf2 || *ep != '\0' || start > end) {
+                    fprintf(stderr,
+                            "xl: Invalid argument parsing ioport: %s\n", buf);
+                    exit(1);
+                }
+                if (ul >= UINT32_MAX) {
+                    fprintf(stderr, "xl: ioport %lx too big\n", ul);
+                    exit(1);
+                }
+                end = ul;
+            } else if ( *ep != '\0' )
+                fprintf(stderr,
+                        "xl: Invalid argument parsing ioport: %s\n", buf);
+            b_info->ioports[i].first = start;
+            b_info->ioports[i].number = end - start + 1;
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "irqs", &irqs, &num_irqs, 0)) {
+        b_info->num_irqs = num_irqs;
+        b_info->irqs = calloc(num_irqs, sizeof(*b_info->irqs));
+        if (b_info->irqs == NULL) {
+            fprintf(stderr, "unable to allocate memory for ioports\n");
+            exit(-1);
+        }
+        for (i = 0; i < num_irqs; i++) {
+            char *ep;
+            unsigned long ul;
+            buf = xlu_cfg_get_listitem (irqs, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Unable to get element %d in irq list\n", i);
+                exit(1);
+            }
+            ul = strtoul(buf, &ep, 10);
+            if (ep == buf || *ep != '\0') {
+                fprintf(stderr,
+                        "xl: Invalid argument parsing irq: %s\n", buf);
+                exit(1);
+            }
+            if (ul >= UINT32_MAX) {
+                fprintf(stderr, "xl: irq %lx too big\n", ul);
+                exit(1);
+            }
+            b_info->irqs[i] = ul;
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "iomem", &iomem, &num_iomem, 0)) {
+        int ret;
+        b_info->num_iomem = num_iomem;
+        b_info->iomem = calloc(num_iomem, sizeof(*b_info->iomem));
+        if (b_info->iomem == NULL) {
+            fprintf(stderr, "unable to allocate memory for iomem\n");
+            exit(-1);
+        }
+        for (i = 0; i < num_iomem; i++) {
+            int used;
+
+            buf = xlu_cfg_get_listitem (iomem, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Unable to get element %d in iomem list\n", i);
+                exit(1);
+            }
+            libxl_iomem_range_init(&b_info->iomem[i]);
+            ret = sscanf(buf, "%" SCNx64",%" SCNx64"%n@%" SCNx64"%n",
+                         &b_info->iomem[i].start,
+                         &b_info->iomem[i].number, &used,
+                         &b_info->iomem[i].gfn, &used);
+            if (ret < 2 || buf[used] != '\0') {
+                fprintf(stderr,
+                        "xl: Invalid argument parsing iomem: %s\n", buf);
+                exit(1);
+            }
+        }
+    }
+
+
+
+    if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
+        d_config->num_disks = 0;
+        d_config->disks = NULL;
+        while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
+            libxl_device_disk *disk;
+            char *buf2 = strdup(buf);
+
+            disk = ARRAY_EXTEND_INIT_NODEVID(d_config->disks,
+                                             d_config->num_disks,
+                                             libxl_device_disk_init);
+            parse_disk_config(&config, buf2, disk);
+
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
+        d_config->num_vtpms = 0;
+        d_config->vtpms = NULL;
+        while ((buf = xlu_cfg_get_listitem (vtpms, d_config->num_vtpms)) != NULL) {
+            libxl_device_vtpm *vtpm;
+            char * buf2 = strdup(buf);
+            char *p, *p2;
+            bool got_backend = false;
+
+            vtpm = ARRAY_EXTEND_INIT(d_config->vtpms,
+                                     d_config->num_vtpms,
+                                     libxl_device_vtpm_init);
+
+            p = strtok(buf2, ",");
+            if(p) {
+               do {
+                  while(*p == ' ')
+                     ++p;
+                  if ((p2 = strchr(p, '=')) == NULL)
+                     break;
+                  *p2 = '\0';
+                  if (!strcmp(p, "backend")) {
+                     vtpm->backend_domname = strdup(p2 + 1);
+                     got_backend = true;
+                  } else if(!strcmp(p, "uuid")) {
+                     if( libxl_uuid_from_string(&vtpm->uuid, p2 + 1) ) {
+                        fprintf(stderr,
+                              "Failed to parse vtpm UUID: %s\n", p2 + 1);
+                        exit(1);
+                    }
+                  } else {
+                     fprintf(stderr, "Unknown string `%s' in vtpm spec\n", p);
+                     exit(1);
+                  }
+               } while ((p = strtok(NULL, ",")) != NULL);
+            }
+            if(!got_backend) {
+               fprintf(stderr, "vtpm spec missing required backend field!\n");
+               exit(1);
+            }
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
+        d_config->num_channels = 0;
+        d_config->channels = NULL;
+        while ((buf = xlu_cfg_get_listitem (channels,
+                d_config->num_channels)) != NULL) {
+            libxl_device_channel *chn;
+            libxl_string_list pairs;
+            char *path = NULL;
+            int len;
+
+            chn = ARRAY_EXTEND_INIT(d_config->channels, d_config->num_channels,
+                                   libxl_device_channel_init);
+
+            split_string_into_string_list(buf, ",", &pairs);
+            len = libxl_string_list_length(&pairs);
+            for (i = 0; i < len; i++) {
+                char *key, *key_untrimmed, *value, *value_untrimmed;
+                int rc;
+                rc = split_string_into_pair(pairs[i], "=",
+                                            &key_untrimmed,
+                                            &value_untrimmed);
+                if (rc != 0) {
+                    fprintf(stderr, "failed to parse channel configuration: %s",
+                            pairs[i]);
+                    exit(1);
+                }
+                trim(isspace, key_untrimmed, &key);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp(key, "backend")) {
+                    replace_string(&chn->backend_domname, value);
+                } else if (!strcmp(key, "name")) {
+                    replace_string(&chn->name, value);
+                } else if (!strcmp(key, "path")) {
+                    replace_string(&path, value);
+                } else if (!strcmp(key, "connection")) {
+                    if (!strcmp(value, "pty")) {
+                        chn->connection = LIBXL_CHANNEL_CONNECTION_PTY;
+                    } else if (!strcmp(value, "socket")) {
+                        chn->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
+                    } else {
+                        fprintf(stderr, "unknown channel connection '%s'\n",
+                                value);
+                        exit(1);
+                    }
+                } else {
+                    fprintf(stderr, "unknown channel parameter '%s',"
+                                  " ignoring\n", key);
+                }
+                free(key);
+                free(key_untrimmed);
+                free(value);
+                free(value_untrimmed);
+            }
+            switch (chn->connection) {
+            case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
+                fprintf(stderr, "channel has unknown 'connection'\n");
+                exit(1);
+            case LIBXL_CHANNEL_CONNECTION_SOCKET:
+                if (!path) {
+                    fprintf(stderr, "channel connection 'socket' requires path=..\n");
+                    exit(1);
+                }
+                chn->u.socket.path = xstrdup(path);
+                break;
+            case LIBXL_CHANNEL_CONNECTION_PTY:
+                /* Nothing to do since PTY has no arguments */
+                break;
+            default:
+                fprintf(stderr, "unknown channel connection: %d",
+                        chn->connection);
+                exit(1);
+            }
+            libxl_string_list_dispose(&pairs);
+            free(path);
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
+        d_config->num_nics = 0;
+        d_config->nics = NULL;
+        while ((buf = xlu_cfg_get_listitem (nics, d_config->num_nics)) != NULL) {
+            libxl_device_nic *nic;
+            char *buf2 = strdup(buf);
+            char *p;
+
+            nic = ARRAY_EXTEND_INIT(d_config->nics,
+                                    d_config->num_nics,
+                                    libxl_device_nic_init);
+            set_default_nic_values(nic);
+
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_nic;
+            do {
+                while (*p == ' ')
+                    p++;
+                parse_nic_config(nic, &config, p);
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_nic:
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "vif2", NULL, 0, 0)) {
+        fprintf(stderr, "WARNING: vif2: netchannel2 is deprecated and not supported by xl\n");
+    }
+
+    d_config->num_vfbs = 0;
+    d_config->num_vkbs = 0;
+    d_config->vfbs = NULL;
+    d_config->vkbs = NULL;
+
+    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0, 0)) {
+        while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
+            libxl_device_vfb *vfb;
+            libxl_device_vkb *vkb;
+
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+
+            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
+                                    libxl_device_vfb_init);
+
+            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
+                                    libxl_device_vkb_init);
+
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_vfb;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "vnc")) {
+                    libxl_defbool_set(&vfb->vnc.enable, atoi(p2 + 1));
+                } else if (!strcmp(p, "vnclisten")) {
+                    free(vfb->vnc.listen);
+                    vfb->vnc.listen = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncpasswd")) {
+                    free(vfb->vnc.passwd);
+                    vfb->vnc.passwd = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncdisplay")) {
+                    vfb->vnc.display = atoi(p2 + 1);
+                } else if (!strcmp(p, "vncunused")) {
+                    libxl_defbool_set(&vfb->vnc.findunused, atoi(p2 + 1));
+                } else if (!strcmp(p, "keymap")) {
+                    free(vfb->keymap);
+                    vfb->keymap = strdup(p2 + 1);
+                } else if (!strcmp(p, "sdl")) {
+                    libxl_defbool_set(&vfb->sdl.enable, atoi(p2 + 1));
+                } else if (!strcmp(p, "opengl")) {
+                    libxl_defbool_set(&vfb->sdl.opengl, atoi(p2 + 1));
+                } else if (!strcmp(p, "display")) {
+                    free(vfb->sdl.display);
+                    vfb->sdl.display = strdup(p2 + 1);
+                } else if (!strcmp(p, "xauthority")) {
+                    free(vfb->sdl.xauthority);
+                    vfb->sdl.xauthority = strdup(p2 + 1);
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+
+skip_vfb:
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l, 0))
+        pci_msitranslate = l;
+
+    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l, 0))
+        pci_power_mgmt = l;
+
+    if (!xlu_cfg_get_long (config, "pci_permissive", &l, 0))
+        pci_permissive = l;
+
+    if (!xlu_cfg_get_long (config, "pci_seize", &l, 0))
+        pci_seize = l;
+
+    /* To be reworked (automatically enabled) once the auto ballooning
+     * after guest starts is done (with PCI devices passed in). */
+    if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
+        xlu_cfg_get_defbool(config, "e820_host", &b_info->u.pv.e820_host, 0);
+    }
+
+    if (!xlu_cfg_get_string(config, "rdm", &buf, 0)) {
+        libxl_rdm_reserve rdm;
+        if (!xlu_rdm_parse(config, &rdm, buf)) {
+            b_info->u.hvm.rdm.strategy = rdm.strategy;
+            b_info->u.hvm.rdm.policy = rdm.policy;
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
+        d_config->num_pcidevs = 0;
+        d_config->pcidevs = NULL;
+        for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
+            libxl_device_pci *pcidev;
+
+            pcidev = ARRAY_EXTEND_INIT_NODEVID(d_config->pcidevs,
+                                               d_config->num_pcidevs,
+                                               libxl_device_pci_init);
+            pcidev->msitranslate = pci_msitranslate;
+            pcidev->power_mgmt = pci_power_mgmt;
+            pcidev->permissive = pci_permissive;
+            pcidev->seize = pci_seize;
+            /*
+             * Like other pci option, the per-device policy always follows
+             * the global policy by default.
+             */
+            pcidev->rdm_policy = b_info->u.hvm.rdm.policy;
+            e = xlu_pci_parse_bdf(config, pcidev, buf);
+            if (e) {
+                fprintf(stderr,
+                        "unable to parse PCI BDF `%s' for passthrough\n",
+                        buf);
+                exit(-e);
+            }
+        }
+        if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV)
+            libxl_defbool_set(&b_info->u.pv.e820_host, true);
+    }
+
+    if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) {
+        d_config->num_dtdevs = 0;
+        d_config->dtdevs = NULL;
+        for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) {
+            libxl_device_dtdev *dtdev;
+
+            dtdev = ARRAY_EXTEND_INIT_NODEVID(d_config->dtdevs,
+                                              d_config->num_dtdevs,
+                                              libxl_device_dtdev_init);
+
+            dtdev->path = strdup(buf);
+            if (dtdev->path == NULL) {
+                fprintf(stderr, "unable to duplicate string for dtdevs\n");
+                exit(-1);
+            }
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "usbctrl", &usbctrls, 0, 0)) {
+        d_config->num_usbctrls = 0;
+        d_config->usbctrls = NULL;
+        while ((buf = xlu_cfg_get_listitem(usbctrls, d_config->num_usbctrls))
+               != NULL) {
+            libxl_device_usbctrl *usbctrl;
+            char *buf2 = strdup(buf);
+            char *p;
+
+            usbctrl = ARRAY_EXTEND_INIT(d_config->usbctrls,
+                                        d_config->num_usbctrls,
+                                        libxl_device_usbctrl_init);
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_usbctrl;
+            do {
+                while (*p == ' ')
+                    p++;
+                if (parse_usbctrl_config(usbctrl, p))
+                    exit(1);
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_usbctrl:
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "usbdev", &usbdevs, 0, 0)) {
+        d_config->num_usbdevs = 0;
+        d_config->usbdevs = NULL;
+        while ((buf = xlu_cfg_get_listitem(usbdevs, d_config->num_usbdevs))
+               != NULL) {
+            libxl_device_usbdev *usbdev;
+            char *buf2 = strdup(buf);
+            char *p;
+
+            usbdev = ARRAY_EXTEND_INIT_NODEVID(d_config->usbdevs,
+                                               d_config->num_usbdevs,
+                                               libxl_device_usbdev_init);
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_usbdev;
+            do {
+                while (*p == ' ')
+                    p++;
+                if (parse_usbdev_config(usbdev, p))
+                    exit(1);
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_usbdev:
+            free(buf2);
+        }
+    }
+
+    switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
+    case 0:
+        {
+            const char *errstr;
+
+            for (i = 0; (buf = xlu_cfg_get_listitem(cpuids, i)) != NULL; i++) {
+                e = libxl_cpuid_parse_config_xend(&b_info->cpuid, buf);
+                switch (e) {
+                case 0: continue;
+                case 1:
+                    errstr = "illegal leaf number";
+                    break;
+                case 2:
+                    errstr = "illegal subleaf number";
+                    break;
+                case 3:
+                    errstr = "missing colon";
+                    break;
+                case 4:
+                    errstr = "invalid register name (must be e[abcd]x)";
+                    break;
+                case 5:
+                    errstr = "policy string must be exactly 32 characters long";
+                    break;
+                default:
+                    errstr = "unknown error";
+                    break;
+                }
+                fprintf(stderr, "while parsing CPUID line: \"%s\":\n", buf);
+                fprintf(stderr, "  error #%i: %s\n", e, errstr);
+            }
+        }
+        break;
+    case EINVAL:    /* config option is not a list, parse as a string */
+        if (!xlu_cfg_get_string(config, "cpuid", &buf, 0)) {
+            char *buf2, *p, *strtok_ptr = NULL;
+            const char *errstr;
+
+            buf2 = strdup(buf);
+            p = strtok_r(buf2, ",", &strtok_ptr);
+            if (p == NULL) {
+                free(buf2);
+                break;
+            }
+            if (strcmp(p, "host")) {
+                fprintf(stderr, "while parsing CPUID string: \"%s\":\n", buf);
+                fprintf(stderr, "  error: first word must be \"host\"\n");
+                free(buf2);
+                break;
+            }
+            for (p = strtok_r(NULL, ",", &strtok_ptr); p != NULL;
+                 p = strtok_r(NULL, ",", &strtok_ptr)) {
+                e = libxl_cpuid_parse_config(&b_info->cpuid, p);
+                switch (e) {
+                case 0: continue;
+                case 1:
+                    errstr = "missing \"=\" in key=value";
+                    break;
+                case 2:
+                    errstr = "unknown CPUID flag name";
+                    break;
+                case 3:
+                    errstr = "illegal CPUID value (must be: [0|1|x|k|s])";
+                    break;
+                default:
+                    errstr = "unknown error";
+                    break;
+                }
+                fprintf(stderr, "while parsing CPUID flag: \"%s\":\n", p);
+                fprintf(stderr, "  error #%i: %s\n", e, errstr);
+            }
+            free(buf2);
+        }
+        break;
+    default:
+        break;
+    }
+
+    /* parse device model arguments, this works for pv, hvm and stubdom */
+    if (!xlu_cfg_get_string (config, "device_model", &buf, 0)) {
+        fprintf(stderr,
+                "WARNING: ignoring device_model directive.\n"
+                "WARNING: Use \"device_model_override\" instead if you"
+                " really want a non-default device_model\n");
+        if (strstr(buf, "stubdom-dm")) {
+            if (c_info->type == LIBXL_DOMAIN_TYPE_HVM)
+                fprintf(stderr, "WARNING: Or use"
+                        " \"device_model_stubdomain_override\" if you "
+                        " want to enable stubdomains\n");
+            else
+                fprintf(stderr, "WARNING: ignoring"
+                        " \"device_model_stubdomain_override\" directive"
+                        " for pv guest\n");
+        }
+    }
+
+
+    xlu_cfg_replace_string (config, "device_model_override",
+                            &b_info->device_model, 0);
+    if (!xlu_cfg_get_string (config, "device_model_version", &buf, 0)) {
+        if (!strcmp(buf, "qemu-xen-traditional")) {
+            b_info->device_model_version
+                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
+        } else if (!strcmp(buf, "qemu-xen")) {
+            b_info->device_model_version
+                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
+        } else if (!strcmp(buf, "none")) {
+            b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_NONE;
+        } else {
+            fprintf(stderr,
+                    "Unknown device_model_version \"%s\" specified\n", buf);
+            exit(1);
+        }
+    } else if (b_info->device_model)
+        fprintf(stderr, "WARNING: device model override given without specific DM version\n");
+    xlu_cfg_get_defbool (config, "device_model_stubdomain_override",
+                         &b_info->device_model_stubdomain, 0);
+
+    if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel",
+                             &buf, 0))
+        xlu_cfg_replace_string(config, "device_model_stubdomain_seclabel",
+                               &b_info->device_model_ssid_label, 0);
+
+    xlu_cfg_replace_string(config, "device_model_user",
+                           &b_info->device_model_user, 0);
+
+#define parse_extra_args(type)                                            \
+    e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \
+                                    &b_info->extra##type, 0);            \
+    if (e && e != ESRCH) {                                                \
+        fprintf(stderr,"xl: Unable to parse device_model_args"#type".\n");\
+        exit(-ERROR_FAIL);                                                \
+    }
+
+    /* parse extra args for qemu, common to both pv, hvm */
+    parse_extra_args();
+
+    /* parse extra args dedicated to pv */
+    parse_extra_args(_pv);
+
+    /* parse extra args dedicated to hvm */
+    parse_extra_args(_hvm);
+
+#undef parse_extra_args
+
+    /* If we've already got vfb=[] for PV guest then ignore top level
+     * VNC config. */
+    if (c_info->type == LIBXL_DOMAIN_TYPE_PV && !d_config->num_vfbs) {
+        long vnc_enabled = 0;
+
+        if (!xlu_cfg_get_long (config, "vnc", &l, 0))
+            vnc_enabled = l;
+
+        if (vnc_enabled) {
+            libxl_device_vfb *vfb;
+            libxl_device_vkb *vkb;
+
+            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
+                                    libxl_device_vfb_init);
+
+            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
+                                    libxl_device_vkb_init);
+
+            parse_top_level_vnc_options(config, &vfb->vnc);
+            parse_top_level_sdl_options(config, &vfb->sdl);
+            xlu_cfg_replace_string (config, "keymap", &vfb->keymap, 0);
+        }
+    } else {
+        parse_top_level_vnc_options(config, &b_info->u.hvm.vnc);
+        parse_top_level_sdl_options(config, &b_info->u.hvm.sdl);
+    }
+
+    if (c_info->type == LIBXL_DOMAIN_TYPE_HVM) {
+        if (!xlu_cfg_get_string (config, "vga", &buf, 0)) {
+            if (!strcmp(buf, "stdvga")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
+            } else if (!strcmp(buf, "cirrus")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
+            } else if (!strcmp(buf, "none")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE;
+            } else if (!strcmp(buf, "qxl")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL;
+            } else {
+                fprintf(stderr, "Unknown vga \"%s\" specified\n", buf);
+                exit(1);
+            }
+        } else if (!xlu_cfg_get_long(config, "stdvga", &l, 0))
+            b_info->u.hvm.vga.kind = l ? LIBXL_VGA_INTERFACE_TYPE_STD :
+                                         LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
+
+        if (!xlu_cfg_get_string(config, "hdtype", &buf, 0) &&
+            libxl_hdtype_from_string(buf, &b_info->u.hvm.hdtype)) {
+                fprintf(stderr, "ERROR: invalid value \"%s\" for \"hdtype\"\n",
+                    buf);
+                exit (1);
+        }
+
+        xlu_cfg_replace_string (config, "keymap", &b_info->u.hvm.keymap, 0);
+        xlu_cfg_get_defbool (config, "spice", &b_info->u.hvm.spice.enable, 0);
+        if (!xlu_cfg_get_long (config, "spiceport", &l, 0))
+            b_info->u.hvm.spice.port = l;
+        if (!xlu_cfg_get_long (config, "spicetls_port", &l, 0))
+            b_info->u.hvm.spice.tls_port = l;
+        xlu_cfg_replace_string (config, "spicehost",
+                                &b_info->u.hvm.spice.host, 0);
+        xlu_cfg_get_defbool(config, "spicedisable_ticketing",
+                            &b_info->u.hvm.spice.disable_ticketing, 0);
+        xlu_cfg_replace_string (config, "spicepasswd",
+                                &b_info->u.hvm.spice.passwd, 0);
+        xlu_cfg_get_defbool(config, "spiceagent_mouse",
+                            &b_info->u.hvm.spice.agent_mouse, 0);
+        xlu_cfg_get_defbool(config, "spicevdagent",
+                            &b_info->u.hvm.spice.vdagent, 0);
+        xlu_cfg_get_defbool(config, "spice_clipboard_sharing",
+                            &b_info->u.hvm.spice.clipboard_sharing, 0);
+        if (!xlu_cfg_get_long (config, "spiceusbredirection", &l, 0))
+            b_info->u.hvm.spice.usbredirection = l;
+        xlu_cfg_replace_string (config, "spice_image_compression",
+                                &b_info->u.hvm.spice.image_compression, 0);
+        xlu_cfg_replace_string (config, "spice_streaming_video",
+                                &b_info->u.hvm.spice.streaming_video, 0);
+        xlu_cfg_get_defbool(config, "nographic", &b_info->u.hvm.nographic, 0);
+        if (!xlu_cfg_get_long(config, "gfx_passthru", &l, 1)) {
+            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, l);
+        } else if (!xlu_cfg_get_string(config, "gfx_passthru", &buf, 0)) {
+            if (libxl_gfx_passthru_kind_from_string(buf,
+                                        &b_info->u.hvm.gfx_passthru_kind)) {
+                fprintf(stderr,
+                        "ERROR: invalid value \"%s\" for \"gfx_passthru\"\n",
+                        buf);
+                exit (1);
+            }
+            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, true);
+        }
+        switch (xlu_cfg_get_list_as_string_list(config, "serial",
+                                                &b_info->u.hvm.serial_list,
+                                                1))
+        {
+
+        case 0: break; /* Success */
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            /* If it's not a valid list, try reading it as an atom,
+             * falling through to an error if it fails */
+            if (!xlu_cfg_replace_string(config, "serial",
+                                        &b_info->u.hvm.serial, 0))
+                break;
+            /* FALLTHRU */
+        default:
+            fprintf(stderr,"xl: Unable to parse serial.\n");
+            exit(-ERROR_FAIL);
+        }
+        xlu_cfg_replace_string (config, "boot", &b_info->u.hvm.boot, 0);
+        xlu_cfg_get_defbool(config, "usb", &b_info->u.hvm.usb, 0);
+        if (!xlu_cfg_get_long (config, "usbversion", &l, 0))
+            b_info->u.hvm.usbversion = l;
+        switch (xlu_cfg_get_list_as_string_list(config, "usbdevice",
+                                                &b_info->u.hvm.usbdevice_list,
+                                                1))
+        {
+
+        case 0: break; /* Success */
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            /* If it's not a valid list, try reading it as an atom,
+             * falling through to an error if it fails */
+            if (!xlu_cfg_replace_string(config, "usbdevice",
+                                        &b_info->u.hvm.usbdevice, 0))
+                break;
+            /* FALLTHRU */
+        default:
+            fprintf(stderr,"xl: Unable to parse usbdevice.\n");
+            exit(-ERROR_FAIL);
+        }
+        xlu_cfg_replace_string (config, "soundhw", &b_info->u.hvm.soundhw, 0);
+        xlu_cfg_get_defbool(config, "xen_platform_pci",
+                            &b_info->u.hvm.xen_platform_pci, 0);
+
+        if(b_info->u.hvm.vnc.listen
+           && b_info->u.hvm.vnc.display
+           && strchr(b_info->u.hvm.vnc.listen, ':') != NULL) {
+            fprintf(stderr,
+                    "ERROR: Display specified both in vnclisten"
+                    " and vncdisplay!\n");
+            exit (1);
+
+        }
+
+        if (!xlu_cfg_get_string (config, "vendor_device", &buf, 0)) {
+            libxl_vendor_device d;
+
+            e = libxl_vendor_device_from_string(buf, &d);
+            if (e) {
+                fprintf(stderr,
+                        "xl: unknown vendor_device '%s'\n",
+                        buf);
+                exit(-ERROR_FAIL);
+            }
+
+            b_info->u.hvm.vendor_device = d;
+        }
+    }
+
+    if (!xlu_cfg_get_string (config, "gic_version", &buf, 1)) {
+        e = libxl_gic_version_from_string(buf, &b_info->arch_arm.gic_version);
+        if (e) {
+            fprintf(stderr,
+                    "Unknown gic_version \"%s\" specified\n", buf);
+            exit(-ERROR_FAIL);
+        }
+     }
+
+    xlu_cfg_destroy(config);
+}
+
+static void reload_domain_config(uint32_t domid,
+                                 libxl_domain_config *d_config)
+{
+    int rc;
+    uint8_t *t_data;
+    int ret, t_len;
+    libxl_domain_config d_config_new;
+
+    /* In case user has used "config-update" to store a new config
+     * file.
+     */
+    ret = libxl_userdata_retrieve(ctx, domid, "xl", &t_data, &t_len);
+    if (ret && errno != ENOENT) {
+        LOG("\"xl\" configuration found but failed to load\n");
+    }
+    if (t_len > 0) {
+        LOG("\"xl\" configuration found, using it\n");
+        libxl_domain_config_dispose(d_config);
+        libxl_domain_config_init(d_config);
+        parse_config_data("<updated>", (const char *)t_data,
+                          t_len, d_config);
+        free(t_data);
+        libxl_userdata_unlink(ctx, domid, "xl");
+        return;
+    }
+
+    libxl_domain_config_init(&d_config_new);
+    rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config_new);
+    if (rc) {
+        LOG("failed to retrieve guest configuration (rc=%d). "
+            "reusing old configuration", rc);
+        libxl_domain_config_dispose(&d_config_new);
+    } else {
+        libxl_domain_config_dispose(d_config);
+        /* Steal allocations */
+        memcpy(d_config, &d_config_new, sizeof(libxl_domain_config));
+    }
+}
+
+/* Can update r_domid if domain is destroyed */
+static domain_restart_type handle_domain_death(uint32_t *r_domid,
+                                               libxl_event *event,
+                                               libxl_domain_config *d_config)
+{
+    domain_restart_type restart = DOMAIN_RESTART_NONE;
+    libxl_action_on_shutdown action;
+
+    switch (event->u.domain_shutdown.shutdown_reason) {
+    case LIBXL_SHUTDOWN_REASON_POWEROFF:
+        action = d_config->on_poweroff;
+        break;
+    case LIBXL_SHUTDOWN_REASON_REBOOT:
+        action = d_config->on_reboot;
+        break;
+    case LIBXL_SHUTDOWN_REASON_SUSPEND:
+        LOG("Domain has suspended.");
+        return 0;
+    case LIBXL_SHUTDOWN_REASON_CRASH:
+        action = d_config->on_crash;
+        break;
+    case LIBXL_SHUTDOWN_REASON_WATCHDOG:
+        action = d_config->on_watchdog;
+        break;
+    case LIBXL_SHUTDOWN_REASON_SOFT_RESET:
+        action = d_config->on_soft_reset;
+        break;
+    default:
+        LOG("Unknown shutdown reason code %d. Destroying domain.",
+            event->u.domain_shutdown.shutdown_reason);
+        action = LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
+    }
+
+    LOG("Action for shutdown reason code %d is %s",
+        event->u.domain_shutdown.shutdown_reason,
+        action_on_shutdown_names[action]);
+
+    if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY || action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART) {
+        char *corefile;
+        int rc;
+
+        xasprintf(&corefile, XEN_DUMP_DIR "/%s", d_config->c_info.name);
+        LOG("dumping core to %s", corefile);
+        rc = libxl_domain_core_dump(ctx, *r_domid, corefile, NULL);
+        if (rc) LOG("core dump failed (rc=%d).", rc);
+        free(corefile);
+        /* No point crying over spilled milk, continue on failure. */
+
+        if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY)
+            action = LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
+        else
+            action = LIBXL_ACTION_ON_SHUTDOWN_RESTART;
+    }
+
+    switch (action) {
+    case LIBXL_ACTION_ON_SHUTDOWN_PRESERVE:
+        break;
+
+    case LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME:
+        reload_domain_config(*r_domid, d_config);
+        restart = DOMAIN_RESTART_RENAME;
+        break;
+
+    case LIBXL_ACTION_ON_SHUTDOWN_RESTART:
+        reload_domain_config(*r_domid, d_config);
+        restart = DOMAIN_RESTART_NORMAL;
+        /* fall-through */
+    case LIBXL_ACTION_ON_SHUTDOWN_DESTROY:
+        LOG("Domain %d needs to be cleaned up: destroying the domain",
+            *r_domid);
+        libxl_domain_destroy(ctx, *r_domid, 0);
+        *r_domid = INVALID_DOMID;
+        break;
+
+    case LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET:
+        reload_domain_config(*r_domid, d_config);
+        restart = DOMAIN_RESTART_SOFT_RESET;
+        break;
+
+    case LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY:
+    case LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART:
+        /* Already handled these above. */
+        abort();
+    }
+
+    return restart;
+}
+
+/* Preserve a copy of a domain under a new name. Updates *r_domid */
+static int preserve_domain(uint32_t *r_domid, libxl_event *event,
+                           libxl_domain_config *d_config)
+{
+    time_t now;
+    struct tm tm;
+    char strtime[24];
+
+    libxl_uuid new_uuid;
+
+    int rc;
+
+    now = time(NULL);
+    if (now == ((time_t) -1)) {
+        LOG("Failed to get current time for domain rename");
+        return 0;
+    }
+
+    tzset();
+    if (gmtime_r(&now, &tm) == NULL) {
+        LOG("Failed to convert time to UTC");
+        return 0;
+    }
+
+    if (!strftime(&strtime[0], sizeof(strtime), "-%Y%m%dT%H%MZ", &tm)) {
+        LOG("Failed to format time as a string");
+        return 0;
+    }
+
+    libxl_uuid_generate(&new_uuid);
+
+    LOG("Preserving domain %u %s with suffix%s",
+        *r_domid, d_config->c_info.name, strtime);
+    rc = libxl_domain_preserve(ctx, *r_domid, &d_config->c_info,
+                               strtime, new_uuid);
+
+    /*
+     * Although the domain still exists it is no longer the one we are
+     * concerned with.
+     */
+    *r_domid = INVALID_DOMID;
+
+    return rc == 0 ? 1 : 0;
+}
+
+/*
+ * Returns false if memory can't be freed, but also if we encounter errors.
+ * Returns true in case there is already, or we manage to free it, enough
+ * memory, but also if autoballoon is false.
+ */
+static bool freemem(uint32_t domid, libxl_domain_build_info *b_info)
+{
+    int rc, retries = 3;
+    uint64_t need_memkb, free_memkb;
+
+    if (!autoballoon)
+        return true;
+
+    rc = libxl_domain_need_memory(ctx, b_info, &need_memkb);
+    if (rc < 0)
+        return false;
+
+    do {
+        rc = libxl_get_free_memory(ctx, &free_memkb);
+        if (rc < 0)
+            return false;
+
+        if (free_memkb >= need_memkb)
+            return true;
+
+        rc = libxl_set_memory_target(ctx, 0, free_memkb - need_memkb, 1, 0);
+        if (rc < 0)
+            return false;
+
+        /* wait until dom0 reaches its target, as long as we are making
+         * progress */
+        rc = libxl_wait_for_memory_target(ctx, 0, 10);
+        if (rc < 0)
+            return false;
+
+        retries--;
+    } while (retries > 0);
+
+    return false;
+}
+
+static void autoconnect_console(libxl_ctx *ctx_ignored,
+                                libxl_event *ev, void *priv)
+{
+    uint32_t bldomid = ev->domid;
+    int notify_fd = *(int*)priv; /* write end of the notification pipe */
+
+    libxl_event_free(ctx, ev);
+
+    console_child_report(child_console);
+
+    pid_t pid = xl_fork(child_console, "console child");
+    if (pid)
+        return;
+
+    postfork();
+
+    sleep(1);
+    libxl_primary_console_exec(ctx, bldomid, notify_fd);
+    /* Do not return. xl continued in child process */
+    perror("xl: unable to exec console client");
+    _exit(1);
+}
+
+static int domain_wait_event(uint32_t domid, libxl_event **event_r)
+{
+    int ret;
+    for (;;) {
+        ret = libxl_event_wait(ctx, event_r, LIBXL_EVENTMASK_ALL, 0,0);
+        if (ret) {
+            LOG("Domain %u, failed to get event, quitting (rc=%d)", domid, ret);
+            return ret;
+        }
+        if ((*event_r)->domid != domid) {
+            char *evstr = libxl_event_to_json(ctx, *event_r);
+            LOG("INTERNAL PROBLEM - ignoring unexpected event for"
+                " domain %d (expected %d): event=%s",
+                (*event_r)->domid, domid, evstr);
+            free(evstr);
+            libxl_event_free(ctx, *event_r);
+            continue;
+        }
+        return ret;
+    }
+}
+
+static void evdisable_disk_ejects(libxl_evgen_disk_eject **diskws,
+                                 int num_disks)
+{
+    int i;
+
+    for (i = 0; i < num_disks; i++) {
+        if (diskws[i])
+            libxl_evdisable_disk_eject(ctx, diskws[i]);
+        diskws[i] = NULL;
+    }
+}
+
+static int create_domain(struct domain_create *dom_info)
+{
+    uint32_t domid = INVALID_DOMID;
+
+    libxl_domain_config d_config;
+
+    int debug = dom_info->debug;
+    int daemonize = dom_info->daemonize;
+    int monitor = dom_info->monitor;
+    int paused = dom_info->paused;
+    int vncautopass = dom_info->vncautopass;
+    const char *config_file = dom_info->config_file;
+    const char *extra_config = dom_info->extra_config;
+    const char *restore_file = dom_info->restore_file;
+    const char *config_source = NULL;
+    const char *restore_source = NULL;
+    int migrate_fd = dom_info->migrate_fd;
+    bool config_in_json;
+
+    int i;
+    int need_daemon = daemonize;
+    int ret, rc;
+    libxl_evgen_domain_death *deathw = NULL;
+    libxl_evgen_disk_eject **diskws = NULL; /* one per disk */
+    unsigned int num_diskws = 0;
+    void *config_data = 0;
+    int config_len = 0;
+    int restore_fd = -1;
+    int restore_fd_to_close = -1;
+    int send_back_fd = -1;
+    const libxl_asyncprogress_how *autoconnect_console_how;
+    int notify_pipe[2] = { -1, -1 };
+    struct save_file_header hdr;
+    uint32_t domid_soft_reset = INVALID_DOMID;
+
+    int restoring = (restore_file || (migrate_fd >= 0));
+
+    libxl_domain_config_init(&d_config);
+
+    if (restoring) {
+        uint8_t *optdata_begin = 0;
+        const uint8_t *optdata_here = 0;
+        union { uint32_t u32; char b[4]; } u32buf;
+        uint32_t badflags;
+
+        if (migrate_fd >= 0) {
+            restore_source = "<incoming migration stream>";
+            restore_fd = migrate_fd;
+            send_back_fd = dom_info->send_back_fd;
+        } else {
+            restore_source = restore_file;
+            restore_fd = open(restore_file, O_RDONLY);
+            if (restore_fd == -1) {
+                fprintf(stderr, "Can't open restore file: %s\n", strerror(errno));
+                return ERROR_INVAL;
+            }
+            restore_fd_to_close = restore_fd;
+            rc = libxl_fd_set_cloexec(ctx, restore_fd, 1);
+            if (rc) return rc;
+        }
+
+        CHK_ERRNOVAL(libxl_read_exactly(
+                         ctx, restore_fd, &hdr, sizeof(hdr),
+                         restore_source, "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_source, hdr.mandatory_flags, hdr.optional_flags,
+                hdr.optional_data_len);
+
+        badflags = hdr.mandatory_flags & ~XL_MANDATORY_FLAG_ALL;
+        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_ERRNOVAL(libxl_read_exactly(
+                             ctx, restore_fd, optdata_begin,
+                             hdr.optional_data_len, restore_source,
+                             "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%s\n",
+                    !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON)
+                    ? " in JSON format" : "");
+            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;
+        /* /dev/null represents special case (read config. from command line) */
+        if (!strcmp(config_file, "/dev/null")) {
+            config_len = 0;
+        } else {
+            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; }
+        }
+        if (!restoring && extra_config && strlen(extra_config)) {
+            if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
+                fprintf(stderr, "Failed to attach extra configuration\n");
+                return ERROR_FAIL;
+            }
+            /* allocate space for the extra config plus two EOLs plus \0 */
+            config_data = xrealloc(config_data, config_len
+                + strlen(extra_config) + 2 + 1);
+            config_len += sprintf(config_data + config_len, "\n%s\n",
+                extra_config);
+        }
+        config_source=config_file;
+        config_in_json = false;
+    } else {
+        if (!config_data) {
+            fprintf(stderr, "Config file not specified and"
+                    " none in save file\n");
+            return ERROR_INVAL;
+        }
+        config_source = "<saved>";
+        config_in_json = !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON);
+    }
+
+    if (!dom_info->quiet)
+        fprintf(stderr, "Parsing config from %s\n", config_source);
+
+    if (config_in_json) {
+        libxl_domain_config_from_json(ctx, &d_config,
+                                      (const char *)config_data);
+    } else {
+        parse_config_data(config_source, config_data, config_len, &d_config);
+    }
+
+    if (migrate_fd >= 0) {
+        if (d_config.c_info.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 = d_config.c_info.name;
+            d_config.c_info.name = 0; /* steals allocation from config */
+
+            xasprintf(&d_config.c_info.name, "%s--incoming", common_domname);
+            *dom_info->migration_domname_r = strdup(d_config.c_info.name);
+        }
+    }
+
+    if (debug || dom_info->dryrun) {
+        FILE *cfg_print_fh = (debug && !dom_info->dryrun) ? stderr : stdout;
+        if (default_output_format == OUTPUT_FORMAT_SXP) {
+            printf_info_sexp(-1, &d_config, cfg_print_fh);
+        } else {
+            char *json = libxl_domain_config_to_json(ctx, &d_config);
+            if (!json) {
+                fprintf(stderr,
+                        "Failed to convert domain configuration to JSON\n");
+                exit(1);
+            }
+            fputs(json, cfg_print_fh);
+            free(json);
+            flush_stream(cfg_print_fh);
+        }
+    }
+
+
+    ret = 0;
+    if (dom_info->dryrun)
+        goto out;
+
+start:
+    assert(domid == INVALID_DOMID);
+
+    rc = acquire_lock();
+    if (rc < 0)
+        goto error_out;
+
+    if (domid_soft_reset == INVALID_DOMID) {
+        if (!freemem(domid, &d_config.b_info)) {
+            fprintf(stderr, "failed to free memory for the domain\n");
+            ret = ERROR_FAIL;
+            goto error_out;
+        }
+    }
+
+    libxl_asyncprogress_how autoconnect_console_how_buf;
+    if ( dom_info->console_autoconnect ) {
+        if (libxl_pipe(ctx, notify_pipe)) {
+            ret = ERROR_FAIL;
+            goto error_out;
+        }
+        autoconnect_console_how_buf.callback = autoconnect_console;
+        autoconnect_console_how_buf.for_callback = &notify_pipe[1];
+        autoconnect_console_how = &autoconnect_console_how_buf;
+    }else{
+        autoconnect_console_how = 0;
+    }
+
+    if ( restoring ) {
+        libxl_domain_restore_params params;
+
+        libxl_domain_restore_params_init(&params);
+
+        params.checkpointed_stream = dom_info->checkpointed_stream;
+        params.stream_version =
+            (hdr.mandatory_flags & XL_MANDATORY_FLAG_STREAMv2) ? 2 : 1;
+        params.colo_proxy_script = dom_info->colo_proxy_script;
+
+        ret = libxl_domain_create_restore(ctx, &d_config,
+                                          &domid, restore_fd,
+                                          send_back_fd, &params,
+                                          0, autoconnect_console_how);
+
+        libxl_domain_restore_params_dispose(&params);
+
+        /*
+         * On subsequent reboot etc we should create the domain, not
+         * restore/migrate-receive it again.
+         */
+        restoring = 0;
+    } else if (domid_soft_reset != INVALID_DOMID) {
+        /* Do soft reset. */
+        ret = libxl_domain_soft_reset(ctx, &d_config, domid_soft_reset,
+                                      0, autoconnect_console_how);
+        domid = domid_soft_reset;
+        domid_soft_reset = INVALID_DOMID;
+    } else {
+        ret = libxl_domain_create_new(ctx, &d_config, &domid,
+                                      0, autoconnect_console_how);
+    }
+    if ( ret )
+        goto error_out;
+
+    release_lock();
+
+    if (restore_fd_to_close >= 0) {
+        if (close(restore_fd_to_close))
+            fprintf(stderr, "Failed to close restoring file, fd %d, errno %d\n",
+                    restore_fd_to_close, errno);
+        restore_fd_to_close = -1;
+    }
+
+    if (autoconnect_console_how) {
+        char buf[1];
+        int r;
+
+        /* Try to get notification from xenconsole. Just move on if
+         * error occurs -- it's only minor annoyance if console
+         * doesn't show up.
+         */
+        do {
+            r = read(notify_pipe[0], buf, 1);
+        } while (r == -1 && errno == EINTR);
+
+        if (r == -1)
+            fprintf(stderr,
+                    "Failed to get notification from xenconsole: %s\n",
+                    strerror(errno));
+        else if (r == 0)
+            fprintf(stderr, "Got EOF from xenconsole notification fd\n");
+        else if (r == 1 && buf[0] != 0x00)
+            fprintf(stderr, "Got unexpected response from xenconsole: %#x\n",
+                    buf[0]);
+
+        close(notify_pipe[0]);
+        close(notify_pipe[1]);
+        notify_pipe[0] = notify_pipe[1] = -1;
+    }
+
+    if (!paused)
+        libxl_domain_unpause(ctx, domid);
+
+    ret = domid; /* caller gets success in parent */
+    if (!daemonize && !monitor)
+        goto out;
+
+    if (dom_info->vnc)
+        autoconnect_vncviewer(domid, vncautopass);
+
+    if (need_daemon) {
+        char *name;
+
+        xasprintf(&name, "xl-%s", d_config.c_info.name);
+        ret = do_daemonize(name, NULL);
+        free(name);
+        if (ret) {
+            ret = (ret == 1) ? domid : ret;
+            goto out;
+        }
+        need_daemon = 0;
+    }
+    LOG("Waiting for domain %s (domid %u) to die [pid %ld]",
+        d_config.c_info.name, domid, (long)getpid());
+
+    ret = libxl_evenable_domain_death(ctx, domid, 0, &deathw);
+    if (ret) goto out;
+
+    if (!diskws) {
+        diskws = xmalloc(sizeof(*diskws) * d_config.num_disks);
+        for (i = 0; i < d_config.num_disks; i++)
+            diskws[i] = NULL;
+        num_diskws = d_config.num_disks;
+    }
+    for (i = 0; i < num_diskws; i++) {
+        if (d_config.disks[i].removable) {
+            ret = libxl_evenable_disk_eject(ctx, domid, d_config.disks[i].vdev,
+                                            0, &diskws[i]);
+            if (ret) goto out;
+        }
+    }
+    while (1) {
+        libxl_event *event;
+        ret = domain_wait_event(domid, &event);
+        if (ret) goto out;
+
+        switch (event->type) {
+
+        case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
+            LOG("Domain %u has shut down, reason code %d 0x%x", domid,
+                event->u.domain_shutdown.shutdown_reason,
+                event->u.domain_shutdown.shutdown_reason);
+            switch (handle_domain_death(&domid, event, &d_config)) {
+            case DOMAIN_RESTART_SOFT_RESET:
+                domid_soft_reset = domid;
+                domid = INVALID_DOMID;
+                /* fall through */
+            case DOMAIN_RESTART_RENAME:
+                if (domid_soft_reset == INVALID_DOMID &&
+                    !preserve_domain(&domid, event, &d_config)) {
+                    libxl_event_free(ctx, event);
+                    /* If we fail then exit leaving the old domain in place. */
+                    ret = -1;
+                    goto out;
+                }
+
+                /* Otherwise fall through and restart. */
+            case DOMAIN_RESTART_NORMAL:
+                libxl_event_free(ctx, event);
+                libxl_evdisable_domain_death(ctx, deathw);
+                deathw = NULL;
+                evdisable_disk_ejects(diskws, num_diskws);
+                free(diskws);
+                diskws = NULL;
+                num_diskws = 0;
+                /* discard any other events which may have been generated */
+                while (!(ret = libxl_event_check(ctx, &event,
+                                                 LIBXL_EVENTMASK_ALL, 0,0))) {
+                    libxl_event_free(ctx, event);
+                }
+                if (ret != ERROR_NOT_READY) {
+                    LOG("warning, libxl_event_check (cleanup) failed (rc=%d)",
+                        ret);
+                }
+
+                /*
+                 * Do not attempt to reconnect if we come round again due to a
+                 * guest reboot -- the stdin/out will be disconnected by then.
+                 */
+                dom_info->console_autoconnect = 0;
+
+                /* Some settings only make sense on first boot. */
+                paused = 0;
+                if (common_domname
+                    && strcmp(d_config.c_info.name, common_domname)) {
+                    d_config.c_info.name = strdup(common_domname);
+                }
+
+                /*
+                 * XXX FIXME: If this sleep is not there then domain
+                 * re-creation fails sometimes.
+                 */
+                LOG("Done. Rebooting now");
+                sleep(2);
+                goto start;
+
+            case DOMAIN_RESTART_NONE:
+                LOG("Done. Exiting now");
+                libxl_event_free(ctx, event);
+                ret = 0;
+                goto out;
+
+            default:
+                abort();
+            }
+
+        case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
+            LOG("Domain %u has been destroyed.", domid);
+            libxl_event_free(ctx, event);
+            ret = 0;
+            goto out;
+
+        case LIBXL_EVENT_TYPE_DISK_EJECT:
+            /* XXX what is this for? */
+            libxl_cdrom_insert(ctx, domid, &event->u.disk_eject.disk, NULL);
+            break;
+
+        default:;
+            char *evstr = libxl_event_to_json(ctx, event);
+            LOG("warning, got unexpected event type %d, event=%s",
+                event->type, evstr);
+            free(evstr);
+        }
+
+        libxl_event_free(ctx, event);
+    }
+
+error_out:
+    release_lock();
+    if (libxl_domid_valid_guest(domid)) {
+        libxl_domain_destroy(ctx, domid, 0);
+        domid = INVALID_DOMID;
+    }
+
+out:
+    if (restore_fd_to_close >= 0) {
+        if (close(restore_fd_to_close))
+            fprintf(stderr, "Failed to close restoring file, fd %d, errno %d\n",
+                    restore_fd_to_close, errno);
+        restore_fd_to_close = -1;
+    }
+
+    if (logfile != 2)
+        close(logfile);
+
+    libxl_domain_config_dispose(&d_config);
+
+    free(config_data);
+
+    console_child_report(child_console);
+
+    if (deathw)
+        libxl_evdisable_domain_death(ctx, deathw);
+    if (diskws) {
+        evdisable_disk_ejects(diskws, d_config.num_disks);
+        free(diskws);
+    }
+
+    /*
+     * If we have daemonized then do not return to the caller -- this has
+     * already happened in the parent.
+     */
+    if ( daemonize && !need_daemon )
+        exit(ret);
+
+    return ret;
+}
+
+void help(const char *command)
+{
+    int i;
+    struct cmd_spec *cmd;
+
+    if (!command || !strcmp(command, "help")) {
+        printf("Usage xl [-vfN] <subcommand> [args]\n\n");
+        printf("xl full list of subcommands:\n\n");
+        for (i = 0; i < cmdtable_len; i++) {
+            printf(" %-19s ", cmd_table[i].cmd_name);
+            if (strlen(cmd_table[i].cmd_name) > 19)
+                printf("\n %-19s ", "");
+            printf("%s\n", cmd_table[i].cmd_desc);
+        }
+    } else {
+        cmd = cmdtable_lookup(command);
+        if (cmd) {
+            printf("Usage: xl [-v%s%s] %s %s\n\n%s.\n\n",
+                   cmd->modifies ? "f" : "",
+                   cmd->can_dryrun ? "N" : "",
+                   cmd->cmd_name,
+                   cmd->cmd_usage,
+                   cmd->cmd_desc);
+            if (cmd->cmd_option)
+                printf("Options:\n\n%s\n", cmd->cmd_option);
+        }
+        else {
+            printf("command \"%s\" not implemented\n", command);
+        }
+    }
+}
+
+/* Returns -1 on failure; the amount of memory on success. */
+static int64_t parse_mem_size_kb(const char *mem)
+{
+    char *endptr;
+    int64_t kbytes;
+
+    kbytes = strtoll(mem, &endptr, 10);
+
+    if (strlen(endptr) > 1)
+        return -1;
+
+    switch (tolower((uint8_t)*endptr)) {
+    case 't':
+        kbytes <<= 10;
+        /* fallthrough */
+    case 'g':
+        kbytes <<= 10;
+        /* fallthrough */
+    case '\0':
+    case 'm':
+        kbytes <<= 10;
+        /* fallthrough */
+    case 'k':
+        break;
+    case 'b':
+        kbytes >>= 10;
+        break;
+    default:
+        return -1;
+    }
+
+    return kbytes;
+}
+
+/* Must be last in list */
+#define COMMON_LONG_OPTS {"help", 0, 0, 'h'}, \
+                         {0, 0, 0, 0}
+
+/*
+ * Callers should use SWITCH_FOREACH_OPT in preference to calling this
+ * directly.
+ */
+static int def_getopt(int argc, char * const argv[],
+                      const char *optstring,
+                      const struct option *longopts,
+                      const char* helpstr, int reqargs)
+{
+    int opt;
+    const struct option def_options[] = {
+        COMMON_LONG_OPTS
+    };
+
+    if (!longopts)
+        longopts = def_options;
+
+    opterr = 0;
+    while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) == '?') {
+        if (optopt == 'h') {
+            help(helpstr);
+            exit(0);
+        }
+        fprintf(stderr, "option `%c' not supported.\n", optopt);
+        exit(2);
+    }
+    if (opt == 'h') {
+        help(helpstr);
+        exit(0);
+    }
+    if (opt != -1)
+        return opt;
+
+    if (argc - optind <= reqargs - 1) {
+        fprintf(stderr, "'xl %s' requires at least %d argument%s.\n\n",
+                helpstr, reqargs, reqargs > 1 ? "s" : "");
+        help(helpstr);
+        exit(2);
+    }
+    return -1;
+}
+
+/*
+ * Wraps def_getopt into a convenient loop+switch to process all
+ * arguments. This macro is intended to be called from main_XXX().
+ *
+ *   SWITCH_FOREACH_OPT(int *opt, "OPTS",
+ *                      const struct option *longopts,
+ *                      const char *commandname,
+ *                      int num_opts_req) { ...
+ *
+ * opt:               pointer to an int variable, holds the current option
+ *                    during processing.
+ * OPTS:              short options, as per getopt_long(3)'s optstring argument.
+ *                    do not include "h"; will be provided automatically
+ * longopts:          long options, as per getopt_long(3)'s longopts argument.
+ *                    May be null.
+ * commandname:       name of this command, for usage string.
+ * num_required_opts: number of non-option command line parameters
+ *                    which are required.
+ *
+ * In addition the calling context is expected to contain variables
+ * "argc" and "argv" in the conventional C-style:
+ *   main(int argc, char **argv)
+ * manner.
+ *
+ * Callers should treat SWITCH_FOREACH_OPT as they would a switch
+ * statement over the value of `opt`. Each option given in `opts` (or
+ * `lopts`) should be handled by a case statement as if it were inside
+ * a switch statement.
+ *
+ * In addition to the options provided in opts the macro will handle
+ * the "help" option and enforce a minimum number of non-option
+ * command line pearameters as follows:
+ *  -- if the user passes a -h or --help option. help will be printed,
+ *     and the macro will cause the process to exit with code 0.
+ *  -- if the user does not provided `num_required_opts` non-option
+ *     arguments, the macro will cause the process to exit with code 2.
+ *
+ * Example:
+ *
+ * int main_foo(int argc, char **argv) {
+ *     int opt;
+ *
+ *     SWITCH_FOREACH_OPT(opt, "blah", NULL, "foo", 0) {
+ *      case 'b':
+ *          ... handle b option...
+ *          break;
+ *      case 'l':
+ *          ... handle l option ...
+ *          break;
+ *      case etc etc...
+ *      }
+ *      ... do something useful with the options ...
+ * }
+ */
+#define SWITCH_FOREACH_OPT(opt, opts, longopts,                         \
+                           commandname, num_required_opts)              \
+    while (((opt) = def_getopt(argc, argv, "h" opts, (longopts),          \
+                                (commandname), (num_required_opts))) != -1) \
+        switch (opt)
+
+static int set_memory_max(uint32_t domid, const char *mem)
+{
+    int64_t memorykb;
+
+    memorykb = parse_mem_size_kb(mem);
+    if (memorykb == -1) {
+        fprintf(stderr, "invalid memory size: %s\n", mem);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_domain_setmaxmem(ctx, domid, memorykb)) {
+        fprintf(stderr, "cannot set domid %u static max memory to : %s\n", domid, mem);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_memmax(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0;
+    char *mem;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "mem-max", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    mem = argv[optind + 1];
+
+    return set_memory_max(domid, mem);
+}
+
+static int set_memory_target(uint32_t domid, const char *mem)
+{
+    int64_t memorykb;
+
+    memorykb = parse_mem_size_kb(mem);
+    if (memorykb == -1)  {
+        fprintf(stderr, "invalid memory size: %s\n", mem);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_set_memory_target(ctx, domid, memorykb, 0, /* enforce */ 1)) {
+        fprintf(stderr, "cannot set domid %u dynamic max memory to : %s\n", domid, mem);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_memset(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0;
+    const char *mem;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "mem-set", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    mem = argv[optind + 1];
+
+    return set_memory_target(domid, mem);
+}
+
+static int cd_insert(uint32_t domid, const char *virtdev, char *phys)
+{
+    libxl_device_disk disk;
+    char *buf = NULL;
+    XLU_Config *config = 0;
+    struct stat b;
+    int r;
+
+    xasprintf(&buf, "vdev=%s,access=r,devtype=cdrom,target=%s",
+              virtdev, phys ? phys : "");
+
+    parse_disk_config(&config, buf, &disk);
+
+    /* ATM the existence of the backing file is not checked for qdisk
+     * in libxl_cdrom_insert() because RAW is used for remote
+     * protocols as well as plain files.  This will ideally be changed
+     * for 4.4, but this work-around fixes the problem of "cd-insert"
+     * returning success for non-existent files. */
+    if (disk.format != LIBXL_DISK_FORMAT_EMPTY
+        && stat(disk.pdev_path, &b)) {
+        fprintf(stderr, "Cannot stat file: %s\n",
+                disk.pdev_path);
+        r = 1;
+        goto out;
+    }
+
+    if (libxl_cdrom_insert(ctx, domid, &disk, NULL)) {
+        r = 1;
+        goto out;
+    }
+
+    r = 0;
+
+out:
+    libxl_device_disk_dispose(&disk);
+    free(buf);
+
+    return r;
+}
+
+int main_cd_eject(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0;
+    const char *virtdev;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cd-eject", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    virtdev = argv[optind + 1];
+
+    if (cd_insert(domid, virtdev, NULL))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_cd_insert(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0;
+    const char *virtdev;
+    char *file = NULL; /* modified by cd_insert tokenising it */
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cd-insert", 3) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    virtdev = argv[optind + 1];
+    file = argv[optind + 2];
+
+    if (cd_insert(domid, virtdev, file))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_usbctrl_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc = 0;
+    libxl_device_usbctrl usbctrl;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-attach", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind++]);
+
+    libxl_device_usbctrl_init(&usbctrl);
+
+    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
+        if (parse_usbctrl_config(&usbctrl, *argv))
+            return 1;
+    }
+
+    rc = libxl_device_usbctrl_add(ctx, domid, &usbctrl, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbctrl_add failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return rc;
+}
+
+int main_usbctrl_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, devid, rc;
+    libxl_device_usbctrl usbctrl;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    libxl_device_usbctrl_init(&usbctrl);
+    if (libxl_devid_to_device_usbctrl(ctx, domid, devid, &usbctrl)) {
+        fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_usbctrl_remove(ctx, domid, &usbctrl, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbctrl_remove failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return rc;
+
+}
+
+int main_usbdev_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc;
+    libxl_device_usbdev usbdev;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-attach", 2) {
+        /* No options */
+    }
+
+    libxl_device_usbdev_init(&usbdev);
+
+    domid = find_domain(argv[optind++]);
+
+    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
+        if (parse_usbdev_config(&usbdev, *argv))
+            return 1;
+    }
+
+    rc = libxl_device_usbdev_add(ctx, domid, &usbdev, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbdev_add failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbdev_dispose(&usbdev);
+    return rc;
+}
+
+int main_usbdev_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int ctrl, port;
+    int opt, rc = 1;
+    libxl_device_usbdev usbdev;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-detach", 3) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    ctrl = atoi(argv[optind+1]);
+    port = atoi(argv[optind+2]);
+
+    if (argc - optind > 3) {
+        fprintf(stderr, "Invalid arguments.\n");
+        return 1;
+    }
+
+    libxl_device_usbdev_init(&usbdev);
+    if (libxl_ctrlport_to_device_usbdev(ctx, domid, ctrl, port, &usbdev)) {
+        fprintf(stderr, "Unknown device at controller %d port %d.\n",
+                ctrl, port);
+        return 1;
+    }
+
+    rc = libxl_device_usbdev_remove(ctx, domid, &usbdev, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbdev_remove failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbdev_dispose(&usbdev);
+    return rc;
+}
+
+int main_usblist(int argc, char **argv)
+{
+    uint32_t domid;
+    libxl_device_usbctrl *usbctrls;
+    libxl_usbctrlinfo usbctrlinfo;
+    int numctrl, i, j, opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-list", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind++]);
+
+    if (argc > optind) {
+        fprintf(stderr, "Invalid arguments.\n");
+        exit(-1);
+    }
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
+    if (!usbctrls) {
+        return 0;
+    }
+
+    for (i = 0; i < numctrl; ++i) {
+        printf("%-6s %-12s %-3s %-5s %-7s %-5s\n",
+                "Devid", "Type", "BE", "state", "usb-ver", "ports");
+
+        libxl_usbctrlinfo_init(&usbctrlinfo);
+
+        if (!libxl_device_usbctrl_getinfo(ctx, domid,
+                                &usbctrls[i], &usbctrlinfo)) {
+            printf("%-6d %-12s %-3d %-5d %-7d %-5d\n",
+                    usbctrlinfo.devid,
+                    libxl_usbctrl_type_to_string(usbctrlinfo.type),
+                    usbctrlinfo.backend_id, usbctrlinfo.state,
+                    usbctrlinfo.version, usbctrlinfo.ports);
+
+            for (j = 1; j <= usbctrlinfo.ports; j++) {
+                libxl_device_usbdev usbdev;
+
+                libxl_device_usbdev_init(&usbdev);
+
+                printf("  Port %d:", j);
+
+                if (!libxl_ctrlport_to_device_usbdev(ctx, domid,
+                                                     usbctrlinfo.devid,
+                                                     j, &usbdev)) {
+                    printf(" Bus %03x Device %03x\n",
+                           usbdev.u.hostdev.hostbus,
+                           usbdev.u.hostdev.hostaddr);
+                } else {
+                    printf("\n");
+                }
+
+                libxl_device_usbdev_dispose(&usbdev);
+            }
+        }
+
+        libxl_usbctrlinfo_dispose(&usbctrlinfo);
+    }
+
+    libxl_device_usbctrl_list_free(usbctrls, numctrl);
+    return 0;
+}
+
+int main_console(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0, num = 0;
+    libxl_console_type type = 0;
+
+    SWITCH_FOREACH_OPT(opt, "n:t:", NULL, "console", 1) {
+    case 't':
+        if (!strcmp(optarg, "pv"))
+            type = LIBXL_CONSOLE_TYPE_PV;
+        else if (!strcmp(optarg, "serial"))
+            type = LIBXL_CONSOLE_TYPE_SERIAL;
+        else {
+            fprintf(stderr, "console type supported are: pv, serial\n");
+            return EXIT_FAILURE;
+        }
+        break;
+    case 'n':
+        num = atoi(optarg);
+        break;
+    }
+
+    domid = find_domain(argv[optind]);
+    if (!type)
+        libxl_primary_console_exec(ctx, domid, -1);
+    else
+        libxl_console_exec(ctx, domid, num, type, -1);
+    fprintf(stderr, "Unable to attach console\n");
+    return EXIT_FAILURE;
+}
+
+int main_vncviewer(int argc, char **argv)
+{
+    static const struct option opts[] = {
+        {"autopass", 0, 0, 'a'},
+        {"vncviewer-autopass", 0, 0, 'a'},
+        COMMON_LONG_OPTS
+    };
+    uint32_t domid;
+    int opt, autopass = 0;
+
+    SWITCH_FOREACH_OPT(opt, "a", opts, "vncviewer", 1) {
+    case 'a':
+        autopass = 1;
+        break;
+    }
+
+    domid = find_domain(argv[optind]);
+
+    if (vncviewer(domid, autopass))
+        return EXIT_FAILURE;
+    return EXIT_SUCCESS;
+}
+
+static void pcilist(uint32_t domid)
+{
+    libxl_device_pci *pcidevs;
+    int num, i;
+
+    pcidevs = libxl_device_pci_list(ctx, domid, &num);
+    if (pcidevs == NULL)
+        return;
+    printf("Vdev Device\n");
+    for (i = 0; i < num; i++) {
+        printf("%02x.%01x %04x:%02x:%02x.%01x\n",
+               (pcidevs[i].vdevfn >> 3) & 0x1f, pcidevs[i].vdevfn & 0x7,
+               pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
+        libxl_device_pci_dispose(&pcidevs[i]);
+    }
+    free(pcidevs);
+}
+
+int main_pcilist(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-list", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+
+    pcilist(domid);
+    return 0;
+}
+
+static int pcidetach(uint32_t domid, const char *bdf, int force)
+{
+    libxl_device_pci pcidev;
+    XLU_Config *config;
+    int r = 0;
+
+    libxl_device_pci_init(&pcidev);
+
+    config = xlu_cfg_init(stderr, "command line");
+    if (!config) { perror("xlu_cfg_inig"); exit(-1); }
+
+    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
+        fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
+        exit(2);
+    }
+    if (force) {
+        if (libxl_device_pci_destroy(ctx, domid, &pcidev, 0))
+            r = 1;
+    } else {
+        if (libxl_device_pci_remove(ctx, domid, &pcidev, 0))
+            r = 1;
+    }
+
+    libxl_device_pci_dispose(&pcidev);
+    xlu_cfg_destroy(config);
+
+    return r;
+}
+
+int main_pcidetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    int force = 0;
+    const char *bdf = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "f", NULL, "pci-detach", 2) {
+    case 'f':
+        force = 1;
+        break;
+    }
+
+    domid = find_domain(argv[optind]);
+    bdf = argv[optind + 1];
+
+    if (pcidetach(domid, bdf, force))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+static int pciattach(uint32_t domid, const char *bdf, const char *vs)
+{
+    libxl_device_pci pcidev;
+    XLU_Config *config;
+    int r = 0;
+
+    libxl_device_pci_init(&pcidev);
+
+    config = xlu_cfg_init(stderr, "command line");
+    if (!config) { perror("xlu_cfg_inig"); exit(-1); }
+
+    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
+        fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
+        exit(2);
+    }
+
+    if (libxl_device_pci_add(ctx, domid, &pcidev, 0))
+        r = 1;
+
+    libxl_device_pci_dispose(&pcidev);
+    xlu_cfg_destroy(config);
+
+    return r;
+}
+
+int main_pciattach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    const char *bdf = NULL, *vs = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-attach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    bdf = argv[optind + 1];
+
+    if (optind + 1 < argc)
+        vs = argv[optind + 2];
+
+    if (pciattach(domid, bdf, vs))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+static void pciassignable_list(void)
+{
+    libxl_device_pci *pcidevs;
+    int num, i;
+
+    pcidevs = libxl_device_pci_assignable_list(ctx, &num);
+
+    if ( pcidevs == NULL )
+        return;
+    for (i = 0; i < num; i++) {
+        printf("%04x:%02x:%02x.%01x\n",
+               pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
+        libxl_device_pci_dispose(&pcidevs[i]);
+    }
+    free(pcidevs);
+}
+
+int main_pciassignable_list(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-list", 0) {
+        /* No options */
+    }
+
+    pciassignable_list();
+    return 0;
+}
+
+static int pciassignable_add(const char *bdf, int rebind)
+{
+    libxl_device_pci pcidev;
+    XLU_Config *config;
+    int r = 0;
+
+    libxl_device_pci_init(&pcidev);
+
+    config = xlu_cfg_init(stderr, "command line");
+    if (!config) { perror("xlu_cfg_init"); exit(-1); }
+
+    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
+        fprintf(stderr, "pci-assignable-add: malformed BDF specification \"%s\"\n", bdf);
+        exit(2);
+    }
+
+    if (libxl_device_pci_assignable_add(ctx, &pcidev, rebind))
+        r = 1;
+
+    libxl_device_pci_dispose(&pcidev);
+    xlu_cfg_destroy(config);
+
+    return r;
+}
+
+int main_pciassignable_add(int argc, char **argv)
+{
+    int opt;
+    const char *bdf = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-add", 1) {
+        /* No options */
+    }
+
+    bdf = argv[optind];
+
+    if (pciassignable_add(bdf, 1))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+static int pciassignable_remove(const char *bdf, int rebind)
+{
+    libxl_device_pci pcidev;
+    XLU_Config *config;
+    int r = 0;
+
+    libxl_device_pci_init(&pcidev);
+
+    config = xlu_cfg_init(stderr, "command line");
+    if (!config) { perror("xlu_cfg_init"); exit(-1); }
+
+    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
+        fprintf(stderr, "pci-assignable-remove: malformed BDF specification \"%s\"\n", bdf);
+        exit(2);
+    }
+
+    if (libxl_device_pci_assignable_remove(ctx, &pcidev, rebind))
+        r = 1;
+
+    libxl_device_pci_dispose(&pcidev);
+    xlu_cfg_destroy(config);
+
+    return r;
+}
+
+int main_pciassignable_remove(int argc, char **argv)
+{
+    int opt;
+    const char *bdf = NULL;
+    int rebind = 0;
+
+    SWITCH_FOREACH_OPT(opt, "r", NULL, "pci-assignable-remove", 1) {
+    case 'r':
+        rebind=1;
+        break;
+    }
+
+    bdf = argv[optind];
+
+    if (pciassignable_remove(bdf, rebind))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+static void pause_domain(uint32_t domid)
+{
+    libxl_domain_pause(ctx, domid);
+}
+
+static void unpause_domain(uint32_t domid)
+{
+    libxl_domain_unpause(ctx, domid);
+}
+
+static void destroy_domain(uint32_t domid, int force)
+{
+    int rc;
+
+    if (domid == 0 && !force) {
+        fprintf(stderr, "Not destroying domain 0; use -f to force.\n"
+                        "This can only be done when using a disaggregated "
+                        "hardware domain and toolstack.\n\n");
+        exit(EXIT_FAILURE);
+    }
+    rc = libxl_domain_destroy(ctx, domid, 0);
+    if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n",rc); exit(EXIT_FAILURE); }
+}
+
+static void wait_for_domain_deaths(libxl_evgen_domain_death **deathws, int nr)
+{
+    int rc, count = 0;
+    LOG("Waiting for %d domains", nr);
+    while(1 && count < nr) {
+        libxl_event *event;
+        rc = libxl_event_wait(ctx, &event, LIBXL_EVENTMASK_ALL, 0,0);
+        if (rc) {
+            LOG("Failed to get event, quitting (rc=%d)", rc);
+            exit(EXIT_FAILURE);
+        }
+
+        switch (event->type) {
+        case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
+            LOG("Domain %d has been destroyed", event->domid);
+            libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
+            count++;
+            break;
+        case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
+            LOG("Domain %d has been shut down, reason code %d",
+                event->domid, event->u.domain_shutdown.shutdown_reason);
+            libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
+            count++;
+            break;
+        default:
+            LOG("Unexpected event type %d", event->type);
+            break;
+        }
+        libxl_event_free(ctx, event);
+    }
+}
+
+static void shutdown_domain(uint32_t domid,
+                            libxl_evgen_domain_death **deathw,
+                            libxl_ev_user for_user,
+                            int fallback_trigger)
+{
+    int rc;
+
+    fprintf(stderr, "Shutting down domain %u\n", domid);
+    rc=libxl_domain_shutdown(ctx, domid);
+    if (rc == ERROR_NOPARAVIRT) {
+        if (fallback_trigger) {
+            fprintf(stderr, "PV control interface not available:"
+                    " sending ACPI power button event.\n");
+            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_POWER, 0);
+        } else {
+            fprintf(stderr, "PV control interface not available:"
+                    " external graceful shutdown not possible.\n");
+            fprintf(stderr, "Use \"-F\" to fallback to ACPI power event.\n");
+        }
+    }
+
+    if (rc) {
+        fprintf(stderr,"shutdown failed (rc=%d)\n",rc);exit(EXIT_FAILURE);
+    }
+
+    if (deathw) {
+        rc = libxl_evenable_domain_death(ctx, domid, for_user, deathw);
+        if (rc) {
+            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
+            exit(EXIT_FAILURE);
+        }
+    }
+}
+
+static void reboot_domain(uint32_t domid, libxl_evgen_domain_death **deathw,
+                          libxl_ev_user for_user, int fallback_trigger)
+{
+    int rc;
+
+    fprintf(stderr, "Rebooting domain %u\n", domid);
+    rc=libxl_domain_reboot(ctx, domid);
+    if (rc == ERROR_NOPARAVIRT) {
+        if (fallback_trigger) {
+            fprintf(stderr, "PV control interface not available:"
+                    " sending ACPI reset button event.\n");
+            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_RESET, 0);
+        } else {
+            fprintf(stderr, "PV control interface not available:"
+                    " external graceful reboot not possible.\n");
+            fprintf(stderr, "Use \"-F\" to fallback to ACPI reset event.\n");
+        }
+    }
+    if (rc) {
+        fprintf(stderr,"reboot failed (rc=%d)\n",rc);exit(EXIT_FAILURE);
+    }
+
+    if (deathw) {
+        rc = libxl_evenable_domain_death(ctx, domid, for_user, deathw);
+        if (rc) {
+            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
+            exit(EXIT_FAILURE);
+        }
+    }
+}
+
+static void list_domains_details(const libxl_dominfo *info, int nb_domain)
+{
+    libxl_domain_config d_config;
+
+    int i, rc;
+
+    yajl_gen hand = NULL;
+    yajl_gen_status s;
+    const char *buf;
+    libxl_yajl_length yajl_len = 0;
+
+    if (default_output_format == OUTPUT_FORMAT_JSON) {
+        hand = libxl_yajl_gen_alloc(NULL);
+        if (!hand) {
+            fprintf(stderr, "unable to allocate JSON generator\n");
+            return;
+        }
+
+        s = yajl_gen_array_open(hand);
+        if (s != yajl_gen_status_ok)
+            goto out;
+    } else
+        s = yajl_gen_status_ok;
+
+    for (i = 0; i < nb_domain; i++) {
+        libxl_domain_config_init(&d_config);
+        rc = libxl_retrieve_domain_configuration(ctx, info[i].domid, &d_config);
+        if (rc)
+            continue;
+        if (default_output_format == OUTPUT_FORMAT_JSON)
+            s = printf_info_one_json(hand, info[i].domid, &d_config);
+        else
+            printf_info_sexp(info[i].domid, &d_config, stdout);
+        libxl_domain_config_dispose(&d_config);
+        if (s != yajl_gen_status_ok)
+            goto out;
+    }
+
+    if (default_output_format == OUTPUT_FORMAT_JSON) {
+        s = yajl_gen_array_close(hand);
+        if (s != yajl_gen_status_ok)
+            goto out;
+
+        s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &yajl_len);
+        if (s != yajl_gen_status_ok)
+            goto out;
+
+        puts(buf);
+    }
+
+out:
+    if (default_output_format == OUTPUT_FORMAT_JSON) {
+        yajl_gen_free(hand);
+        if (s != yajl_gen_status_ok)
+            fprintf(stderr,
+                    "unable to format domain config as JSON (YAJL:%d)\n", s);
+    }
+}
+
+static void print_bitmap(uint8_t *map, int maplen, FILE *stream)
+{
+    int i;
+    uint8_t pmap = 0, bitmask = 0;
+    int firstset = 0, state = 0;
+
+    for (i = 0; i < maplen; i++) {
+        if (i % 8 == 0) {
+            pmap = *map++;
+            bitmask = 1;
+        } else bitmask <<= 1;
+
+        switch (state) {
+        case 0:
+        case 2:
+            if ((pmap & bitmask) != 0) {
+                firstset = i;
+                state++;
+            }
+            continue;
+        case 1:
+        case 3:
+            if ((pmap & bitmask) == 0) {
+                fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
+                if (i - 1 > firstset)
+                    fprintf(stream, "-%d", i - 1);
+                state = 2;
+            }
+            continue;
+        }
+    }
+    switch (state) {
+        case 0:
+            fprintf(stream, "none");
+            break;
+        case 2:
+            break;
+        case 1:
+            if (firstset == 0) {
+                fprintf(stream, "all");
+                break;
+            }
+        case 3:
+            fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
+            if (i - 1 > firstset)
+                fprintf(stream, "-%d", i - 1);
+            break;
+    }
+}
+
+static void list_domains(bool verbose, bool context, bool claim, bool numa,
+                         bool cpupool, const libxl_dominfo *info, int nb_domain)
+{
+    int i;
+    static const char shutdown_reason_letters[]= "-rscwS";
+    libxl_bitmap nodemap;
+    libxl_physinfo physinfo;
+
+    libxl_bitmap_init(&nodemap);
+    libxl_physinfo_init(&physinfo);
+
+    printf("Name                                        ID   Mem VCPUs\tState\tTime(s)");
+    if (verbose) printf("   UUID                            Reason-Code\tSecurity Label");
+    if (context && !verbose) printf("   Security Label");
+    if (claim) printf("  Claimed");
+    if (cpupool) printf("         Cpupool");
+    if (numa) {
+        if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
+            fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
+            exit(EXIT_FAILURE);
+        }
+        if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+            fprintf(stderr, "libxl_physinfo failed.\n");
+            libxl_bitmap_dispose(&nodemap);
+            exit(EXIT_FAILURE);
+        }
+
+        printf(" NODE Affinity");
+    }
+    printf("\n");
+    for (i = 0; i < nb_domain; i++) {
+        char *domname;
+        libxl_shutdown_reason shutdown_reason;
+        domname = libxl_domid_to_name(ctx, info[i].domid);
+        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
+        printf("%-40s %5d %5lu %5d     %c%c%c%c%c%c  %8.1f",
+                domname,
+                info[i].domid,
+                (unsigned long) ((info[i].current_memkb +
+                    info[i].outstanding_memkb)/ 1024),
+                info[i].vcpu_online,
+                info[i].running ? 'r' : '-',
+                info[i].blocked ? 'b' : '-',
+                info[i].paused ? 'p' : '-',
+                info[i].shutdown ? 's' : '-',
+                (shutdown_reason >= 0 &&
+                 shutdown_reason < sizeof(shutdown_reason_letters)-1
+                 ? shutdown_reason_letters[shutdown_reason] : '?'),
+                info[i].dying ? 'd' : '-',
+                ((float)info[i].cpu_time / 1e9));
+        free(domname);
+        if (verbose) {
+            printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
+            if (info[i].shutdown) printf(" %8x", shutdown_reason);
+            else printf(" %8s", "-");
+        }
+        if (claim)
+            printf(" %5lu", (unsigned long)info[i].outstanding_memkb / 1024);
+        if (verbose || context)
+            printf(" %16s", info[i].ssid_label ? : "-");
+        if (cpupool) {
+            char *poolname = libxl_cpupoolid_to_name(ctx, info[i].cpupool);
+            printf("%16s", poolname);
+            free(poolname);
+        }
+        if (numa) {
+            libxl_domain_get_nodeaffinity(ctx, info[i].domid, &nodemap);
+
+            putchar(' ');
+            print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
+        }
+        putchar('\n');
+    }
+
+    libxl_bitmap_dispose(&nodemap);
+    libxl_physinfo_dispose(&physinfo);
+}
+
+static void list_vm(void)
+{
+    libxl_vminfo *info;
+    char *domname;
+    int nb_vm, i;
+
+    info = libxl_list_vm(ctx, &nb_vm);
+
+    if (!info) {
+        fprintf(stderr, "libxl_list_vm failed.\n");
+        exit(EXIT_FAILURE);
+    }
+    printf("UUID                                  ID    name\n");
+    for (i = 0; i < nb_vm; i++) {
+        domname = libxl_domid_to_name(ctx, info[i].domid);
+        printf(LIBXL_UUID_FMT "  %d    %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
+            info[i].domid, domname);
+        free(domname);
+    }
+    libxl_vminfo_list_free(info, nb_vm);
+}
+
+static void core_dump_domain(uint32_t domid, const char *filename)
+{
+    int rc;
+
+    rc=libxl_domain_core_dump(ctx, domid, filename, NULL);
+    if (rc) { fprintf(stderr,"core dump failed (rc=%d)\n",rc);exit(EXIT_FAILURE); }
+}
+
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+static void save_domain_core_begin(uint32_t domid,
+                                   const char *override_config_file,
+                                   uint8_t **config_data_r,
+                                   int *config_len_r)
+{
+    int rc;
+    libxl_domain_config d_config;
+    char *config_c = 0;
+
+    /* configuration file in optional data: */
+
+    libxl_domain_config_init(&d_config);
+
+    if (override_config_file) {
+        void *config_v = 0;
+        rc = libxl_read_file_contents(ctx, override_config_file,
+                                      &config_v, config_len_r);
+        if (rc) {
+            fprintf(stderr, "unable to read overridden config file\n");
+            exit(EXIT_FAILURE);
+        }
+        parse_config_data(override_config_file, config_v, *config_len_r,
+                          &d_config);
+        free(config_v);
+    } else {
+        rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config);
+        if (rc) {
+            fprintf(stderr, "unable to retrieve domain configuration\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    config_c = libxl_domain_config_to_json(ctx, &d_config);
+    if (!config_c) {
+        fprintf(stderr, "unable to convert config file to JSON\n");
+        exit(EXIT_FAILURE);
+    }
+    *config_data_r = (uint8_t *)config_c;
+    *config_len_r = strlen(config_c) + 1; /* including trailing '\0' */
+
+    libxl_domain_config_dispose(&d_config);
+}
+
+static void save_domain_core_writeconfig(int fd, const char *source,
+                                  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;
+    hdr.mandatory_flags = XL_MANDATORY_FLAG_STREAMv2;
+
+    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);
+    if (config_len)
+        hdr.mandatory_flags |= XL_MANDATORY_FLAG_JSON;
+
+    /* that's the optional data */
+
+    CHK_ERRNOVAL(libxl_write_exactly(
+                     ctx, fd, &hdr, sizeof(hdr), source, "header"));
+    CHK_ERRNOVAL(libxl_write_exactly(
+                     ctx, fd, optdata_begin, hdr.optional_data_len,
+                     source, "header"));
+
+    free(optdata_begin);
+
+    fprintf(stderr, "Saving to %s new xl format (info"
+            " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
+            source, hdr.mandatory_flags, hdr.optional_flags,
+            hdr.optional_data_len);
+}
+
+static int save_domain(uint32_t domid, const char *filename, int checkpoint,
+                            int leavepaused, const char *override_config_file)
+{
+    int fd;
+    uint8_t *config_data;
+    int config_len;
+
+    save_domain_core_begin(domid, 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(EXIT_FAILURE);
+    }
+
+    save_domain_core_writeconfig(fd, filename, config_data, config_len);
+
+    int rc = libxl_domain_suspend(ctx, domid, fd, 0, NULL);
+    close(fd);
+
+    if (rc < 0) {
+        fprintf(stderr, "Failed to save domain, resuming domain\n");
+        libxl_domain_resume(ctx, domid, 1, 0);
+    }
+    else if (leavepaused || checkpoint) {
+        if (leavepaused)
+            libxl_domain_pause(ctx, domid);
+        libxl_domain_resume(ctx, domid, 1, 0);
+    }
+    else
+        libxl_domain_destroy(ctx, domid, 0);
+
+    exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+static pid_t create_migration_child(const char *rune, int *send_fd,
+                                        int *recv_fd)
+{
+    int sendpipe[2], recvpipe[2];
+    pid_t child;
+
+    if (!rune || !send_fd || !recv_fd)
+        return -1;
+
+    MUST( libxl_pipe(ctx, sendpipe) );
+    MUST( libxl_pipe(ctx, recvpipe) );
+
+    child = xl_fork(child_migration, "migration transport process");
+
+    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(EXIT_FAILURE);
+    }
+
+    close(sendpipe[0]);
+    close(recvpipe[1]);
+    *send_fd = sendpipe[1];
+    *recv_fd = recvpipe[0];
+
+    /* if receiver dies, we get an error and can clean up
+       rather than just dying */
+    signal(SIGPIPE, SIG_IGN);
+
+    return child;
+}
+
+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 1;
+
+    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 1;
+    }
+    return 0;
+}
+
+static void migration_child_report(int recv_fd) {
+    pid_t child;
+    int status, sr;
+    struct timeval now, waituntil, timeout;
+    static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
+
+    if (!xl_child_pid(child_migration)) return;
+
+    CHK_SYSCALL(gettimeofday(&waituntil, 0));
+    waituntil.tv_sec += 2;
+
+    for (;;) {
+        pid_t migration_child = xl_child_pid(child_migration);
+        child = xl_waitpid(child_migration, &status, WNOHANG);
+
+        if (child == migration_child) {
+            if (status)
+                xl_report_child_exitstatus(XTL_INFO, child_migration,
+                                           migration_child, status);
+            break;
+        }
+        if (child == -1) {
+            fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
+                    (long)migration_child, strerror(errno));
+            break;
+        }
+        assert(child == 0);
+
+        CHK_SYSCALL(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;
+            }
+        }
+    }
+}
+
+static void migrate_do_preamble(int send_fd, int recv_fd, pid_t child,
+                                uint8_t *config_data, int config_len,
+                                const char *rune)
+{
+    int rc = 0;
+
+    if (send_fd < 0 || recv_fd < 0) {
+        fprintf(stderr, "migrate_do_preamble: invalid file descriptors\n");
+        exit(EXIT_FAILURE);
+    }
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
+                                   sizeof(migrate_receiver_banner)-1,
+                                   "banner", rune);
+    if (rc) {
+        close(send_fd);
+        migration_child_report(recv_fd);
+        exit(EXIT_FAILURE);
+    }
+
+    save_domain_core_writeconfig(send_fd, "migration stream",
+                                 config_data, config_len);
+
+}
+
+static void migrate_domain(uint32_t domid, const char *rune, int debug,
+                           const char *override_config_file)
+{
+    pid_t child = -1;
+    int rc;
+    int send_fd = -1, recv_fd = -1;
+    char *away_domname;
+    char rc_buf;
+    uint8_t *config_data;
+    int config_len, flags = LIBXL_SUSPEND_LIVE;
+
+    save_domain_core_begin(domid, override_config_file,
+                           &config_data, &config_len);
+
+    if (!config_len) {
+        fprintf(stderr, "No config file stored for running domain and "
+                "none supplied - cannot migrate.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    child = create_migration_child(rune, &send_fd, &recv_fd);
+
+    migrate_do_preamble(send_fd, recv_fd, child, config_data, config_len,
+                        rune);
+
+    xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
+
+    if (debug)
+        flags |= LIBXL_SUSPEND_DEBUG;
+    rc = libxl_domain_suspend(ctx, domid, send_fd, flags, NULL);
+    if (rc) {
+        fprintf(stderr, "migration sender: libxl_domain_suspend failed"
+                " (rc=%d)\n", rc);
+        if (rc == ERROR_GUEST_TIMEDOUT)
+            goto failed_suspend;
+        else
+            goto failed_resume;
+    }
+
+    //fprintf(stderr, "migration sender: Transfer complete.\n");
+    // Should only be printed when debugging as it's a bit messy with
+    // progress indication.
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
+                                   sizeof(migrate_receiver_ready),
+                                   "ready message", rune);
+    if (rc) goto failed_resume;
+
+    xtl_stdiostream_adjust_flags(logger, 0, XTL_STDIOSTREAM_HIDE_PROGRESS);
+
+    /* 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) {
+        xasprintf(&away_domname, "%s--migratedaway", common_domname);
+        rc = libxl_domain_rename(ctx, domid, common_domname, away_domname);
+        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);
+        }
+        rc = libxl_domain_resume(ctx, domid, 1, 0);
+        if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
+
+        fprintf(stderr, "Migration failed due to problems at target.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    fprintf(stderr, "migration sender: Target reports successful startup.\n");
+    libxl_domain_destroy(ctx, domid, 0); /* bang! */
+    fprintf(stderr, "Migration successful.\n");
+    exit(EXIT_SUCCESS);
+
+ failed_suspend:
+    close(send_fd);
+    migration_child_report(recv_fd);
+    fprintf(stderr, "Migration failed, failed to suspend at sender.\n");
+    exit(EXIT_FAILURE);
+
+ failed_resume:
+    close(send_fd);
+    migration_child_report(recv_fd);
+    fprintf(stderr, "Migration failed, resuming at sender.\n");
+    libxl_domain_resume(ctx, domid, 1, 0);
+    exit(EXIT_FAILURE);
+
+ 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(recv_fd);
+    exit(EXIT_FAILURE);
+}
+
+static void migrate_receive(int debug, int daemonize, int monitor,
+                            int pause_after_migration,
+                            int send_fd, int recv_fd,
+                            libxl_checkpointed_stream checkpointed,
+                            char *colo_proxy_script)
+{
+    uint32_t domid;
+    int rc, rc2;
+    char rc_buf;
+    char *migration_domname;
+    struct domain_create dom_info;
+
+    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_ERRNOVAL(libxl_write_exactly(
+                     ctx, send_fd, migrate_receiver_banner,
+                     sizeof(migrate_receiver_banner)-1,
+                     "migration ack stream", "banner") );
+
+    memset(&dom_info, 0, sizeof(dom_info));
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.monitor = monitor;
+    dom_info.paused = 1;
+    dom_info.migrate_fd = recv_fd;
+    dom_info.send_back_fd = send_fd;
+    dom_info.migration_domname_r = &migration_domname;
+    dom_info.checkpointed_stream = checkpointed;
+    dom_info.colo_proxy_script = colo_proxy_script;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0) {
+        fprintf(stderr, "migration target: Domain creation failed"
+                " (code %d).\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    domid = rc;
+
+    switch (checkpointed) {
+    case LIBXL_CHECKPOINTED_STREAM_REMUS:
+    case LIBXL_CHECKPOINTED_STREAM_COLO:
+    {
+        const char *ha = checkpointed == LIBXL_CHECKPOINTED_STREAM_COLO ?
+                         "COLO" : "Remus";
+        /* If we are here, it means that the sender (primary) has crashed.
+         * TODO: Split-Brain Check.
+         */
+        fprintf(stderr, "migration target: %s Failover for domain %u\n",
+                ha, domid);
+
+        /*
+         * If domain renaming fails, lets just continue (as we need the domain
+         * to be up & dom names may not matter much, as long as its reachable
+         * over network).
+         *
+         * If domain unpausing fails, destroy domain ? Or is it better to have
+         * a consistent copy of the domain (memory, cpu state, disk)
+         * on atleast one physical host ? Right now, lets just leave the domain
+         * as is and let the Administrator decide (or troubleshoot).
+         */
+        if (migration_domname) {
+            rc = libxl_domain_rename(ctx, domid, migration_domname,
+                                     common_domname);
+            if (rc)
+                fprintf(stderr, "migration target (%s): "
+                        "Failed to rename domain from %s to %s:%d\n",
+                        ha, migration_domname, common_domname, rc);
+        }
+
+        if (checkpointed == LIBXL_CHECKPOINTED_STREAM_COLO)
+            /* The guest is running after failover in COLO mode */
+            exit(rc ? -ERROR_FAIL: 0);
+
+        rc = libxl_domain_unpause(ctx, domid);
+        if (rc)
+            fprintf(stderr, "migration target (%s): "
+                    "Failed to unpause domain %s (id: %u):%d\n",
+                    ha, common_domname, domid, rc);
+
+        exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
+    }
+    default:
+        /* do nothing */
+        break;
+    }
+
+    fprintf(stderr, "migration target: Transfer complete,"
+            " requesting permission to start domain.\n");
+
+    rc = libxl_write_exactly(ctx, send_fd,
+                             migrate_receiver_ready,
+                             sizeof(migrate_receiver_ready),
+                             "migration ack stream", "ready message");
+    if (rc) exit(EXIT_FAILURE);
+
+    rc = migrate_read_fixedmessage(recv_fd, 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);
+        if (rc) goto perhaps_destroy_notify_rc;
+    }
+
+    if (!pause_after_migration) {
+        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, send_fd,
+                              migrate_report, sizeof(migrate_report),
+                              "migration ack stream",
+                              "success/failure report");
+    if (rc2) exit(EXIT_FAILURE);
+
+    rc_buf = -rc;
+    assert(!!rc_buf == !!rc);
+    rc2 = libxl_write_exactly(ctx, send_fd, &rc_buf, 1,
+                              "migration ack stream",
+                              "success/failure code");
+    if (rc2) exit(EXIT_FAILURE);
+
+    if (rc) {
+        fprintf(stderr, "migration target: Failure, destroying our copy.\n");
+
+        rc2 = libxl_domain_destroy(ctx, domid, 0);
+        if (rc2) {
+            fprintf(stderr, "migration target: Failed to destroy our copy"
+                    " (code %d).\n", rc2);
+            exit(EXIT_FAILURE);
+        }
+
+        fprintf(stderr, "migration target: Cleanup OK, granting sender"
+                " permission to resume.\n");
+
+        rc2 = libxl_write_exactly(ctx, send_fd,
+                                  migrate_permission_to_go,
+                                  sizeof(migrate_permission_to_go),
+                                  "migration ack stream",
+                                  "permission to sender to have domain back");
+        if (rc2) exit(EXIT_FAILURE);
+    }
+
+    exit(EXIT_SUCCESS);
+}
+
+int main_restore(int argc, char **argv)
+{
+    const char *checkpoint_file = NULL;
+    const char *config_file = NULL;
+    struct domain_create dom_info;
+    int paused = 0, debug = 0, daemonize = 1, monitor = 1,
+        console_autoconnect = 0, vnc = 0, vncautopass = 0;
+    int opt, rc;
+    static struct option opts[] = {
+        {"vncviewer", 0, 0, 'V'},
+        {"vncviewer-autopass", 0, 0, 'A'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "FcpdeVA", opts, "restore", 1) {
+    case 'c':
+        console_autoconnect = 1;
+        break;
+    case 'p':
+        paused = 1;
+        break;
+    case 'd':
+        debug = 1;
+        break;
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'e':
+        daemonize = 0;
+        monitor = 0;
+        break;
+    case 'V':
+        vnc = 1;
+        break;
+    case 'A':
+        vnc = vncautopass = 1;
+        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");
+        return EXIT_FAILURE;
+    }
+
+    memset(&dom_info, 0, sizeof(dom_info));
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.monitor = monitor;
+    dom_info.paused = paused;
+    dom_info.config_file = config_file;
+    dom_info.restore_file = checkpoint_file;
+    dom_info.migrate_fd = -1;
+    dom_info.send_back_fd = -1;
+    dom_info.vnc = vnc;
+    dom_info.vncautopass = vncautopass;
+    dom_info.console_autoconnect = console_autoconnect;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_migrate_receive(int argc, char **argv)
+{
+    int debug = 0, daemonize = 1, monitor = 1, pause_after_migration = 0;
+    libxl_checkpointed_stream checkpointed = LIBXL_CHECKPOINTED_STREAM_NONE;
+    int opt;
+    char *script = NULL;
+    static struct option opts[] = {
+        {"colo", 0, 0, 0x100},
+        /* It is a shame that the management code for disk is not here. */
+        {"coloft-script", 1, 0, 0x200},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "Fedrp", opts, "migrate-receive", 0) {
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'e':
+        daemonize = 0;
+        monitor = 0;
+        break;
+    case 'd':
+        debug = 1;
+        break;
+    case 'r':
+        checkpointed = LIBXL_CHECKPOINTED_STREAM_REMUS;
+        break;
+    case 0x100:
+        checkpointed = LIBXL_CHECKPOINTED_STREAM_COLO;
+        break;
+    case 0x200:
+        script = optarg;
+        break;
+    case 'p':
+        pause_after_migration = 1;
+        break;
+    }
+
+    if (argc-optind != 0) {
+        help("migrate-receive");
+        return EXIT_FAILURE;
+    }
+    migrate_receive(debug, daemonize, monitor, pause_after_migration,
+                    STDOUT_FILENO, STDIN_FILENO,
+                    checkpointed, script);
+
+    return EXIT_SUCCESS;
+}
+
+int main_save(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *filename;
+    const char *config_filename = NULL;
+    int checkpoint = 0;
+    int leavepaused = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "cp", NULL, "save", 2) {
+    case 'c':
+        checkpoint = 1;
+        break;
+    case 'p':
+        leavepaused = 1;
+        break;
+    }
+
+    if (argc-optind > 3) {
+        help("save");
+        return EXIT_FAILURE;
+    }
+
+    domid = find_domain(argv[optind]);
+    filename = argv[optind + 1];
+    if ( argc - optind >= 3 )
+        config_filename = argv[optind + 2];
+
+    save_domain(domid, filename, checkpoint, leavepaused, config_filename);
+    return EXIT_SUCCESS;
+}
+
+int main_migrate(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *config_filename = NULL;
+    const char *ssh_command = "ssh";
+    char *rune = NULL;
+    char *host;
+    int opt, daemonize = 1, monitor = 1, debug = 0, pause_after_migration = 0;
+    static struct option opts[] = {
+        {"debug", 0, 0, 0x100},
+        {"live", 0, 0, 0x200},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "FC:s:ep", opts, "migrate", 2) {
+    case 'C':
+        config_filename = optarg;
+        break;
+    case 's':
+        ssh_command = optarg;
+        break;
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'e':
+        daemonize = 0;
+        monitor = 0;
+        break;
+    case 'p':
+        pause_after_migration = 1;
+        break;
+    case 0x100: /* --debug */
+        debug = 1;
+        break;
+    case 0x200: /* --live */
+        /* ignored for compatibility with xm */
+        break;
+    }
+
+    domid = find_domain(argv[optind]);
+    host = argv[optind + 1];
+
+    bool pass_tty_arg = progress_use_cr || (isatty(2) > 0);
+
+    if (!ssh_command[0]) {
+        rune= host;
+    } else {
+        char verbose_buf[minmsglevel_default+3];
+        int verbose_len;
+        verbose_buf[0] = ' ';
+        verbose_buf[1] = '-';
+        memset(verbose_buf+2, 'v', minmsglevel_default);
+        verbose_buf[sizeof(verbose_buf)-1] = 0;
+        if (minmsglevel == minmsglevel_default) {
+            verbose_len = 0;
+        } else {
+            verbose_len = (minmsglevel_default - minmsglevel) + 2;
+        }
+        xasprintf(&rune, "exec %s %s xl%s%.*s migrate-receive%s%s%s",
+                  ssh_command, host,
+                  pass_tty_arg ? " -t" : "",
+                  verbose_len, verbose_buf,
+                  daemonize ? "" : " -e",
+                  debug ? " -d" : "",
+                  pause_after_migration ? " -p" : "");
+    }
+
+    migrate_domain(domid, rune, debug, config_filename);
+    return EXIT_SUCCESS;
+}
+#endif
+
+int main_dump_core(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "dump-core", 2) {
+        /* No options */
+    }
+
+    core_dump_domain(find_domain(argv[optind]), argv[optind + 1]);
+    return EXIT_SUCCESS;
+}
+
+int main_pause(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pause", 1) {
+        /* No options */
+    }
+
+    pause_domain(find_domain(argv[optind]));
+
+    return EXIT_SUCCESS;
+}
+
+int main_unpause(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "unpause", 1) {
+        /* No options */
+    }
+
+    unpause_domain(find_domain(argv[optind]));
+
+    return EXIT_SUCCESS;
+}
+
+int main_destroy(int argc, char **argv)
+{
+    int opt;
+    int force = 0;
+
+    SWITCH_FOREACH_OPT(opt, "f", NULL, "destroy", 1) {
+    case 'f':
+        force = 1;
+        break;
+    }
+
+    destroy_domain(find_domain(argv[optind]), force);
+    return EXIT_SUCCESS;
+}
+
+static int main_shutdown_or_reboot(int do_reboot, int argc, char **argv)
+{
+    const char *what = do_reboot ? "reboot" : "shutdown";
+    void (*fn)(uint32_t domid,
+               libxl_evgen_domain_death **, libxl_ev_user, int) =
+        do_reboot ? &reboot_domain : &shutdown_domain;
+    int opt, i, nb_domain;
+    int wait_for_it = 0, all = 0, nrdeathws = 0;
+    int fallback_trigger = 0;
+    static struct option opts[] = {
+        {"all", 0, 0, 'a'},
+        {"wait", 0, 0, 'w'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "awF", opts, what, 0) {
+    case 'a':
+        all = 1;
+        break;
+    case 'w':
+        wait_for_it = 1;
+        break;
+    case 'F':
+        fallback_trigger = 1;
+        break;
+    }
+
+    if (!argv[optind] && !all) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        return EXIT_FAILURE;
+    }
+
+    if (all) {
+        libxl_dominfo *dominfo;
+        libxl_evgen_domain_death **deathws = NULL;
+        if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            return EXIT_FAILURE;
+        }
+
+        if (wait_for_it)
+            deathws = calloc(nb_domain, sizeof(*deathws));
+
+        for (i = 0; i<nb_domain; i++) {
+            if (dominfo[i].domid == 0 || dominfo[i].never_stop)
+                continue;
+            fn(dominfo[i].domid, deathws ? &deathws[i] : NULL, i,
+               fallback_trigger);
+            nrdeathws++;
+        }
+
+        if (deathws) {
+            wait_for_domain_deaths(deathws, nrdeathws);
+            free(deathws);
+        }
+
+        libxl_dominfo_list_free(dominfo, nb_domain);
+    } else {
+        libxl_evgen_domain_death *deathw = NULL;
+        uint32_t domid = find_domain(argv[optind]);
+
+        fn(domid, wait_for_it ? &deathw : NULL, 0, fallback_trigger);
+
+        if (wait_for_it)
+            wait_for_domain_deaths(&deathw, 1);
+    }
+
+
+    return EXIT_SUCCESS;
+}
+
+int main_shutdown(int argc, char **argv)
+{
+    return main_shutdown_or_reboot(0, argc, argv);
+}
+
+int main_reboot(int argc, char **argv)
+{
+    return main_shutdown_or_reboot(1, argc, argv);
+}
+
+int main_list(int argc, char **argv)
+{
+    int opt;
+    bool verbose = false;
+    bool context = false;
+    bool details = false;
+    bool cpupool = false;
+    bool numa = false;
+    static struct option opts[] = {
+        {"long", 0, 0, 'l'},
+        {"verbose", 0, 0, 'v'},
+        {"context", 0, 0, 'Z'},
+        {"cpupool", 0, 0, 'c'},
+        {"numa", 0, 0, 'n'},
+        COMMON_LONG_OPTS
+    };
+
+    libxl_dominfo info_buf;
+    libxl_dominfo *info, *info_free=0;
+    int nb_domain, rc;
+
+    SWITCH_FOREACH_OPT(opt, "lvhZcn", opts, "list", 0) {
+    case 'l':
+        details = true;
+        break;
+    case 'v':
+        verbose = true;
+        break;
+    case 'Z':
+        context = true;
+        break;
+    case 'c':
+        cpupool = true;
+        break;
+    case 'n':
+        numa = true;
+        break;
+    }
+
+    libxl_dominfo_init(&info_buf);
+
+    if (optind >= argc) {
+        info = libxl_list_domain(ctx, &nb_domain);
+        if (!info) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            return EXIT_FAILURE;
+        }
+        info_free = info;
+    } else if (optind == argc-1) {
+        uint32_t domid = find_domain(argv[optind]);
+        rc = libxl_domain_info(ctx, &info_buf, domid);
+        if (rc == ERROR_DOMAIN_NOTFOUND) {
+            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
+                argv[optind]);
+            return EXIT_FAILURE;
+        }
+        if (rc) {
+            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
+            return EXIT_FAILURE;
+        }
+        info = &info_buf;
+        nb_domain = 1;
+    } else {
+        help("list");
+        return EXIT_FAILURE;
+    }
+
+    if (details)
+        list_domains_details(info, nb_domain);
+    else
+        list_domains(verbose, context, false /* claim */, numa, cpupool,
+                     info, nb_domain);
+
+    if (info_free)
+        libxl_dominfo_list_free(info, nb_domain);
+
+    libxl_dominfo_dispose(&info_buf);
+
+    return EXIT_SUCCESS;
+}
+
+int main_vm_list(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vm-list", 0) {
+        /* No options */
+    }
+
+    list_vm();
+    return EXIT_SUCCESS;
+}
+
+static void string_realloc_append(char **accumulate, const char *more)
+{
+    /* Appends more to accumulate.  Accumulate is either NULL, or
+     * points (always) to a malloc'd nul-terminated string. */
+
+    size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
+    size_t morelen = strlen(more) + 1/*nul*/;
+    if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
+        fprintf(stderr,"Additional config data far too large\n");
+        exit(-ERROR_FAIL);
+    }
+
+    *accumulate = xrealloc(*accumulate, oldlen + morelen);
+    memcpy(*accumulate + oldlen, more, morelen);
+}
+
+int main_create(int argc, char **argv)
+{
+    const char *filename = NULL;
+    struct domain_create dom_info;
+    int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
+        quiet = 0, monitor = 1, vnc = 0, vncautopass = 0;
+    int opt, rc;
+    static struct option opts[] = {
+        {"dryrun", 0, 0, 'n'},
+        {"quiet", 0, 0, 'q'},
+        {"defconfig", 1, 0, 'f'},
+        {"vncviewer", 0, 0, 'V'},
+        {"vncviewer-autopass", 0, 0, 'A'},
+        COMMON_LONG_OPTS
+    };
+
+    dom_info.extra_config = NULL;
+
+    if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
+        filename = argv[1];
+        argc--; argv++;
+    }
+
+    SWITCH_FOREACH_OPT(opt, "Fnqf:pcdeVA", opts, "create", 0) {
+    case 'f':
+        filename = optarg;
+        break;
+    case 'p':
+        paused = 1;
+        break;
+    case 'c':
+        console_autoconnect = 1;
+        break;
+    case 'd':
+        debug = 1;
+        break;
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'e':
+        daemonize = 0;
+        monitor = 0;
+        break;
+    case 'n':
+        dryrun_only = 1;
+        break;
+    case 'q':
+        quiet = 1;
+        break;
+    case 'V':
+        vnc = 1;
+        break;
+    case 'A':
+        vnc = vncautopass = 1;
+        break;
+    }
+
+    memset(&dom_info, 0, sizeof(dom_info));
+
+    for (; optind < argc; optind++) {
+        if (strchr(argv[optind], '=') != NULL) {
+            string_realloc_append(&dom_info.extra_config, argv[optind]);
+            string_realloc_append(&dom_info.extra_config, "\n");
+        } else if (!filename) {
+            filename = argv[optind];
+        } else {
+            help("create");
+            free(dom_info.extra_config);
+            return 2;
+        }
+    }
+
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.monitor = monitor;
+    dom_info.paused = paused;
+    dom_info.dryrun = dryrun_only;
+    dom_info.quiet = quiet;
+    dom_info.config_file = filename;
+    dom_info.migrate_fd = -1;
+    dom_info.send_back_fd = -1;
+    dom_info.vnc = vnc;
+    dom_info.vncautopass = vncautopass;
+    dom_info.console_autoconnect = console_autoconnect;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0) {
+        free(dom_info.extra_config);
+        return -rc;
+    }
+
+    free(dom_info.extra_config);
+    return 0;
+}
+
+int main_config_update(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *filename = NULL;
+    char *extra_config = NULL;
+    void *config_data = 0;
+    int config_len = 0;
+    libxl_domain_config d_config;
+    int opt, rc;
+    int debug = 0;
+    static struct option opts[] = {
+        {"defconfig", 1, 0, 'f'},
+        COMMON_LONG_OPTS
+    };
+
+    if (argc < 2) {
+        fprintf(stderr, "xl config-update requires a domain argument\n");
+        help("config-update");
+        exit(1);
+    }
+
+    fprintf(stderr, "WARNING: xl now has better capability to manage domain configuration, "
+            "avoid using this command when possible\n");
+
+    domid = find_domain(argv[1]);
+    argc--; argv++;
+
+    if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
+        filename = argv[1];
+        argc--; argv++;
+    }
+
+    SWITCH_FOREACH_OPT(opt, "dqf:", opts, "config_update", 0) {
+    case 'd':
+        debug = 1;
+        break;
+    case 'f':
+        filename = optarg;
+        break;
+    }
+
+    for (; optind < argc; optind++) {
+        if (strchr(argv[optind], '=') != NULL) {
+            string_realloc_append(&extra_config, argv[optind]);
+            string_realloc_append(&extra_config, "\n");
+        } else if (!filename) {
+            filename = argv[optind];
+        } else {
+            help("create");
+            free(extra_config);
+            return 2;
+        }
+    }
+    if (filename) {
+        free(config_data);  config_data = 0;
+        rc = libxl_read_file_contents(ctx, filename,
+                                      &config_data, &config_len);
+        if (rc) { fprintf(stderr, "Failed to read config file: %s: %s\n",
+                           filename, strerror(errno));
+                  free(extra_config); return ERROR_FAIL; }
+        if (extra_config && strlen(extra_config)) {
+            if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
+                fprintf(stderr, "Failed to attach extra configuration\n");
+                exit(1);
+            }
+            /* allocate space for the extra config plus two EOLs plus \0 */
+            config_data = realloc(config_data, config_len
+                + strlen(extra_config) + 2 + 1);
+            if (!config_data) {
+                fprintf(stderr, "Failed to realloc config_data\n");
+                exit(1);
+            }
+            config_len += sprintf(config_data + config_len, "\n%s\n",
+                extra_config);
+        }
+    } else {
+        fprintf(stderr, "Config file not specified\n");
+        exit(1);
+    }
+
+    libxl_domain_config_init(&d_config);
+
+    parse_config_data(filename, config_data, config_len, &d_config);
+
+    if (debug || dryrun_only)
+        printf_info(default_output_format, -1, &d_config, stdout);
+
+    if (!dryrun_only) {
+        fprintf(stderr, "setting dom%u configuration\n", domid);
+        rc = libxl_userdata_store(ctx, domid, "xl",
+                                   config_data, config_len);
+        if (rc) {
+            fprintf(stderr, "failed to update configuration\n");
+            exit(1);
+        }
+    }
+
+    libxl_domain_config_dispose(&d_config);
+
+    free(config_data);
+    free(extra_config);
+    return 0;
+}
+
+static void button_press(uint32_t domid, const char *b)
+{
+    libxl_trigger trigger;
+
+    if (!strcmp(b, "power")) {
+        trigger = LIBXL_TRIGGER_POWER;
+    } else if (!strcmp(b, "sleep")) {
+        trigger = LIBXL_TRIGGER_SLEEP;
+    } else {
+        fprintf(stderr, "%s is an invalid button identifier\n", b);
+        exit(EXIT_FAILURE);
+    }
+
+    libxl_send_trigger(ctx, domid, trigger, 0);
+}
+
+int main_button_press(int argc, char **argv)
+{
+    int opt;
+
+    fprintf(stderr, "WARNING: \"button-press\" is deprecated. "
+            "Please use \"trigger\"\n");
+
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "button-press", 2) {
+        /* No options */
+    }
+
+    button_press(find_domain(argv[optind]), argv[optind + 1]);
+
+    return 0;
+}
+
+static void print_vcpuinfo(uint32_t tdomid,
+                           const libxl_vcpuinfo *vcpuinfo,
+                           uint32_t nr_cpus)
+{
+    char *domname;
+
+    /*      NAME  ID  VCPU */
+    domname = libxl_domid_to_name(ctx, tdomid);
+    printf("%-32s %5u %5u",
+           domname, tdomid, vcpuinfo->vcpuid);
+    free(domname);
+    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 HARD AND SOFT AFFINITY */
+    print_bitmap(vcpuinfo->cpumap.map, nr_cpus, stdout);
+    printf(" / ");
+    print_bitmap(vcpuinfo->cpumap_soft.map, nr_cpus, stdout);
+    printf("\n");
+}
+
+static void print_domain_vcpuinfo(uint32_t domid, uint32_t nr_cpus)
+{
+    libxl_vcpuinfo *vcpuinfo;
+    int i, nb_vcpu, nrcpus;
+
+    vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nrcpus);
+
+    if (!vcpuinfo)
+        return;
+
+    for (i = 0; i < nb_vcpu; i++) {
+        print_vcpuinfo(domid, &vcpuinfo[i], nr_cpus);
+    }
+
+    libxl_vcpuinfo_list_free(vcpuinfo, nb_vcpu);
+}
+
+static void vcpulist(int argc, char **argv)
+{
+    libxl_dominfo *dominfo;
+    libxl_physinfo physinfo;
+    int i, nb_domain;
+
+    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)",
+           "Affinity (Hard / Soft)");
+    if (!argc) {
+        if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            goto vcpulist_out;
+        }
+
+        for (i = 0; i<nb_domain; i++)
+            print_domain_vcpuinfo(dominfo[i].domid, physinfo.nr_cpus);
+
+        libxl_dominfo_list_free(dominfo, nb_domain);
+    } else {
+        for (; argc > 0; ++argv, --argc) {
+            uint32_t domid = find_domain(*argv);
+            print_domain_vcpuinfo(domid, physinfo.nr_cpus);
+        }
+    }
+  vcpulist_out:
+    libxl_physinfo_dispose(&physinfo);
+}
+
+int main_vcpulist(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vcpu-list", 0) {
+        /* No options */
+    }
+
+    vcpulist(argc - optind, argv + optind);
+    return EXIT_SUCCESS;
+}
+
+int main_vcpupin(int argc, char **argv)
+{
+    static struct option opts[] = {
+        {"force", 0, 0, 'f'},
+        COMMON_LONG_OPTS
+    };
+    libxl_vcpuinfo *vcpuinfo;
+    libxl_bitmap cpumap_hard, cpumap_soft;;
+    libxl_bitmap *soft = &cpumap_soft, *hard = &cpumap_hard;
+    uint32_t domid;
+    /*
+     * int would be enough for vcpuid, but we don't want to
+     * mess aroung range checking the return value of strtol().
+     */
+    long vcpuid;
+    const char *vcpu, *hard_str, *soft_str;
+    char *endptr;
+    int opt, nb_cpu, nb_vcpu, rc = EXIT_FAILURE;
+    bool force = false;
+
+    libxl_bitmap_init(&cpumap_hard);
+    libxl_bitmap_init(&cpumap_soft);
+
+    SWITCH_FOREACH_OPT(opt, "f", opts, "vcpu-pin", 3) {
+    case 'f':
+        force = true;
+        break;
+    default:
+        break;
+    }
+
+    domid = find_domain(argv[optind]);
+    vcpu = argv[optind+1];
+    hard_str = argv[optind+2];
+    soft_str = (argc > optind+3) ? argv[optind+3] : NULL;
+
+    /* Figure out with which vCPU we are dealing with */
+    vcpuid = strtol(vcpu, &endptr, 10);
+    if (vcpu == endptr || vcpuid < 0) {
+        if (strcmp(vcpu, "all")) {
+            fprintf(stderr, "Error: Invalid argument %s as VCPU.\n", vcpu);
+            goto out;
+        }
+        if (force) {
+            fprintf(stderr, "Error: --force and 'all' as VCPU not allowed.\n");
+            goto out;
+        }
+        vcpuid = -1;
+    }
+
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap_hard, 0) ||
+        libxl_cpu_bitmap_alloc(ctx, &cpumap_soft, 0))
+        goto out;
+
+    /*
+     * Syntax is: xl vcpu-pin <domid> <vcpu> <hard> <soft>
+     * We want to handle all the following cases ('-' means
+     * "leave it alone"):
+     *  xl vcpu-pin 0 3 3,4
+     *  xl vcpu-pin 0 3 3,4 -
+     *  xl vcpu-pin 0 3 - 6-9
+     *  xl vcpu-pin 0 3 3,4 6-9
+     */
+
+    /*
+     * Hard affinity is always present. However, if it's "-", all we need
+     * is passing a NULL pointer to the libxl_set_vcpuaffinity() call below.
+     */
+    if (!strcmp(hard_str, "-"))
+        hard = NULL;
+    else if (cpurange_parse(hard_str, hard))
+        goto out;
+    /*
+     * Soft affinity is handled similarly. Only difference: we also want
+     * to pass NULL to libxl_set_vcpuaffinity() if it is not specified.
+     */
+    if (argc <= optind+3 || !strcmp(soft_str, "-"))
+        soft = NULL;
+    else if (cpurange_parse(soft_str, soft))
+        goto out;
+
+    if (dryrun_only) {
+        nb_cpu = libxl_get_online_cpus(ctx);
+        if (nb_cpu < 0) {
+            fprintf(stderr, "libxl_get_online_cpus failed.\n");
+            goto out;
+        }
+
+        fprintf(stdout, "cpumap: ");
+        if (hard)
+            print_bitmap(hard->map, nb_cpu, stdout);
+        else
+            fprintf(stdout, "-");
+        if (soft) {
+            fprintf(stdout, " ");
+            print_bitmap(soft->map, nb_cpu, stdout);
+        }
+        fprintf(stdout, "\n");
+
+        if (ferror(stdout) || fflush(stdout)) {
+            perror("stdout");
+            exit(EXIT_FAILURE);
+        }
+
+        rc = EXIT_SUCCESS;
+        goto out;
+    }
+
+    if (force) {
+        if (libxl_set_vcpuaffinity_force(ctx, domid, vcpuid, hard, soft)) {
+            fprintf(stderr, "Could not set affinity for vcpu `%ld'.\n",
+                    vcpuid);
+            goto out;
+        }
+    }
+    else if (vcpuid != -1) {
+        if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, hard, soft)) {
+            fprintf(stderr, "Could not set affinity for vcpu `%ld'.\n",
+                    vcpuid);
+            goto out;
+        }
+    } else {
+        if (!(vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nb_cpu))) {
+            fprintf(stderr, "libxl_list_vcpu failed.\n");
+            goto out;
+        }
+        if (libxl_set_vcpuaffinity_all(ctx, domid, nb_vcpu, hard, soft))
+            fprintf(stderr, "Could not set affinity.\n");
+        libxl_vcpuinfo_list_free(vcpuinfo, nb_vcpu);
+    }
+
+    rc = EXIT_SUCCESS;
+ out:
+    libxl_bitmap_dispose(&cpumap_soft);
+    libxl_bitmap_dispose(&cpumap_hard);
+    return rc;
+}
+
+static int vcpuset(uint32_t domid, const char* nr_vcpus, int check_host)
+{
+    char *endptr;
+    unsigned int max_vcpus, i;
+    libxl_bitmap cpumap;
+    int rc;
+
+    libxl_bitmap_init(&cpumap);
+    max_vcpus = strtoul(nr_vcpus, &endptr, 10);
+    if (nr_vcpus == endptr) {
+        fprintf(stderr, "Error: Invalid argument.\n");
+        return 1;
+    }
+
+    /*
+     * Maximum amount of vCPUS the guest is allowed to set is limited
+     * by the host's amount of pCPUs.
+     */
+    if (check_host) {
+        unsigned int online_vcpus, host_cpu = libxl_get_max_cpus(ctx);
+        libxl_dominfo dominfo;
+
+        if (libxl_domain_info(ctx, &dominfo, domid))
+            return 1;
+
+        online_vcpus = dominfo.vcpu_online;
+        libxl_dominfo_dispose(&dominfo);
+
+        if (max_vcpus > online_vcpus && max_vcpus > host_cpu) {
+            fprintf(stderr, "You are overcommmitting! You have %d physical" \
+                    " CPUs and want %d vCPUs! Aborting, use --ignore-host to" \
+                    " continue\n", host_cpu, max_vcpus);
+            return 1;
+        }
+    }
+    rc = libxl_cpu_bitmap_alloc(ctx, &cpumap, max_vcpus);
+    if (rc) {
+        fprintf(stderr, "libxl_cpu_bitmap_alloc failed, rc: %d\n", rc);
+        return 1;
+    }
+    for (i = 0; i < max_vcpus; i++)
+        libxl_bitmap_set(&cpumap, i);
+
+    rc = libxl_set_vcpuonline(ctx, domid, &cpumap);
+    if (rc == ERROR_DOMAIN_NOTFOUND)
+        fprintf(stderr, "Domain %u does not exist.\n", domid);
+    else if (rc)
+        fprintf(stderr, "libxl_set_vcpuonline failed domid=%u max_vcpus=%d," \
+                " rc: %d\n", domid, max_vcpus, rc);
+
+    libxl_bitmap_dispose(&cpumap);
+    return rc ? 1 : 0;
+}
+
+int main_vcpuset(int argc, char **argv)
+{
+    static struct option opts[] = {
+        {"ignore-host", 0, 0, 'i'},
+        COMMON_LONG_OPTS
+    };
+    int opt, check_host = 1;
+
+    SWITCH_FOREACH_OPT(opt, "i", opts, "vcpu-set", 2) {
+    case 'i':
+        check_host = 0;
+        break;
+    default:
+        break;
+    }
+
+    if (vcpuset(find_domain(argv[optind]), argv[optind + 1], check_host))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+/* Possibly select a specific piece of `xl info` to print. */
+static const char *info_name;
+static int maybe_printf(const char *fmt, ...) __attribute__((format(printf,1,2)));
+static int maybe_printf(const char *fmt, ...)
+{
+    va_list ap;
+    char *str;
+    int count = 0;
+
+    va_start(ap, fmt);
+    if (vasprintf(&str, fmt, ap) != -1) {
+        if (info_name) {
+            char *s;
+
+            if (!strncmp(str, info_name, strlen(info_name)) &&
+                (s = strchr(str, ':')) && s[1] == ' ')
+                count = fputs(&s[2], stdout);
+        } else
+            count = fputs(str, stdout);
+
+        free(str);
+    }
+    va_end(ap);
+
+    return count;
+}
+
+static void output_xeninfo(void)
+{
+    const libxl_version_info *info;
+    libxl_scheduler sched;
+    int rc;
+
+    if (!(info = libxl_get_version_info(ctx))) {
+        fprintf(stderr, "libxl_get_version_info failed.\n");
+        return;
+    }
+
+    rc = libxl_get_scheduler(ctx);
+    if (rc < 0) {
+        fprintf(stderr, "get_scheduler sysctl failed.\n");
+        return;
+    }
+    sched = rc;
+
+    maybe_printf("xen_major              : %d\n", info->xen_version_major);
+    maybe_printf("xen_minor              : %d\n", info->xen_version_minor);
+    maybe_printf("xen_extra              : %s\n", info->xen_version_extra);
+    maybe_printf("xen_version            : %d.%d%s\n", info->xen_version_major,
+           info->xen_version_minor, info->xen_version_extra);
+    maybe_printf("xen_caps               : %s\n", info->capabilities);
+    maybe_printf("xen_scheduler          : %s\n", libxl_scheduler_to_string(sched));
+    maybe_printf("xen_pagesize           : %u\n", info->pagesize);
+    maybe_printf("platform_params        : virt_start=0x%"PRIx64"\n", info->virt_start);
+    maybe_printf("xen_changeset          : %s\n", info->changeset);
+    maybe_printf("xen_commandline        : %s\n", info->commandline);
+    maybe_printf("cc_compiler            : %s\n", info->compiler);
+    maybe_printf("cc_compile_by          : %s\n", info->compile_by);
+    maybe_printf("cc_compile_domain      : %s\n", info->compile_domain);
+    maybe_printf("cc_compile_date        : %s\n", info->compile_date);
+    maybe_printf("build_id               : %s\n", info->build_id);
+
+    return;
+}
+
+static void output_nodeinfo(void)
+{
+    struct utsname utsbuf;
+
+    if (uname(&utsbuf) < 0)
+        return;
+
+    maybe_printf("host                   : %s\n", utsbuf.nodename);
+    maybe_printf("release                : %s\n", utsbuf.release);
+    maybe_printf("version                : %s\n", utsbuf.version);
+    maybe_printf("machine                : %s\n", utsbuf.machine);
+}
+
+static void output_physinfo(void)
+{
+    libxl_physinfo info;
+    const libxl_version_info *vinfo;
+    unsigned int i;
+    libxl_bitmap cpumap;
+    int n = 0;
+
+    if (libxl_get_physinfo(ctx, &info) != 0) {
+        fprintf(stderr, "libxl_physinfo failed.\n");
+        return;
+    }
+    maybe_printf("nr_cpus                : %d\n", info.nr_cpus);
+    maybe_printf("max_cpu_id             : %d\n", info.max_cpu_id);
+    maybe_printf("nr_nodes               : %d\n", info.nr_nodes);
+    maybe_printf("cores_per_socket       : %d\n", info.cores_per_socket);
+    maybe_printf("threads_per_core       : %d\n", info.threads_per_core);
+    maybe_printf("cpu_mhz                : %d\n", info.cpu_khz / 1000);
+
+    maybe_printf("hw_caps                : %08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x\n",
+         info.hw_cap[0], info.hw_cap[1], info.hw_cap[2], info.hw_cap[3],
+         info.hw_cap[4], info.hw_cap[5], info.hw_cap[6], info.hw_cap[7]
+        );
+
+    maybe_printf("virt_caps              :%s%s\n",
+         info.cap_hvm ? " hvm" : "",
+         info.cap_hvm_directio ? " hvm_directio" : ""
+        );
+
+    vinfo = libxl_get_version_info(ctx);
+    if (vinfo) {
+        i = (1 << 20) / vinfo->pagesize;
+        maybe_printf("total_memory           : %"PRIu64"\n", info.total_pages / i);
+        maybe_printf("free_memory            : %"PRIu64"\n", (info.free_pages - info.outstanding_pages) / i);
+        maybe_printf("sharing_freed_memory   : %"PRIu64"\n", info.sharing_freed_pages / i);
+        maybe_printf("sharing_used_memory    : %"PRIu64"\n", info.sharing_used_frames / i);
+        maybe_printf("outstanding_claims     : %"PRIu64"\n", info.outstanding_pages / i);
+    }
+    if (!libxl_get_freecpus(ctx, &cpumap)) {
+        libxl_for_each_bit(i, cpumap)
+            if (libxl_bitmap_test(&cpumap, i))
+                n++;
+        maybe_printf("free_cpus              : %d\n", n);
+        free(cpumap.map);
+    }
+    libxl_physinfo_dispose(&info);
+    return;
+}
+
+static void output_numainfo(void)
+{
+    libxl_numainfo *info;
+    int i, j, nr;
+
+    info = libxl_get_numainfo(ctx, &nr);
+    if (info == NULL) {
+        fprintf(stderr, "libxl_get_numainfo failed.\n");
+        return;
+    }
+
+    printf("numa_info              :\n");
+    printf("node:    memsize    memfree    distances\n");
+
+    for (i = 0; i < nr; i++) {
+        if (info[i].size != LIBXL_NUMAINFO_INVALID_ENTRY) {
+            printf("%4d:    %6"PRIu64"     %6"PRIu64"      %d", i,
+                   info[i].size >> 20, info[i].free >> 20,
+                   info[i].dists[0]);
+            for (j = 1; j < info[i].num_dists; j++)
+                printf(",%d", info[i].dists[j]);
+            printf("\n");
+        }
+    }
+
+    libxl_numainfo_list_free(info, nr);
+
+    return;
+}
+
+static void output_topologyinfo(void)
+{
+    libxl_cputopology *cpuinfo;
+    int i, nr;
+    libxl_pcitopology *pciinfo;
+    int valid_devs = 0;
+
+
+    cpuinfo = libxl_get_cpu_topology(ctx, &nr);
+    if (cpuinfo == NULL) {
+        fprintf(stderr, "libxl_get_cpu_topology failed.\n");
+        return;
+    }
+
+    printf("cpu_topology           :\n");
+    printf("cpu:    core    socket     node\n");
+
+    for (i = 0; i < nr; i++) {
+        if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
+            printf("%3d:    %4d     %4d     %4d\n", i,
+                   cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node);
+    }
+
+    libxl_cputopology_list_free(cpuinfo, nr);
+
+    pciinfo = libxl_get_pci_topology(ctx, &nr);
+    if (pciinfo == NULL) {
+        fprintf(stderr, "libxl_get_pci_topology failed.\n");
+        return;
+    }
+
+    printf("device topology        :\n");
+    printf("device           node\n");
+    for (i = 0; i < nr; i++) {
+        if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) {
+            printf("%04x:%02x:%02x.%01x      %d\n", pciinfo[i].seg,
+                   pciinfo[i].bus,
+                   ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7),
+                   pciinfo[i].node);
+            valid_devs++;
+        }
+    }
+
+    if (valid_devs == 0)
+        printf("No device topology data available\n");
+
+    libxl_pcitopology_list_free(pciinfo, nr);
+
+    return;
+}
+
+static void print_info(int numa)
+{
+    output_nodeinfo();
+
+    output_physinfo();
+
+    if (numa) {
+        output_topologyinfo();
+        output_numainfo();
+    }
+    output_xeninfo();
+
+    maybe_printf("xend_config_format     : 4\n");
+
+    return;
+}
+
+int main_info(int argc, char **argv)
+{
+    int opt;
+    static struct option opts[] = {
+        {"numa", 0, 0, 'n'},
+        COMMON_LONG_OPTS
+    };
+    int numa = 0;
+
+    SWITCH_FOREACH_OPT(opt, "n", opts, "info", 0) {
+    case 'n':
+        numa = 1;
+        break;
+    }
+
+    /*
+     * If an extra argument is provided, filter out a specific piece of
+     * information.
+     */
+    if (numa == 0 && argc > optind)
+        info_name = argv[optind];
+
+    print_info(numa);
+    return 0;
+}
+
+static void sharing(const libxl_dominfo *info, int nb_domain)
+{
+    int i;
+
+    printf("Name                                        ID   Mem Shared\n");
+
+    for (i = 0; i < nb_domain; i++) {
+        char *domname;
+        unsigned shutdown_reason;
+        domname = libxl_domid_to_name(ctx, info[i].domid);
+        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
+        printf("%-40s %5d %5lu  %5lu\n",
+                domname,
+                info[i].domid,
+                (unsigned long) ((info[i].current_memkb +
+                    info[i].outstanding_memkb) / 1024),
+                (unsigned long) (info[i].shared_memkb / 1024));
+        free(domname);
+    }
+}
+
+int main_sharing(int argc, char **argv)
+{
+    int opt = 0;
+    libxl_dominfo info_buf;
+    libxl_dominfo *info, *info_free = NULL;
+    int nb_domain, rc;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "sharing", 0) {
+        /* No options */
+    }
+
+    if (optind >= argc) {
+        info = libxl_list_domain(ctx, &nb_domain);
+        if (!info) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            return EXIT_FAILURE;
+        }
+        info_free = info;
+    } else if (optind == argc-1) {
+        uint32_t domid = find_domain(argv[optind]);
+        rc = libxl_domain_info(ctx, &info_buf, domid);
+        if (rc == ERROR_DOMAIN_NOTFOUND) {
+            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
+                argv[optind]);
+            return EXIT_FAILURE;
+        }
+        if (rc) {
+            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
+            return EXIT_FAILURE;
+        }
+        info = &info_buf;
+        nb_domain = 1;
+    } else {
+        help("sharing");
+        return EXIT_FAILURE;
+    }
+
+    sharing(info, nb_domain);
+
+    if (info_free)
+        libxl_dominfo_list_free(info_free, nb_domain);
+    else
+        libxl_dominfo_dispose(info);
+
+    return EXIT_SUCCESS;
+}
+
+static int sched_domain_get(libxl_scheduler sched, int domid,
+                            libxl_domain_sched_params *scinfo)
+{
+    if (libxl_domain_sched_params_get(ctx, domid, scinfo)) {
+        fprintf(stderr, "libxl_domain_sched_params_get failed.\n");
+        return 1;
+    }
+    if (scinfo->sched != sched) {
+        fprintf(stderr, "libxl_domain_sched_params_get returned %s not %s.\n",
+                libxl_scheduler_to_string(scinfo->sched),
+                libxl_scheduler_to_string(sched));
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_domain_set(int domid, const libxl_domain_sched_params *scinfo)
+{
+    if (libxl_domain_sched_params_set(ctx, domid, scinfo)) {
+        fprintf(stderr, "libxl_domain_sched_params_set failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_vcpu_get(libxl_scheduler sched, int domid,
+                          libxl_vcpu_sched_params *scinfo)
+{
+    int rc;
+
+    rc = libxl_vcpu_sched_params_get(ctx, domid, scinfo);
+    if (rc) {
+        fprintf(stderr, "libxl_vcpu_sched_params_get failed.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (scinfo->sched != sched) {
+        fprintf(stderr, "libxl_vcpu_sched_params_get returned %s not %s.\n",
+                libxl_scheduler_to_string(scinfo->sched),
+                libxl_scheduler_to_string(sched));
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_vcpu_get_all(libxl_scheduler sched, int domid,
+                              libxl_vcpu_sched_params *scinfo)
+{
+    int rc;
+
+    rc = libxl_vcpu_sched_params_get_all(ctx, domid, scinfo);
+    if (rc) {
+        fprintf(stderr, "libxl_vcpu_sched_params_get_all failed.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (scinfo->sched != sched) {
+        fprintf(stderr, "libxl_vcpu_sched_params_get_all returned %s not %s.\n",
+                libxl_scheduler_to_string(scinfo->sched),
+                libxl_scheduler_to_string(sched));
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_vcpu_set(int domid, const libxl_vcpu_sched_params *scinfo)
+{
+    int rc;
+
+    rc = libxl_vcpu_sched_params_set(ctx, domid, scinfo);
+    if (rc) {
+        fprintf(stderr, "libxl_vcpu_sched_params_set failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    return 0;
+}
+
+static int sched_vcpu_set_all(int domid, const libxl_vcpu_sched_params *scinfo)
+{
+    int rc;
+
+    rc = libxl_vcpu_sched_params_set_all(ctx, domid, scinfo);
+    if (rc) {
+        fprintf(stderr, "libxl_vcpu_sched_params_set_all failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    return 0;
+}
+
+static int sched_credit_params_set(int poolid, libxl_sched_credit_params *scinfo)
+{
+    if (libxl_sched_credit_params_set(ctx, poolid, scinfo)) {
+        fprintf(stderr, "libxl_sched_credit_params_set failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_credit_params_get(int poolid, libxl_sched_credit_params *scinfo)
+{
+    if (libxl_sched_credit_params_get(ctx, poolid, scinfo)) {
+        fprintf(stderr, "libxl_sched_credit_params_get failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_credit_domain_output(int domid)
+{
+    char *domname;
+    libxl_domain_sched_params scinfo;
+
+    if (domid < 0) {
+        printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
+        return 0;
+    }
+
+    libxl_domain_sched_params_init(&scinfo);
+    if (sched_domain_get(LIBXL_SCHEDULER_CREDIT, domid, &scinfo)) {
+        libxl_domain_sched_params_dispose(&scinfo);
+        return 1;
+    }
+    domname = libxl_domid_to_name(ctx, domid);
+    printf("%-33s %4d %6d %4d\n",
+        domname,
+        domid,
+        scinfo.weight,
+        scinfo.cap);
+    free(domname);
+    libxl_domain_sched_params_dispose(&scinfo);
+    return 0;
+}
+
+static int sched_credit_pool_output(uint32_t poolid)
+{
+    libxl_sched_credit_params scparam;
+    char *poolname;
+
+    poolname = libxl_cpupoolid_to_name(ctx, poolid);
+    if (sched_credit_params_get(poolid, &scparam)) {
+        printf("Cpupool %s: [sched params unavailable]\n",
+               poolname);
+    } else {
+        printf("Cpupool %s: tslice=%dms ratelimit=%dus\n",
+               poolname,
+               scparam.tslice_ms,
+               scparam.ratelimit_us);
+    }
+    free(poolname);
+    return 0;
+}
+
+static int sched_credit2_params_set(int poolid,
+                                    libxl_sched_credit2_params *scinfo)
+{
+    if (libxl_sched_credit2_params_set(ctx, poolid, scinfo)) {
+        fprintf(stderr, "libxl_sched_credit2_params_set failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_credit2_params_get(int poolid,
+                                    libxl_sched_credit2_params *scinfo)
+{
+    if (libxl_sched_credit2_params_get(ctx, poolid, scinfo)) {
+        fprintf(stderr, "libxl_sched_credit2_params_get failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_credit2_domain_output(int domid)
+{
+    char *domname;
+    libxl_domain_sched_params scinfo;
+
+    if (domid < 0) {
+        printf("%-33s %4s %6s\n", "Name", "ID", "Weight");
+        return 0;
+    }
+
+    libxl_domain_sched_params_init(&scinfo);
+    if (sched_domain_get(LIBXL_SCHEDULER_CREDIT2, domid, &scinfo)) {
+        libxl_domain_sched_params_dispose(&scinfo);
+        return 1;
+    }
+    domname = libxl_domid_to_name(ctx, domid);
+    printf("%-33s %4d %6d\n",
+        domname,
+        domid,
+        scinfo.weight);
+    free(domname);
+    libxl_domain_sched_params_dispose(&scinfo);
+    return 0;
+}
+
+static int sched_credit2_pool_output(uint32_t poolid)
+{
+    libxl_sched_credit2_params scparam;
+    char *poolname = libxl_cpupoolid_to_name(ctx, poolid);
+
+    if (sched_credit2_params_get(poolid, &scparam))
+        printf("Cpupool %s: [sched params unavailable]\n", poolname);
+    else
+        printf("Cpupool %s: ratelimit=%dus\n",
+               poolname, scparam.ratelimit_us);
+
+    free(poolname);
+
+    return 0;
+}
+
+static int sched_rtds_domain_output(
+    int domid)
+{
+    char *domname;
+    libxl_domain_sched_params scinfo;
+
+    if (domid < 0) {
+        printf("%-33s %4s %9s %9s\n", "Name", "ID", "Period", "Budget");
+        return 0;
+    }
+
+    libxl_domain_sched_params_init(&scinfo);
+    if (sched_domain_get(LIBXL_SCHEDULER_RTDS, domid, &scinfo)) {
+        libxl_domain_sched_params_dispose(&scinfo);
+        return 1;
+    }
+
+    domname = libxl_domid_to_name(ctx, domid);
+    printf("%-33s %4d %9d %9d\n",
+        domname,
+        domid,
+        scinfo.period,
+        scinfo.budget);
+    free(domname);
+    libxl_domain_sched_params_dispose(&scinfo);
+    return 0;
+}
+
+static int sched_rtds_vcpu_output(int domid, libxl_vcpu_sched_params *scinfo)
+{
+    char *domname;
+    int rc = 0;
+    int i;
+
+    if (domid < 0) {
+        printf("%-33s %4s %4s %9s %9s\n", "Name", "ID",
+               "VCPU", "Period", "Budget");
+        return 0;
+    }
+
+    rc = sched_vcpu_get(LIBXL_SCHEDULER_RTDS, domid, scinfo);
+    if (rc)
+        return 1;
+
+    domname = libxl_domid_to_name(ctx, domid);
+    for ( i = 0; i < scinfo->num_vcpus; i++ ) {
+        printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32"\n",
+               domname,
+               domid,
+               scinfo->vcpus[i].vcpuid,
+               scinfo->vcpus[i].period,
+               scinfo->vcpus[i].budget);
+    }
+    free(domname);
+    return 0;
+}
+
+static int sched_rtds_vcpu_output_all(int domid,
+                                      libxl_vcpu_sched_params *scinfo)
+{
+    char *domname;
+    int rc = 0;
+    int i;
+
+    if (domid < 0) {
+        printf("%-33s %4s %4s %9s %9s\n", "Name", "ID",
+               "VCPU", "Period", "Budget");
+        return 0;
+    }
+
+    scinfo->num_vcpus = 0;
+    rc = sched_vcpu_get_all(LIBXL_SCHEDULER_RTDS, domid, scinfo);
+    if (rc)
+        return 1;
+
+    domname = libxl_domid_to_name(ctx, domid);
+    for ( i = 0; i < scinfo->num_vcpus; i++ ) {
+        printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32"\n",
+               domname,
+               domid,
+               scinfo->vcpus[i].vcpuid,
+               scinfo->vcpus[i].period,
+               scinfo->vcpus[i].budget);
+    }
+    free(domname);
+    return 0;
+}
+
+static int sched_rtds_pool_output(uint32_t poolid)
+{
+    char *poolname;
+
+    poolname = libxl_cpupoolid_to_name(ctx, poolid);
+    printf("Cpupool %s: sched=RTDS\n", poolname);
+
+    free(poolname);
+    return 0;
+}
+
+static int sched_domain_output(libxl_scheduler sched, int (*output)(int),
+                               int (*pooloutput)(uint32_t), const char *cpupool)
+{
+    libxl_dominfo *info;
+    libxl_cpupoolinfo *poolinfo = NULL;
+    uint32_t poolid;
+    int nb_domain, n_pools = 0, i, p;
+    int rc = 0;
+
+    if (cpupool) {
+        if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL) ||
+            !libxl_cpupoolid_is_valid(ctx, poolid)) {
+            fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
+            return 1;
+        }
+    }
+
+    info = libxl_list_domain(ctx, &nb_domain);
+    if (!info) {
+        fprintf(stderr, "libxl_list_domain failed.\n");
+        return 1;
+    }
+    poolinfo = libxl_list_cpupool(ctx, &n_pools);
+    if (!poolinfo) {
+        fprintf(stderr, "error getting cpupool info\n");
+        libxl_dominfo_list_free(info, nb_domain);
+        return 1;
+    }
+
+    for (p = 0; !rc && (p < n_pools); p++) {
+        if ((poolinfo[p].sched != sched) ||
+            (cpupool && (poolid != poolinfo[p].poolid)))
+            continue;
+
+        pooloutput(poolinfo[p].poolid);
+
+        output(-1);
+        for (i = 0; i < nb_domain; i++) {
+            if (info[i].cpupool != poolinfo[p].poolid)
+                continue;
+            rc = output(info[i].domid);
+            if (rc)
+                break;
+        }
+    }
+
+    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
+    libxl_dominfo_list_free(info, nb_domain);
+    return 0;
+}
+
+static int sched_vcpu_output(libxl_scheduler sched,
+                             int (*output)(int, libxl_vcpu_sched_params *),
+                             int (*pooloutput)(uint32_t), const char *cpupool)
+{
+    libxl_dominfo *info;
+    libxl_cpupoolinfo *poolinfo = NULL;
+    uint32_t poolid;
+    int nb_domain, n_pools = 0, i, p;
+    int rc = 0;
+
+    if (cpupool) {
+        if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL)
+            || !libxl_cpupoolid_is_valid(ctx, poolid)) {
+            fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
+            return 1;
+        }
+    }
+
+    info = libxl_list_domain(ctx, &nb_domain);
+    if (!info) {
+        fprintf(stderr, "libxl_list_domain failed.\n");
+        return 1;
+    }
+    poolinfo = libxl_list_cpupool(ctx, &n_pools);
+    if (!poolinfo) {
+        fprintf(stderr, "error getting cpupool info\n");
+        libxl_dominfo_list_free(info, nb_domain);
+        return 1;
+    }
+
+    for (p = 0; !rc && (p < n_pools); p++) {
+        if ((poolinfo[p].sched != sched) ||
+            (cpupool && (poolid != poolinfo[p].poolid)))
+            continue;
+
+        pooloutput(poolinfo[p].poolid);
+
+        output(-1, NULL);
+        for (i = 0; i < nb_domain; i++) {
+            libxl_vcpu_sched_params scinfo;
+            if (info[i].cpupool != poolinfo[p].poolid)
+                continue;
+            libxl_vcpu_sched_params_init(&scinfo);
+            rc = output(info[i].domid, &scinfo);
+            libxl_vcpu_sched_params_dispose(&scinfo);
+            if (rc)
+                break;
+        }
+    }
+
+    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
+    libxl_dominfo_list_free(info, nb_domain);
+    return 0;
+}
+
+/* 
+ * <nothing>             : List all domain params and sched params from all pools
+ * -d [domid]            : List domain params for domain
+ * -d [domid] [params]   : Set domain params for domain
+ * -p [pool]             : list all domains and sched params for pool
+ * -s                    : List sched params for poolid 0
+ * -s [params]           : Set sched params for poolid 0
+ * -p [pool] -s          : List sched params for pool
+ * -p [pool] -s [params] : Set sched params for pool
+ * -p [pool] -d...       : Illegal
+ */
+int main_sched_credit(int argc, char **argv)
+{
+    const char *dom = NULL;
+    const char *cpupool = NULL;
+    int weight = 256, cap = 0;
+    int tslice = 0, ratelimit = 0;
+    bool opt_w = false, opt_c = false;
+    bool opt_t = false, opt_r = false;
+    bool opt_s = false;
+    int opt, rc;
+    static struct option opts[] = {
+        {"domain", 1, 0, 'd'},
+        {"weight", 1, 0, 'w'},
+        {"cap", 1, 0, 'c'},
+        {"schedparam", 0, 0, 's'},
+        {"tslice_ms", 1, 0, 't'},
+        {"ratelimit_us", 1, 0, 'r'},
+        {"cpupool", 1, 0, 'p'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "d:w:c:p:t:r:s", opts, "sched-credit", 0) {
+    case 'd':
+        dom = optarg;
+        break;
+    case 'w':
+        weight = strtol(optarg, NULL, 10);
+        opt_w = true;
+        break;
+    case 'c':
+        cap = strtol(optarg, NULL, 10);
+        opt_c = true;
+        break;
+    case 't':
+        tslice = strtol(optarg, NULL, 10);
+        opt_t = true;
+        break;
+    case 'r':
+        ratelimit = strtol(optarg, NULL, 10);
+        opt_r = true;
+        break;
+    case 's':
+        opt_s = true;
+        break;
+    case 'p':
+        cpupool = optarg;
+        break;
+    }
+
+    if ((cpupool || opt_s) && (dom || opt_w || opt_c)) {
+        fprintf(stderr, "Specifying a cpupool or schedparam is not "
+                "allowed with domain options.\n");
+        return EXIT_FAILURE;
+    }
+    if (!dom && (opt_w || opt_c)) {
+        fprintf(stderr, "Must specify a domain.\n");
+        return EXIT_FAILURE;
+    }
+    if (!opt_s && (opt_t || opt_r)) {
+        fprintf(stderr, "Must specify schedparam to set schedule "
+                "parameter values.\n");
+        return EXIT_FAILURE;
+    }
+
+    if (opt_s) {
+        libxl_sched_credit_params scparam;
+        uint32_t poolid = 0;
+
+        if (cpupool) {
+            if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
+                                                     &poolid, NULL) ||
+                !libxl_cpupoolid_is_valid(ctx, poolid)) {
+                fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
+                return EXIT_FAILURE;
+            }
+        }
+
+        if (!opt_t && !opt_r) { /* Output scheduling parameters */
+            if (sched_credit_pool_output(poolid))
+                return EXIT_FAILURE;
+        } else { /* Set scheduling parameters*/
+            if (sched_credit_params_get(poolid, &scparam))
+                return EXIT_FAILURE;
+
+            if (opt_t)
+                scparam.tslice_ms = tslice;
+
+            if (opt_r)
+                scparam.ratelimit_us = ratelimit;
+
+            if (sched_credit_params_set(poolid, &scparam))
+                return EXIT_FAILURE;
+        }
+    } else if (!dom) { /* list all domain's credit scheduler info */
+        if (sched_domain_output(LIBXL_SCHEDULER_CREDIT,
+                                sched_credit_domain_output,
+                                sched_credit_pool_output,
+                                cpupool))
+            return EXIT_FAILURE;
+    } else {
+        uint32_t domid = find_domain(dom);
+
+        if (!opt_w && !opt_c) { /* output credit scheduler info */
+            sched_credit_domain_output(-1);
+            if (sched_credit_domain_output(domid))
+                return EXIT_FAILURE;
+        } else { /* set credit scheduler paramaters */
+            libxl_domain_sched_params scinfo;
+            libxl_domain_sched_params_init(&scinfo);
+            scinfo.sched = LIBXL_SCHEDULER_CREDIT;
+            if (opt_w)
+                scinfo.weight = weight;
+            if (opt_c)
+                scinfo.cap = cap;
+            rc = sched_domain_set(domid, &scinfo);
+            libxl_domain_sched_params_dispose(&scinfo);
+            if (rc)
+                return EXIT_FAILURE;
+        }
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_sched_credit2(int argc, char **argv)
+{
+    const char *dom = NULL;
+    const char *cpupool = NULL;
+    int ratelimit = 0;
+    int weight = 256;
+    bool opt_s = false;
+    bool opt_r = false;
+    bool opt_w = false;
+    int opt, rc;
+    static struct option opts[] = {
+        {"domain", 1, 0, 'd'},
+        {"weight", 1, 0, 'w'},
+        {"schedparam", 0, 0, 's'},
+        {"ratelimit_us", 1, 0, 'r'},
+        {"cpupool", 1, 0, 'p'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "d:w:p:r:s", opts, "sched-credit2", 0) {
+    case 'd':
+        dom = optarg;
+        break;
+    case 'w':
+        weight = strtol(optarg, NULL, 10);
+        opt_w = true;
+        break;
+    case 's':
+        opt_s = true;
+        break;
+    case 'r':
+        ratelimit = strtol(optarg, NULL, 10);
+        opt_r = true;
+        break;
+    case 'p':
+        cpupool = optarg;
+        break;
+    }
+
+    if (cpupool && (dom || opt_w)) {
+        fprintf(stderr, "Specifying a cpupool is not allowed with other "
+                "options.\n");
+        return EXIT_FAILURE;
+    }
+    if (!dom && opt_w) {
+        fprintf(stderr, "Must specify a domain.\n");
+        return EXIT_FAILURE;
+    }
+
+    if (opt_s) {
+        libxl_sched_credit2_params scparam;
+        uint32_t poolid = 0;
+
+        if (cpupool) {
+            if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
+                                                     &poolid, NULL) ||
+                !libxl_cpupoolid_is_valid(ctx, poolid)) {
+                fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
+                return EXIT_FAILURE;
+            }
+        }
+
+        if (!opt_r) { /* Output scheduling parameters */
+            if (sched_credit2_pool_output(poolid))
+                return EXIT_FAILURE;
+        } else {      /* Set scheduling parameters (so far, just ratelimit) */
+            scparam.ratelimit_us = ratelimit;
+            if (sched_credit2_params_set(poolid, &scparam))
+                return EXIT_FAILURE;
+        }
+    } else if (!dom) { /* list all domain's credit scheduler info */
+        if (sched_domain_output(LIBXL_SCHEDULER_CREDIT2,
+                                sched_credit2_domain_output,
+                                sched_credit2_pool_output,
+                                cpupool))
+            return EXIT_FAILURE;
+    } else {
+        uint32_t domid = find_domain(dom);
+
+        if (!opt_w) { /* output credit2 scheduler info */
+            sched_credit2_domain_output(-1);
+            if (sched_credit2_domain_output(domid))
+                return EXIT_FAILURE;
+        } else { /* set credit2 scheduler paramaters */
+            libxl_domain_sched_params scinfo;
+            libxl_domain_sched_params_init(&scinfo);
+            scinfo.sched = LIBXL_SCHEDULER_CREDIT2;
+            if (opt_w)
+                scinfo.weight = weight;
+            rc = sched_domain_set(domid, &scinfo);
+            libxl_domain_sched_params_dispose(&scinfo);
+            if (rc)
+                return EXIT_FAILURE;
+        }
+    }
+
+    return EXIT_SUCCESS;
+}
+
+/*
+ * <nothing>            : List all domain paramters and sched params
+ * -d [domid]           : List default domain params for domain
+ * -d [domid] [params]  : Set domain params for domain
+ * -d [domid] -v [vcpuid 1] -v [vcpuid 2] ...  :
+ * List per-VCPU params for domain
+ * -d [domid] -v all  : List all per-VCPU params for domain
+ * -v all  : List all per-VCPU params for all domains
+ * -d [domid] -v [vcpuid 1] [params] -v [vcpuid 2] [params] ...  :
+ * Set per-VCPU params for domain
+ * -d [domid] -v all [params]  : Set all per-VCPU params for domain
+ */
+int main_sched_rtds(int argc, char **argv)
+{
+    const char *dom = NULL;
+    const char *cpupool = NULL;
+    int *vcpus = (int *)xmalloc(sizeof(int)); /* IDs of VCPUs that change */
+    int *periods = (int *)xmalloc(sizeof(int)); /* period is in microsecond */
+    int *budgets = (int *)xmalloc(sizeof(int)); /* budget is in microsecond */
+    int v_size = 1; /* size of vcpus array */
+    int p_size = 1; /* size of periods array */
+    int b_size = 1; /* size of budgets array */
+    int v_index = 0; /* index in vcpus array */
+    int p_index =0; /* index in periods array */
+    int b_index =0; /* index for in budgets array */
+    bool opt_p = false;
+    bool opt_b = false;
+    bool opt_v = false;
+    bool opt_all = false; /* output per-dom parameters */
+    int opt, i, rc, r;
+    static struct option opts[] = {
+        {"domain", 1, 0, 'd'},
+        {"period", 1, 0, 'p'},
+        {"budget", 1, 0, 'b'},
+        {"vcpuid",1, 0, 'v'},
+        {"cpupool", 1, 0, 'c'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "d:p:b:v:c", opts, "sched-rtds", 0) {
+    case 'd':
+        dom = optarg;
+        break;
+    case 'p':
+        if (p_index >= p_size) {
+            /*
+             * periods array is full
+             * double the array size for new elements
+             */
+            p_size *= 2;
+            periods = xrealloc(periods, p_size);
+        }
+        periods[p_index++] = strtol(optarg, NULL, 10);
+        opt_p = 1;
+        break;
+    case 'b':
+        if (b_index >= b_size) { /* budgets array is full */
+            b_size *= 2;
+            budgets = xrealloc(budgets, b_size);
+        }
+        budgets[b_index++] = strtol(optarg, NULL, 10);
+        opt_b = 1;
+        break;
+    case 'v':
+        if (!strcmp(optarg, "all")) { /* get or set all vcpus of a domain */
+            opt_all = 1;
+            break;
+        }
+        if (v_index >= v_size) { /* vcpus array is full */
+            v_size *= 2;
+            vcpus = xrealloc(vcpus, v_size);
+        }
+        vcpus[v_index++] = strtol(optarg, NULL, 10);
+        opt_v = 1;
+        break;
+    case 'c':
+        cpupool = optarg;
+        break;
+    }
+
+    if (cpupool && (dom || opt_p || opt_b || opt_v || opt_all)) {
+        fprintf(stderr, "Specifying a cpupool is not allowed with "
+                "other options.\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+    if (!dom && (opt_p || opt_b || opt_v)) {
+        fprintf(stderr, "Missing parameters.\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+    if (dom && !opt_v && !opt_all && (opt_p || opt_b)) {
+        fprintf(stderr, "Must specify VCPU.\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+    if (opt_v && opt_all) {
+        fprintf(stderr, "Incorrect VCPU IDs.\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+    if (((v_index > b_index) && opt_b) || ((v_index > p_index) && opt_p)
+        || p_index != b_index) {
+        fprintf(stderr, "Incorrect number of period and budget\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+
+    if ((!dom) && opt_all) {
+        /* get all domain's per-vcpu rtds scheduler parameters */
+        rc = -sched_vcpu_output(LIBXL_SCHEDULER_RTDS,
+                                sched_rtds_vcpu_output_all,
+                                sched_rtds_pool_output,
+                                cpupool);
+        if (rc) {
+            r = EXIT_FAILURE;
+            goto out;
+        }
+    } else if (!dom && !opt_all) {
+        /* list all domain's default scheduling parameters */
+        rc = -sched_domain_output(LIBXL_SCHEDULER_RTDS,
+                                  sched_rtds_domain_output,
+                                  sched_rtds_pool_output,
+                                  cpupool);
+        if (rc) {
+            r = EXIT_FAILURE;
+            goto out;
+        }
+    } else {
+        uint32_t domid = find_domain(dom);
+        if (!opt_v && !opt_all) { /* output default scheduling parameters */
+            sched_rtds_domain_output(-1);
+            rc = -sched_rtds_domain_output(domid);
+            if (rc) {
+                r = EXIT_FAILURE;
+                goto out;
+            }
+        } else if (!opt_p && !opt_b) {
+            /* get per-vcpu rtds scheduling parameters */
+            libxl_vcpu_sched_params scinfo;
+            libxl_vcpu_sched_params_init(&scinfo);
+            sched_rtds_vcpu_output(-1, &scinfo);
+            scinfo.num_vcpus = v_index;
+            if (v_index > 0) {
+                scinfo.vcpus = (libxl_sched_params *)
+                               xmalloc(sizeof(libxl_sched_params) * (v_index));
+                for (i = 0; i < v_index; i++)
+                    scinfo.vcpus[i].vcpuid = vcpus[i];
+                rc = -sched_rtds_vcpu_output(domid, &scinfo);
+            } else /* get params for all vcpus */
+                rc = -sched_rtds_vcpu_output_all(domid, &scinfo);
+            libxl_vcpu_sched_params_dispose(&scinfo);
+            if (rc) {
+                r = EXIT_FAILURE;
+                goto out;
+            }
+    } else if (opt_v || opt_all) {
+            /* set per-vcpu rtds scheduling parameters */
+            libxl_vcpu_sched_params scinfo;
+            libxl_vcpu_sched_params_init(&scinfo);
+            scinfo.sched = LIBXL_SCHEDULER_RTDS;
+            if (v_index > 0) {
+                scinfo.num_vcpus = v_index;
+                scinfo.vcpus = (libxl_sched_params *)
+                               xmalloc(sizeof(libxl_sched_params) * (v_index));
+                for (i = 0; i < v_index; i++) {
+                    scinfo.vcpus[i].vcpuid = vcpus[i];
+                    scinfo.vcpus[i].period = periods[i];
+                    scinfo.vcpus[i].budget = budgets[i];
+                }
+                rc = sched_vcpu_set(domid, &scinfo);
+            } else { /* set params for all vcpus */
+                scinfo.num_vcpus = 1;
+                scinfo.vcpus = (libxl_sched_params *)
+                               xmalloc(sizeof(libxl_sched_params));
+                scinfo.vcpus[0].period = periods[0];
+                scinfo.vcpus[0].budget = budgets[0];
+                rc = sched_vcpu_set_all(domid, &scinfo);
+            }
+
+            libxl_vcpu_sched_params_dispose(&scinfo);
+            if (rc) {
+                r = EXIT_FAILURE;
+                goto out;
+            }
+        }
+    }
+
+    r = EXIT_SUCCESS;
+out:
+    free(vcpus);
+    free(periods);
+    free(budgets);
+    return r;
+}
+
+int main_domid(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    const char *domname = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "domid", 1) {
+        /* No options */
+    }
+
+    domname = argv[optind];
+
+    if (libxl_name_to_domid(ctx, domname, &domid)) {
+        fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
+        return EXIT_FAILURE;
+    }
+
+    printf("%u\n", domid);
+
+    return EXIT_SUCCESS;
+}
+
+int main_domname(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    char *domname = NULL;
+    char *endptr = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "domname", 1) {
+        /* No options */
+    }
+
+    domid = strtol(argv[optind], &endptr, 10);
+    if (domid == 0 && !strcmp(endptr, argv[optind])) {
+        /*no digits at all*/
+        fprintf(stderr, "Invalid domain id.\n\n");
+        return EXIT_FAILURE;
+    }
+
+    domname = libxl_domid_to_name(ctx, domid);
+    if (!domname) {
+        fprintf(stderr, "Can't get domain name of domain id '%u', maybe this domain does not exist.\n", domid);
+        return EXIT_FAILURE;
+    }
+
+    printf("%s\n", domname);
+    free(domname);
+
+    return EXIT_SUCCESS;
+}
+
+int main_rename(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    const char *dom, *new_name;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "rename", 2) {
+        /* No options */
+    }
+
+    dom = argv[optind++];
+    new_name = argv[optind];
+
+    domid = find_domain(dom);
+    if (libxl_domain_rename(ctx, domid, common_domname, new_name)) {
+        fprintf(stderr, "Can't rename domain '%s'.\n", dom);
+        return 1;
+    }
+
+    return 0;
+}
+
+int main_trigger(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    char *endptr = NULL;
+    int vcpuid = 0;
+    const char *trigger_name = NULL;
+    libxl_trigger trigger;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "trigger", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind++]);
+
+    trigger_name = argv[optind++];
+    if (libxl_trigger_from_string(trigger_name, &trigger)) {
+        fprintf(stderr, "Invalid trigger \"%s\"\n", trigger_name);
+        return EXIT_FAILURE;
+    }
+
+    if (argv[optind]) {
+        vcpuid = strtol(argv[optind], &endptr, 10);
+        if (vcpuid == 0 && !strcmp(endptr, argv[optind])) {
+            fprintf(stderr, "Invalid vcpuid, using default vcpuid=0.\n\n");
+        }
+    }
+
+    libxl_send_trigger(ctx, domid, trigger, vcpuid);
+
+    return EXIT_SUCCESS;
+}
+
+
+int main_sysrq(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    const char *sysrq = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "sysrq", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind++]);
+
+    sysrq = argv[optind];
+
+    if (sysrq[1] != '\0') {
+        fprintf(stderr, "Invalid sysrq.\n\n");
+        help("sysrq");
+        return EXIT_FAILURE;
+    }
+
+    libxl_send_sysrq(ctx, domid, sysrq[0]);
+
+    return EXIT_SUCCESS;
+}
+
+int main_debug_keys(int argc, char **argv)
+{
+    int opt;
+    char *keys;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "debug-keys", 1) {
+        /* No options */
+    }
+
+    keys = argv[optind];
+
+    if (libxl_send_debug_keys(ctx, keys)) {
+        fprintf(stderr, "cannot send debug keys: %s\n", keys);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_dmesg(int argc, char **argv)
+{
+    unsigned int clear = 0;
+    libxl_xen_console_reader *cr;
+    char *line;
+    int opt, ret = 1;
+
+    SWITCH_FOREACH_OPT(opt, "c", NULL, "dmesg", 0) {
+    case 'c':
+        clear = 1;
+        break;
+    }
+
+    cr = libxl_xen_console_read_start(ctx, clear);
+    if (!cr)
+        goto finish;
+
+    while ((ret = libxl_xen_console_read_line(ctx, cr, &line)) > 0)
+        printf("%s", line);
+
+finish:
+    if (cr)
+        libxl_xen_console_read_finish(ctx, cr);
+    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+int main_top(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "top", 0) {
+        /* No options */
+    }
+
+    return system("xentop");
+}
+
+int main_networkattach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    libxl_device_nic nic;
+    XLU_Config *config = 0;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "network-attach", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+
+    config= xlu_cfg_init(stderr, "command line");
+    if (!config) {
+        fprintf(stderr, "Failed to allocate for configuration\n");
+        return 1;
+    }
+
+    libxl_device_nic_init(&nic);
+    set_default_nic_values(&nic);
+
+    for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
+        if (parse_nic_config(&nic, &config, *argv))
+            return 1;
+    }
+
+    if (dryrun_only) {
+        char *json = libxl_device_nic_to_json(ctx, &nic);
+        printf("vif: %s\n", json);
+        free(json);
+        libxl_device_nic_dispose(&nic);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_nic_add(ctx, domid, &nic, 0)) {
+        fprintf(stderr, "libxl_device_nic_add failed.\n");
+        return 1;
+    }
+    libxl_device_nic_dispose(&nic);
+    xlu_cfg_destroy(config);
+    return 0;
+}
+
+int main_networklist(int argc, char **argv)
+{
+    int opt;
+    libxl_device_nic *nics;
+    libxl_nicinfo nicinfo;
+    int nb, i;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "network-list", 1) {
+        /* No options */
+    }
+
+    /*      Idx  BE   MAC   Hdl  Sta  evch txr/rxr  BE-path */
+    printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
+           "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid = find_domain(*argv);
+        nics = libxl_device_nic_list(ctx, domid, &nb);
+        if (!nics) {
+            continue;
+        }
+        for (i = 0; i < nb; ++i) {
+            if (!libxl_device_nic_getinfo(ctx, domid, &nics[i], &nicinfo)) {
+                /* Idx BE */
+                printf("%-3d %-2d ", nicinfo.devid, nicinfo.backend_id);
+                /* MAC */
+                printf(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nics[i].mac));
+                /* Hdl  Sta  evch txr/rxr  BE-path */
+                printf("%6d %5d %6d %5d/%-11d %-30s\n",
+                       nicinfo.devid, nicinfo.state, nicinfo.evtch,
+                       nicinfo.rref_tx, nicinfo.rref_rx, nicinfo.backend);
+                libxl_nicinfo_dispose(&nicinfo);
+            }
+            libxl_device_nic_dispose(&nics[i]);
+        }
+        free(nics);
+    }
+    return 0;
+}
+
+int main_networkdetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    libxl_device_nic nic;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "network-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+
+    if (!strchr(argv[optind+1], ':')) {
+        if (libxl_devid_to_device_nic(ctx, domid, atoi(argv[optind+1]), &nic)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    } else {
+        if (libxl_mac_to_device_nic(ctx, domid, argv[optind+1], &nic)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    }
+    if (libxl_device_nic_remove(ctx, domid, &nic, 0)) {
+        fprintf(stderr, "libxl_device_nic_del failed.\n");
+        return 1;
+    }
+    libxl_device_nic_dispose(&nic);
+    return 0;
+}
+
+int main_channellist(int argc, char **argv)
+{
+    int opt;
+    libxl_device_channel *channels;
+    libxl_channelinfo channelinfo;
+    int nb, i;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "channel-list", 1) {
+        /* No options */
+    }
+
+    /*      Idx BE state evt-ch ring-ref connection params*/
+    printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
+           "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid = find_domain(*argv);
+        channels = libxl_device_channel_list(ctx, domid, &nb);
+        if (!channels)
+            continue;
+        for (i = 0; i < nb; ++i) {
+            if (!libxl_device_channel_getinfo(ctx, domid, &channels[i],
+                &channelinfo)) {
+                printf("%-3d %-2d ", channels[i].devid, channelinfo.backend_id);
+                printf("%-5d ", channelinfo.state);
+                printf("%-6d %-8d ", channelinfo.evtch, channelinfo.rref);
+                printf("%-10s ", libxl_channel_connection_to_string(
+                       channels[i].connection));
+                switch (channels[i].connection) {
+                    case LIBXL_CHANNEL_CONNECTION_PTY:
+                        printf("%-30s ", channelinfo.u.pty.path);
+                        break;
+                    default:
+                        break;
+                }
+                printf("\n");
+                libxl_channelinfo_dispose(&channelinfo);
+            }
+            libxl_device_channel_dispose(&channels[i]);
+        }
+        free(channels);
+    }
+    return 0;
+}
+
+int main_blockattach(int argc, char **argv)
+{
+    int opt;
+    uint32_t fe_domid;
+    libxl_device_disk disk;
+    XLU_Config *config = 0;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "block-attach", 2) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    optind++;
+
+    parse_disk_config_multistring
+        (&config, argc-optind, (const char* const*)argv + optind, &disk);
+
+    if (dryrun_only) {
+        char *json = libxl_device_disk_to_json(ctx, &disk);
+        printf("disk: %s\n", json);
+        free(json);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_disk_add(ctx, fe_domid, &disk, 0)) {
+        fprintf(stderr, "libxl_device_disk_add failed.\n");
+        return 1;
+    }
+    return 0;
+}
+
+int main_blocklist(int argc, char **argv)
+{
+    int opt;
+    int i, nb;
+    libxl_device_disk *disks;
+    libxl_diskinfo diskinfo;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "block-list", 1) {
+        /* No options */
+    }
+
+    printf("%-5s %-3s %-6s %-5s %-6s %-8s %-30s\n",
+           "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid;
+        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            continue;
+        }
+        disks = libxl_device_disk_list(ctx, domid, &nb);
+        if (!disks) {
+            continue;
+        }
+        for (i=0; i<nb; i++) {
+            if (!libxl_device_disk_getinfo(ctx, domid, &disks[i], &diskinfo)) {
+                /*      Vdev BE   hdl  st   evch rref BE-path*/
+                printf("%-5d %-3d %-6d %-5d %-6d %-8d %-30s\n",
+                       diskinfo.devid, diskinfo.backend_id, diskinfo.frontend_id,
+                       diskinfo.state, diskinfo.evtch, diskinfo.rref, diskinfo.backend);
+                libxl_diskinfo_dispose(&diskinfo);
+            }
+            libxl_device_disk_dispose(&disks[i]);
+        }
+        free(disks);
+    }
+    return 0;
+}
+
+int main_blockdetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc = 0;
+    libxl_device_disk disk;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "block-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+
+    if (libxl_vdev_to_device_disk(ctx, domid, argv[optind+1], &disk)) {
+        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
+        return 1;
+    }
+    rc = libxl_device_disk_remove(ctx, domid, &disk, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_disk_remove failed.\n");
+        return 1;
+    }
+    libxl_device_disk_dispose(&disk);
+    return rc;
+}
+
+int main_vtpmattach(int argc, char **argv)
+{
+    int opt;
+    libxl_device_vtpm vtpm;
+    char *oparg;
+    uint32_t domid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-attach", 1) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    ++optind;
+
+    libxl_device_vtpm_init(&vtpm);
+    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
+        if (MATCH_OPTION("uuid", *argv, oparg)) {
+            if(libxl_uuid_from_string(&(vtpm.uuid), oparg)) {
+                fprintf(stderr, "Invalid uuid specified (%s)\n", oparg);
+                return 1;
+            }
+        } else if (MATCH_OPTION("backend", *argv, oparg)) {
+            replace_string(&vtpm.backend_domname, oparg);
+        } else {
+            fprintf(stderr, "unrecognized argument `%s'\n", *argv);
+            return 1;
+        }
+    }
+
+    if(dryrun_only) {
+       char* json = libxl_device_vtpm_to_json(ctx, &vtpm);
+       printf("vtpm: %s\n", json);
+       free(json);
+       libxl_device_vtpm_dispose(&vtpm);
+       if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+       return 0;
+    }
+
+    if (libxl_device_vtpm_add(ctx, domid, &vtpm, 0)) {
+        fprintf(stderr, "libxl_device_vtpm_add failed.\n");
+        return 1;
+    }
+    libxl_device_vtpm_dispose(&vtpm);
+    return 0;
+}
+
+int main_vtpmlist(int argc, char **argv)
+{
+    int opt;
+    libxl_device_vtpm *vtpms;
+    libxl_vtpminfo vtpminfo;
+    int nb, i;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-list", 1) {
+        /* No options */
+    }
+
+    /*      Idx  BE   UUID   Hdl  Sta  evch rref  BE-path */
+    printf("%-3s %-2s %-36s %-6s %-5s %-6s %-5s %-10s\n",
+           "Idx", "BE", "Uuid", "handle", "state", "evt-ch", "ring-ref", "BE-path");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid;
+        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            continue;
+        }
+        if (!(vtpms = libxl_device_vtpm_list(ctx, domid, &nb))) {
+            continue;
+        }
+        for (i = 0; i < nb; ++i) {
+           if(!libxl_device_vtpm_getinfo(ctx, domid, &vtpms[i], &vtpminfo)) {
+              /*      Idx  BE     UUID             Hdl Sta evch rref BE-path*/
+              printf("%-3d %-2d " LIBXL_UUID_FMT " %6d %5d %6d %8d %-30s\n",
+                    vtpminfo.devid, vtpminfo.backend_id,
+                    LIBXL_UUID_BYTES(vtpminfo.uuid),
+                    vtpminfo.devid, vtpminfo.state, vtpminfo.evtch,
+                    vtpminfo.rref, vtpminfo.backend);
+
+              libxl_vtpminfo_dispose(&vtpminfo);
+           }
+           libxl_device_vtpm_dispose(&vtpms[i]);
+        }
+        free(vtpms);
+    }
+    return 0;
+}
+
+int main_vtpmdetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc=0;
+    libxl_device_vtpm vtpm;
+    libxl_uuid uuid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+
+    if ( libxl_uuid_from_string(&uuid, argv[optind+1])) {
+        if (libxl_devid_to_device_vtpm(ctx, domid, atoi(argv[optind+1]), &vtpm)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    } else {
+        if (libxl_uuid_to_device_vtpm(ctx, domid, &uuid, &vtpm)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    }
+    rc = libxl_device_vtpm_remove(ctx, domid, &vtpm, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_vtpm_remove failed.\n");
+    }
+    libxl_device_vtpm_dispose(&vtpm);
+    return rc;
+}
+
+
+static char *uptime_to_string(unsigned long uptime, int short_mode)
+{
+    int sec, min, hour, day;
+    char *time_string;
+
+    day = (int)(uptime / 86400);
+    uptime -= (day * 86400);
+    hour = (int)(uptime / 3600);
+    uptime -= (hour * 3600);
+    min = (int)(uptime / 60);
+    uptime -= (min * 60);
+    sec = uptime;
+
+    if (short_mode)
+        if (day > 1)
+            xasprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
+        else if (day == 1)
+            xasprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
+        else
+            xasprintf(&time_string, "%2d:%02d", hour, min);
+    else
+        if (day > 1)
+            xasprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
+        else if (day == 1)
+            xasprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
+        else
+            xasprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
+
+    return time_string;
+}
+
+int main_claims(int argc, char **argv)
+{
+    libxl_dominfo *info;
+    int opt;
+    int nb_domain;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "claims", 0) {
+        /* No options */
+    }
+
+    if (!claim_mode)
+        fprintf(stderr, "claim_mode not enabled (see man xl.conf).\n");
+
+    info = libxl_list_domain(ctx, &nb_domain);
+    if (!info) {
+        fprintf(stderr, "libxl_list_domain failed.\n");
+        return 1;
+    }
+
+    list_domains(false /* verbose */, false /* context */, true /* claim */,
+                 false /* numa */, false /* cpupool */, info, nb_domain);
+
+    libxl_dominfo_list_free(info, nb_domain);
+    return 0;
+}
+
+static char *current_time_to_string(time_t now)
+{
+    char now_str[100];
+    struct tm *tmp;
+
+    tmp = localtime(&now);
+    if (tmp == NULL) {
+        fprintf(stderr, "Get localtime error");
+        exit(-1);
+    }
+    if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
+        fprintf(stderr, "strftime returned 0");
+        exit(-1);
+    }
+    return strdup(now_str);
+}
+
+static void print_dom0_uptime(int short_mode, time_t now)
+{
+    int fd;
+    ssize_t nr;
+    char buf[512];
+    uint32_t uptime = 0;
+    char *uptime_str = NULL;
+    char *now_str = NULL;
+    char *domname;
+
+    fd = open("/proc/uptime", O_RDONLY);
+    if (fd == -1)
+        goto err;
+
+    nr = read(fd, buf, sizeof(buf) - 1);
+    if (nr == -1) {
+        close(fd);
+        goto err;
+    }
+    close(fd);
+
+    buf[nr] = '\0';
+
+    strtok(buf, " ");
+    uptime = strtoul(buf, NULL, 10);
+
+    domname = libxl_domid_to_name(ctx, 0);
+    if (short_mode)
+    {
+        now_str = current_time_to_string(now);
+        uptime_str = uptime_to_string(uptime, 1);
+        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
+               domname, 0);
+    }
+    else
+    {
+        now_str = NULL;
+        uptime_str = uptime_to_string(uptime, 0);
+        printf("%-33s %4d %s\n", domname,
+               0, uptime_str);
+    }
+
+    free(now_str);
+    free(uptime_str);
+    free(domname);
+    return;
+err:
+    fprintf(stderr, "Can not get Dom0 uptime.\n");
+    exit(-1);
+}
+
+static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
+{
+    uint32_t s_time = 0;
+    uint32_t uptime = 0;
+    char *uptime_str = NULL;
+    char *now_str = NULL;
+    char *domname;
+
+    s_time = libxl_vm_get_start_time(ctx, domuid);
+    if (s_time == -1)
+        return;
+    uptime = now - s_time;
+    domname = libxl_domid_to_name(ctx, domuid);
+    if (short_mode)
+    {
+        now_str = current_time_to_string(now);
+        uptime_str = uptime_to_string(uptime, 1);
+        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
+               domname, domuid);
+    }
+    else
+    {
+        now_str = NULL;
+        uptime_str = uptime_to_string(uptime, 0);
+        printf("%-33s %4d %s\n", domname,
+               domuid, uptime_str);
+    }
+
+    free(domname);
+    free(now_str);
+    free(uptime_str);
+    return;
+}
+
+static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
+{
+    libxl_vminfo *info;
+    time_t now;
+    int nb_vm, i;
+
+    now = time(NULL);
+
+    if (!short_mode)
+        printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
+
+    if (nb_doms == 0) {
+        print_dom0_uptime(short_mode, now);
+        info = libxl_list_vm(ctx, &nb_vm);
+        if (info == NULL) {
+            fprintf(stderr, "Could not list vms.\n");
+            return;
+        }
+        for (i = 0; i < nb_vm; i++) {
+            if (info[i].domid == 0) continue;
+            print_domU_uptime(info[i].domid, short_mode, now);
+        }
+        libxl_vminfo_list_free(info, nb_vm);
+    } else {
+        for (i = 0; i < nb_doms; i++) {
+            if (doms[i] == 0)
+                print_dom0_uptime(short_mode, now);
+            else
+                print_domU_uptime(doms[i], short_mode, now);
+        }
+    }
+}
+
+int main_uptime(int argc, char **argv)
+{
+    const char *dom;
+    int short_mode = 0;
+    uint32_t domains[100];
+    int nb_doms = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "s", NULL, "uptime", 0) {
+    case 's':
+        short_mode = 1;
+        break;
+    }
+
+    for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
+        domains[nb_doms] = find_domain(dom);
+
+    print_uptime(short_mode, domains, nb_doms);
+
+    return 0;
+}
+
+int main_tmem_list(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *dom = NULL;
+    char *buf = NULL;
+    int use_long = 0;
+    int all = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "al", NULL, "tmem-list", 0) {
+    case 'l':
+        use_long = 1;
+        break;
+    case 'a':
+        all = 1;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-list");
+        return 1;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = find_domain(dom);
+
+    buf = libxl_tmem_list(ctx, domid, use_long);
+    if (buf == NULL)
+        return EXIT_FAILURE;
+
+    printf("%s\n", buf);
+    free(buf);
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_freeze(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *dom = NULL;
+    int all = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "a", NULL, "tmem-freeze", 0) {
+    case 'a':
+        all = 1;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-freeze");
+        return EXIT_FAILURE;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = find_domain(dom);
+
+    if (libxl_tmem_freeze(ctx, domid) < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_thaw(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *dom = NULL;
+    int all = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "a", NULL, "tmem-thaw", 0) {
+    case 'a':
+        all = 1;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-thaw");
+        return EXIT_FAILURE;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = find_domain(dom);
+
+    if (libxl_tmem_thaw(ctx, domid) < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_set(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *dom = NULL;
+    uint32_t weight = 0, cap = 0, compress = 0;
+    int opt_w = 0, opt_c = 0, opt_p = 0;
+    int all = 0;
+    int opt;
+    int rc = 0;
+
+    SWITCH_FOREACH_OPT(opt, "aw:c:p:", NULL, "tmem-set", 0) {
+    case 'a':
+        all = 1;
+        break;
+    case 'w':
+        weight = strtol(optarg, NULL, 10);
+        opt_w = 1;
+        break;
+    case 'c':
+        cap = strtol(optarg, NULL, 10);
+        opt_c = 1;
+        break;
+    case 'p':
+        compress = strtol(optarg, NULL, 10);
+        opt_p = 1;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-set");
+        return EXIT_FAILURE;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = find_domain(dom);
+
+    if (!opt_w && !opt_c && !opt_p) {
+        fprintf(stderr, "No set value specified.\n\n");
+        help("tmem-set");
+        return EXIT_FAILURE;
+    }
+
+    if (opt_w)
+        rc = libxl_tmem_set(ctx, domid, "weight", weight);
+    if (opt_c)
+        rc = libxl_tmem_set(ctx, domid, "cap", cap);
+    if (opt_p)
+        rc = libxl_tmem_set(ctx, domid, "compress", compress);
+
+    if (rc < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_shared_auth(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *autharg = NULL;
+    char *endptr = NULL;
+    const char *dom = NULL;
+    char *uuid = NULL;
+    int auth = -1;
+    int all = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "au:A:", NULL, "tmem-shared-auth", 0) {
+    case 'a':
+        all = 1;
+        break;
+    case 'u':
+        uuid = optarg;
+        break;
+    case 'A':
+        autharg = optarg;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-shared-auth");
+        return EXIT_FAILURE;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = find_domain(dom);
+
+    if (uuid == NULL || autharg == NULL) {
+        fprintf(stderr, "No uuid or auth specified.\n\n");
+        help("tmem-shared-auth");
+        return EXIT_FAILURE;
+    }
+
+    auth = strtol(autharg, &endptr, 10);
+    if (*endptr != '\0') {
+        fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_tmem_shared_auth(ctx, domid, uuid, auth) < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_freeable(int argc, char **argv)
+{
+    int opt;
+    int mb;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "tmem-freeable", 0) {
+        /* No options */
+    }
+
+    mb = libxl_tmem_freeable(ctx);
+    if (mb == -1)
+        return EXIT_FAILURE;
+
+    printf("%d\n", mb);
+    return EXIT_SUCCESS;
+}
+
+int main_cpupoolcreate(int argc, char **argv)
+{
+    const char *filename = NULL, *config_src=NULL;
+    const char *p;
+    char *extra_config = NULL;
+    int opt;
+    static struct option opts[] = {
+        {"defconfig", 1, 0, 'f'},
+        {"dryrun", 0, 0, 'n'},
+        COMMON_LONG_OPTS
+    };
+    int ret;
+    char *config_data = 0;
+    int config_len = 0;
+    XLU_Config *config;
+    const char *buf;
+    char *name = NULL;
+    uint32_t poolid;
+    libxl_scheduler sched = 0;
+    XLU_ConfigList *cpus;
+    XLU_ConfigList *nodes;
+    int n_cpus, n_nodes, i, n;
+    libxl_bitmap freemap;
+    libxl_bitmap cpumap;
+    libxl_uuid uuid;
+    libxl_cputopology *topology;
+    int rc = EXIT_FAILURE;
+
+    SWITCH_FOREACH_OPT(opt, "nf:", opts, "cpupool-create", 0) {
+    case 'f':
+        filename = optarg;
+        break;
+    case 'n':
+        dryrun_only = 1;
+        break;
+    }
+
+    libxl_bitmap_init(&freemap);
+    libxl_bitmap_init(&cpumap);
+
+    while (optind < argc) {
+        if ((p = strchr(argv[optind], '='))) {
+            string_realloc_append(&extra_config, "\n");
+            string_realloc_append(&extra_config, argv[optind]);
+        } else if (!filename) {
+            filename = argv[optind];
+        } else {
+            help("cpupool-create");
+            goto out;
+        }
+        optind++;
+    }
+
+    if (filename)
+    {
+        if (libxl_read_file_contents(ctx, filename, (void **)&config_data,
+                                     &config_len)) {
+            fprintf(stderr, "Failed to read config file: %s: %s\n",
+                    filename, strerror(errno));
+            goto out;
+        }
+        config_src=filename;
+    }
+    else
+        config_src="command line";
+
+    if (extra_config && strlen(extra_config)) {
+        if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
+            fprintf(stderr, "Failed to attach extra configuration\n");
+            goto out;
+        }
+        config_data = xrealloc(config_data,
+                               config_len + strlen(extra_config) + 2);
+        if (!config_data) {
+            fprintf(stderr, "Failed to realloc config_data\n");
+            goto out;
+        }
+        config_data[config_len] = 0;
+        strcat(config_data, extra_config);
+        strcat(config_data, "\n");
+        config_len += strlen(extra_config) + 1;
+    }
+
+    config = xlu_cfg_init(stderr, config_src);
+    if (!config) {
+        fprintf(stderr, "Failed to allocate for configuration\n");
+        goto out;
+    }
+
+    ret = xlu_cfg_readdata(config, config_data, config_len);
+    if (ret) {
+        fprintf(stderr, "Failed to parse config file: %s\n", strerror(ret));
+        goto out_cfg;
+    }
+
+    if (!xlu_cfg_get_string (config, "name", &buf, 0))
+        name = strdup(buf);
+    else if (filename)
+        name = libxl_basename(filename);
+    else {
+        fprintf(stderr, "Missing cpupool name!\n");
+        goto out_cfg;
+    }
+    if (!libxl_name_to_cpupoolid(ctx, name, &poolid)) {
+        fprintf(stderr, "Pool name \"%s\" already exists\n", name);
+        goto out_cfg;
+    }
+
+    if (!xlu_cfg_get_string (config, "sched", &buf, 0)) {
+        if ((libxl_scheduler_from_string(buf, &sched)) < 0) {
+            fprintf(stderr, "Unknown scheduler\n");
+            goto out_cfg;
+        }
+    } else {
+        rc = libxl_get_scheduler(ctx);
+        if (rc < 0) {
+            fprintf(stderr, "get_scheduler sysctl failed.\n");
+            goto out_cfg;
+        }
+        sched = rc;
+    }
+
+    if (libxl_get_freecpus(ctx, &freemap)) {
+        fprintf(stderr, "libxl_get_freecpus failed\n");
+        goto out_cfg;
+    }
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
+        fprintf(stderr, "Failed to allocate cpumap\n");
+        goto out_cfg;
+    }
+    if (!xlu_cfg_get_list(config, "nodes", &nodes, 0, 0)) {
+        int nr;
+        n_cpus = 0;
+        n_nodes = 0;
+        topology = libxl_get_cpu_topology(ctx, &nr);
+        if (topology == NULL) {
+            fprintf(stderr, "libxl_get_topologyinfo failed\n");
+            goto out_cfg;
+        }
+        while ((buf = xlu_cfg_get_listitem(nodes, n_nodes)) != NULL) {
+            n = atoi(buf);
+            for (i = 0; i < nr; i++) {
+                if ((topology[i].node == n) &&
+                    libxl_bitmap_test(&freemap, i)) {
+                    libxl_bitmap_set(&cpumap, i);
+                    n_cpus++;
+                }
+            }
+            n_nodes++;
+        }
+
+        libxl_cputopology_list_free(topology, nr);
+
+        if (n_cpus == 0) {
+            fprintf(stderr, "no free cpu found\n");
+            goto out_cfg;
+        }
+    } else if (!xlu_cfg_get_list(config, "cpus", &cpus, 0, 1)) {
+        n_cpus = 0;
+        while ((buf = xlu_cfg_get_listitem(cpus, n_cpus)) != NULL) {
+            i = atoi(buf);
+            if ((i < 0) || !libxl_bitmap_test(&freemap, i)) {
+                fprintf(stderr, "cpu %d illegal or not free\n", i);
+                goto out_cfg;
+            }
+            libxl_bitmap_set(&cpumap, i);
+            n_cpus++;
+        }
+    } else if (!xlu_cfg_get_string(config, "cpus", &buf, 0)) {
+        if (cpurange_parse(buf, &cpumap))
+            goto out_cfg;
+
+        n_cpus = 0;
+        libxl_for_each_set_bit(i, cpumap) {
+            if (!libxl_bitmap_test(&freemap, i)) {
+                fprintf(stderr, "cpu %d illegal or not free\n", i);
+                goto out_cfg;
+            }
+            n_cpus++;
+        }
+    } else
+        n_cpus = 0;
+
+    libxl_uuid_generate(&uuid);
+
+    printf("Using config file \"%s\"\n", config_src);
+    printf("cpupool name:   %s\n", name);
+    printf("scheduler:      %s\n", libxl_scheduler_to_string(sched));
+    printf("number of cpus: %d\n", n_cpus);
+
+    if (!dryrun_only) {
+        poolid = LIBXL_CPUPOOL_POOLID_ANY;
+        if (libxl_cpupool_create(ctx, name, sched, cpumap, &uuid, &poolid)) {
+            fprintf(stderr, "error on creating cpupool\n");
+            goto out_cfg;
+        }
+    }
+    /* We made it! */
+    rc = EXIT_SUCCESS;
+   
+out_cfg:
+    xlu_cfg_destroy(config);
+out:
+    libxl_bitmap_dispose(&freemap);
+    libxl_bitmap_dispose(&cpumap);
+    free(name);
+    free(config_data);
+    free(extra_config);
+    return rc;
+}
+
+int main_cpupoollist(int argc, char **argv)
+{
+    int opt;
+    static struct option opts[] = {
+        {"cpus", 0, 0, 'c'},
+        COMMON_LONG_OPTS
+    };
+    int opt_cpus = 0;
+    const char *pool = NULL;
+    libxl_cpupoolinfo *poolinfo;
+    int n_pools, p, c, n;
+    uint32_t poolid;
+    char *name;
+
+    SWITCH_FOREACH_OPT(opt, "c", opts, "cpupool-list", 0) {
+    case 'c':
+        opt_cpus = 1;
+        break;
+    }
+
+    if (optind < argc) {
+        pool = argv[optind];
+        if (libxl_name_to_cpupoolid(ctx, pool, &poolid)) {
+            fprintf(stderr, "Pool \'%s\' does not exist\n", pool);
+            return EXIT_FAILURE;
+        }
+    }
+
+    poolinfo = libxl_list_cpupool(ctx, &n_pools);
+    if (!poolinfo) {
+        fprintf(stderr, "error getting cpupool info\n");
+        return EXIT_FAILURE;
+    }
+
+    printf("%-19s", "Name");
+    if (opt_cpus)
+        printf("CPU list\n");
+    else
+        printf("CPUs   Sched     Active   Domain count\n");
+
+    for (p = 0; p < n_pools; p++) {
+        if (!pool || (poolinfo[p].poolid == poolid)) {
+            name = poolinfo[p].pool_name;
+            printf("%-19s", name);
+            n = 0;
+            libxl_for_each_bit(c, poolinfo[p].cpumap)
+                if (libxl_bitmap_test(&poolinfo[p].cpumap, c)) {
+                    if (n && opt_cpus) printf(",");
+                    if (opt_cpus) printf("%d", c);
+                    n++;
+                }
+            if (!opt_cpus) {
+                printf("%3d %9s       y       %4d", n,
+                       libxl_scheduler_to_string(poolinfo[p].sched),
+                       poolinfo[p].n_dom);
+            }
+            printf("\n");
+        }
+    }
+
+    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
+
+    return EXIT_SUCCESS;
+}
+
+int main_cpupooldestroy(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    uint32_t poolid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-destroy", 1) {
+        /* No options */
+    }
+
+    pool = argv[optind];
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_cpupool_destroy(ctx, poolid)) {
+        fprintf(stderr, "Can't destroy cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_cpupoolrename(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    const char *new_name;
+    uint32_t poolid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-rename", 2) {
+        /* No options */
+    }
+
+    pool = argv[optind++];
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    new_name = argv[optind];
+
+    if (libxl_cpupool_rename(ctx, new_name, poolid)) {
+        fprintf(stderr, "Can't rename cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_cpupoolcpuadd(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    uint32_t poolid;
+    libxl_bitmap cpumap;
+    int rc = EXIT_FAILURE;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-cpu-add", 2) {
+        /* No options */
+    }
+
+    libxl_bitmap_init(&cpumap);
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
+        fprintf(stderr, "Unable to allocate cpumap");
+        return EXIT_FAILURE;
+    }
+
+    pool = argv[optind++];
+    if (cpurange_parse(argv[optind], &cpumap))
+        goto out;
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
+        goto out;
+    }
+
+    if (libxl_cpupool_cpuadd_cpumap(ctx, poolid, &cpumap))
+        fprintf(stderr, "some cpus may not have been added to %s\n", pool);
+
+    rc = EXIT_SUCCESS;
+
+out:
+    libxl_bitmap_dispose(&cpumap);
+    return rc;
+}
+
+int main_cpupoolcpuremove(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    uint32_t poolid;
+    libxl_bitmap cpumap;
+    int rc = EXIT_FAILURE;
+
+    libxl_bitmap_init(&cpumap);
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
+        fprintf(stderr, "Unable to allocate cpumap");
+        return EXIT_FAILURE;
+    }
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-cpu-remove", 2) {
+        /* No options */
+    }
+
+    pool = argv[optind++];
+    if (cpurange_parse(argv[optind], &cpumap))
+        goto out;
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
+        goto out;
+    }
+
+    if (libxl_cpupool_cpuremove_cpumap(ctx, poolid, &cpumap)) {
+        fprintf(stderr, "Some cpus may have not or only partially been removed from '%s'.\n", pool);
+        fprintf(stderr, "If a cpu can't be added to another cpupool, add it to '%s' again and retry.\n", pool);
+    }
+
+    rc = EXIT_SUCCESS;
+
+out:
+    libxl_bitmap_dispose(&cpumap);
+    return rc;
+}
+
+int main_cpupoolmigrate(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    uint32_t poolid;
+    const char *dom;
+    uint32_t domid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-migrate", 2) {
+        /* No options */
+    }
+
+    dom = argv[optind++];
+    pool = argv[optind];
+
+    if (libxl_domain_qualifier_to_domid(ctx, dom, &domid) ||
+        !libxl_domid_to_name(ctx, domid)) {
+        fprintf(stderr, "unknown domain '%s'\n", dom);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_cpupool_movedomain(ctx, poolid, domid))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_cpupoolnumasplit(int argc, char **argv)
+{
+    int rc;
+    int opt;
+    int p;
+    int c;
+    int n;
+    uint32_t poolid;
+    libxl_scheduler sched;
+    int n_pools;
+    int node;
+    int n_cpus;
+    char *name = NULL;
+    libxl_uuid uuid;
+    libxl_bitmap cpumap;
+    libxl_cpupoolinfo *poolinfo;
+    libxl_cputopology *topology;
+    libxl_dominfo info;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-numa-split", 0) {
+        /* No options */
+    }
+
+    libxl_dominfo_init(&info);
+
+    rc = EXIT_FAILURE;
+
+    libxl_bitmap_init(&cpumap);
+    poolinfo = libxl_list_cpupool(ctx, &n_pools);
+    if (!poolinfo) {
+        fprintf(stderr, "error getting cpupool info\n");
+        return EXIT_FAILURE;
+    }
+    poolid = poolinfo[0].poolid;
+    sched = poolinfo[0].sched;
+    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
+
+    if (n_pools > 1) {
+        fprintf(stderr, "splitting not possible, already cpupools in use\n");
+        return EXIT_FAILURE;
+    }
+
+    topology = libxl_get_cpu_topology(ctx, &n_cpus);
+    if (topology == NULL) {
+        fprintf(stderr, "libxl_get_topologyinfo failed\n");
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
+        fprintf(stderr, "Failed to allocate cpumap\n");
+        goto out;
+    }
+
+    /* Reset Pool-0 to 1st node: first add cpus, then remove cpus to avoid
+       a cpupool without cpus in between */
+
+    node = topology[0].node;
+    if (libxl_cpupool_cpuadd_node(ctx, 0, node, &n)) {
+        fprintf(stderr, "error on adding cpu to Pool 0\n");
+        goto out;
+    }
+
+    xasprintf(&name, "Pool-node%d", node);
+    if (libxl_cpupool_rename(ctx, name, 0)) {
+        fprintf(stderr, "error on renaming Pool 0\n");
+        goto out;
+    }
+
+    n = 0;
+    for (c = 0; c < n_cpus; c++) {
+        if (topology[c].node == node) {
+            topology[c].node = LIBXL_CPUTOPOLOGY_INVALID_ENTRY;
+            libxl_bitmap_set(&cpumap, n);
+            n++;
+        }
+    }
+    if (libxl_domain_info(ctx, &info, 0)) {
+        fprintf(stderr, "error on getting info for Domain-0\n");
+        goto out;
+    }
+    if (info.vcpu_online > n && libxl_set_vcpuonline(ctx, 0, &cpumap)) {
+        fprintf(stderr, "error on removing vcpus for Domain-0\n");
+        goto out;
+    }
+    for (c = 0; c < 10; c++) {
+        /* We've called libxl_dominfo_init before the loop and will
+         * call libxl_dominfo_dispose after the loop when we're done
+         * with info.
+         */
+        libxl_dominfo_dispose(&info);
+        libxl_dominfo_init(&info);
+        if (libxl_domain_info(ctx, &info, 0)) {
+            fprintf(stderr, "error on getting info for Domain-0\n");
+            goto out;
+        }
+        if (info.vcpu_online <= n) {
+            break;
+        }
+        sleep(1);
+    }
+    if (info.vcpu_online > n) {
+        fprintf(stderr, "failed to offline vcpus\n");
+        goto out;
+    }
+    libxl_bitmap_set_none(&cpumap);
+
+    for (c = 0; c < n_cpus; c++) {
+        if (topology[c].node == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) {
+            continue;
+        }
+
+        node = topology[c].node;
+        if (libxl_cpupool_cpuremove_node(ctx, 0, node, &n)) {
+            fprintf(stderr, "error on removing cpu from Pool 0\n");
+            goto out;
+        }
+
+        free(name);
+        xasprintf(&name, "Pool-node%d", node);
+        libxl_uuid_generate(&uuid);
+        poolid = 0;
+        if (libxl_cpupool_create(ctx, name, sched, cpumap, &uuid, &poolid)) {
+            fprintf(stderr, "error on creating cpupool\n");
+            goto out;
+        }
+
+        if (libxl_cpupool_cpuadd_node(ctx, poolid, node, &n)) {
+            fprintf(stderr, "error on adding cpus to cpupool\n");
+            goto out;
+        }
+
+        for (p = c; p < n_cpus; p++) {
+            if (topology[p].node == node) {
+                topology[p].node = LIBXL_CPUTOPOLOGY_INVALID_ENTRY;
+            }
+        }
+    }
+
+    rc = EXIT_SUCCESS;
+
+out:
+    libxl_cputopology_list_free(topology, n_cpus);
+    libxl_bitmap_dispose(&cpumap);
+    libxl_dominfo_dispose(&info);
+    free(name);
+
+    return rc;
+}
+
+int main_getenforce(int argc, char **argv)
+{
+    int ret;
+
+    ret = libxl_flask_getenforce(ctx);
+
+    if (ret < 0) {
+        if (errno == ENOSYS)
+            printf("Flask XSM Disabled\n");
+        else
+            fprintf(stderr, "Failed to get enforcing mode\n");
+    }
+    else if (ret == 1)
+        printf("Enforcing\n");
+    else if (ret == 0)
+        printf("Permissive\n");
+
+    return ret;
+}
+
+int main_setenforce(int argc, char **argv)
+{
+    int ret, mode;
+    const char *p = NULL;
+
+    if (optind >= argc) {
+        help("setenforce");
+        return 2;
+    }
+
+    p = argv[optind];
+
+    if (!strcmp(p, "0"))
+        mode = 0;
+    else if (!strcmp(p, "1"))
+        mode = 1;
+    else if (!strcasecmp(p, "permissive"))
+        mode = 0;
+    else if (!strcasecmp(p, "enforcing"))
+        mode = 1;
+    else {
+        help("setenforce");
+        return 2;
+    }
+
+    ret = libxl_flask_setenforce(ctx, mode);
+
+    if (ret) {
+        if (errno == ENOSYS) {
+            fprintf(stderr, "Flask XSM disabled\n");
+        }
+        else
+            fprintf(stderr, "error occured while setting enforcing mode (%i)\n", ret);
+    }
+
+    return ret;
+}
+
+int main_loadpolicy(int argc, char **argv)
+{
+    const char *polFName;
+    int polFd = -1;
+    void *polMemCp = NULL;
+    struct stat info;
+    int ret;
+
+    if (optind >= argc) {
+        help("loadpolicy");
+        return 2;
+    }
+
+    polFName = argv[optind];
+    polFd = open(polFName, O_RDONLY);
+    if (polFd < 0) {
+        fprintf(stderr, "Error occurred opening policy file '%s': %s\n",
+                polFName, strerror(errno));
+        ret = -1;
+        goto done;
+    }
+
+    ret = stat(polFName, &info);
+    if (ret < 0) {
+        fprintf(stderr, "Error occurred retrieving information about"
+                "policy file '%s': %s\n", polFName, strerror(errno));
+        goto done;
+    }
+
+    polMemCp = malloc(info.st_size);
+
+    ret = read(polFd, polMemCp, info.st_size);
+    if ( ret < 0 ) {
+        fprintf(stderr, "Unable to read new Flask policy file: %s\n",
+                strerror(errno));
+        goto done;
+    }
+
+    ret = libxl_flask_loadpolicy(ctx, polMemCp, info.st_size);
+
+    if (ret < 0) {
+        if (errno == ENOSYS) {
+            fprintf(stderr, "Flask XSM disabled\n");
+        } else {
+            errno = -ret;
+            fprintf(stderr, "Unable to load new Flask policy: %s\n",
+                    strerror(errno));
+            ret = -1;
+        }
+    } else {
+        printf("Successfully loaded policy.\n");
+    }
+
+done:
+    free(polMemCp);
+    if (polFd >= 0)
+        close(polFd);
+
+    return ret;
+}
+
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+int main_remus(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc, daemonize = 1;
+    const char *ssh_command = "ssh";
+    char *host = NULL, *rune = NULL;
+    libxl_domain_remus_info r_info;
+    int send_fd = -1, recv_fd = -1;
+    pid_t child = -1;
+    uint8_t *config_data;
+    int config_len;
+
+    memset(&r_info, 0, sizeof(libxl_domain_remus_info));
+
+    SWITCH_FOREACH_OPT(opt, "Fbundi:s:N:ec", NULL, "remus", 2) {
+    case 'i':
+        r_info.interval = atoi(optarg);
+        break;
+    case 'F':
+        libxl_defbool_set(&r_info.allow_unsafe, true);
+        break;
+    case 'b':
+        libxl_defbool_set(&r_info.blackhole, true);
+        break;
+    case 'u':
+        libxl_defbool_set(&r_info.compression, false);
+        break;
+    case 'n':
+        libxl_defbool_set(&r_info.netbuf, false);
+        break;
+    case 'N':
+        r_info.netbufscript = optarg;
+        break;
+    case 'd':
+        libxl_defbool_set(&r_info.diskbuf, false);
+        break;
+    case 's':
+        ssh_command = optarg;
+        break;
+    case 'e':
+        daemonize = 0;
+        break;
+    case 'c':
+        libxl_defbool_set(&r_info.colo, true);
+    }
+
+    domid = find_domain(argv[optind]);
+    host = argv[optind + 1];
+
+    /* Defaults */
+    libxl_defbool_setdefault(&r_info.blackhole, false);
+    libxl_defbool_setdefault(&r_info.colo, false);
+    if (!libxl_defbool_val(r_info.colo) && !r_info.interval)
+        r_info.interval = 200;
+
+    if (libxl_defbool_val(r_info.colo)) {
+        if (r_info.interval || libxl_defbool_val(r_info.blackhole) ||
+            !libxl_defbool_is_default(r_info.netbuf) ||
+            !libxl_defbool_is_default(r_info.diskbuf)) {
+            perror("option -c is conflict with -i, -d, -n or -b");
+            exit(-1);
+        }
+
+        if (libxl_defbool_is_default(r_info.compression)) {
+            perror("COLO can't be used with memory compression. "
+                   "Disable memory checkpoint compression now...");
+            libxl_defbool_set(&r_info.compression, false);
+        }
+    }
+
+    if (!r_info.netbufscript) {
+        if (libxl_defbool_val(r_info.colo))
+            r_info.netbufscript = default_colo_proxy_script;
+        else
+            r_info.netbufscript = default_remus_netbufscript;
+    }
+
+    if (libxl_defbool_val(r_info.blackhole)) {
+        send_fd = open("/dev/null", O_RDWR, 0644);
+        if (send_fd < 0) {
+            perror("failed to open /dev/null");
+            exit(EXIT_FAILURE);
+        }
+    } else {
+
+        if (!ssh_command[0]) {
+            rune = host;
+        } else {
+            if (!libxl_defbool_val(r_info.colo)) {
+                xasprintf(&rune, "exec %s %s xl migrate-receive %s %s",
+                          ssh_command, host,
+                          "-r",
+                          daemonize ? "" : " -e");
+            } else {
+                xasprintf(&rune, "exec %s %s xl migrate-receive %s %s %s %s",
+                          ssh_command, host,
+                          "--colo",
+                          r_info.netbufscript ? "--coloft-script" : "",
+                          r_info.netbufscript ? r_info.netbufscript : "",
+                          daemonize ? "" : " -e");
+            }
+        }
+
+        save_domain_core_begin(domid, NULL, &config_data, &config_len);
+
+        if (!config_len) {
+            fprintf(stderr, "No config file stored for running domain and "
+                    "none supplied - cannot start remus.\n");
+            exit(EXIT_FAILURE);
+        }
+
+        child = create_migration_child(rune, &send_fd, &recv_fd);
+
+        migrate_do_preamble(send_fd, recv_fd, child, config_data, config_len,
+                            rune);
+
+        if (ssh_command[0])
+            free(rune);
+    }
+
+    /* Point of no return */
+    rc = libxl_domain_remus_start(ctx, &r_info, domid, send_fd, recv_fd, 0);
+
+    /* check if the domain exists. User may have xl destroyed the
+     * domain to force failover
+     */
+    if (libxl_domain_info(ctx, 0, domid)) {
+        fprintf(stderr, "%s: Primary domain has been destroyed.\n",
+                libxl_defbool_val(r_info.colo) ? "COLO" : "Remus");
+        close(send_fd);
+        return EXIT_SUCCESS;
+    }
+
+    /* If we are here, it means remus setup/domain suspend/backup has
+     * failed. Try to resume the domain and exit gracefully.
+     * TODO: Split-Brain check.
+     */
+    if (rc == ERROR_GUEST_TIMEDOUT)
+        fprintf(stderr, "Failed to suspend domain at primary.\n");
+    else {
+        fprintf(stderr, "%s: Backup failed? resuming domain at primary.\n",
+                libxl_defbool_val(r_info.colo) ? "COLO" : "Remus");
+        libxl_domain_resume(ctx, domid, 1, 0);
+    }
+
+    close(send_fd);
+    return EXIT_FAILURE;
+}
+#endif
+
+int main_devd(int argc, char **argv)
+{
+    int ret = 0, opt = 0, daemonize = 1;
+    const char *pidfile = NULL;
+    static const struct option opts[] = {
+        {"pidfile", 1, 0, 'p'},
+        COMMON_LONG_OPTS,
+        {0, 0, 0, 0}
+    };
+
+    SWITCH_FOREACH_OPT(opt, "Fp:", opts, "devd", 0) {
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'p':
+        pidfile = optarg;
+        break;
+    }
+
+    if (daemonize) {
+        ret = do_daemonize("xldevd", pidfile);
+        if (ret) {
+            ret = (ret == 1) ? 0 : ret;
+            goto out;
+        }
+    }
+
+    libxl_device_events_handler(ctx, 0);
+
+out:
+    return ret;
+}
+
+#ifdef LIBXL_HAVE_PSR_CMT
+static int psr_cmt_hwinfo(void)
+{
+    int rc;
+    int enabled;
+    uint32_t total_rmid;
+
+    printf("Cache Monitoring Technology (CMT):\n");
+
+    enabled = libxl_psr_cmt_enabled(ctx);
+    printf("%-16s: %s\n", "Enabled", enabled ? "1" : "0");
+    if (!enabled)
+        return 0;
+
+    rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
+    if (rc) {
+        fprintf(stderr, "Failed to get max RMID value\n");
+        return rc;
+    }
+    printf("%-16s: %u\n", "Total RMID", total_rmid);
+
+    printf("Supported monitor types:\n");
+    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY))
+        printf("cache-occupancy\n");
+    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT))
+        printf("total-mem-bandwidth\n");
+    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT))
+        printf("local-mem-bandwidth\n");
+
+    return rc;
+}
+
+#define MBM_SAMPLE_RETRY_MAX 4
+static int psr_cmt_get_mem_bandwidth(uint32_t domid,
+                                     libxl_psr_cmt_type type,
+                                     uint32_t socketid,
+                                     uint64_t *bandwidth_r)
+{
+    uint64_t sample1, sample2;
+    uint64_t tsc1, tsc2;
+    int retry_attempts = 0;
+    int rc;
+
+    while (1) {
+        rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
+                                      &sample1, &tsc1);
+        if (rc < 0)
+            return rc;
+
+        usleep(10000);
+
+        rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
+                                      &sample2, &tsc2);
+        if (rc < 0)
+            return rc;
+
+        if (tsc2 <= tsc1)
+            return -1;
+
+        /*
+         * Hardware guarantees at most 1 overflow can happen if the duration
+         * between two samples is less than 1 second. Note that tsc returned
+         * from hypervisor is already-scaled time(ns).
+         */
+        if (tsc2 - tsc1 < 1000000000 && sample2 >= sample1)
+            break;
+
+        if (retry_attempts < MBM_SAMPLE_RETRY_MAX) {
+            retry_attempts++;
+        } else {
+            fprintf(stderr, "event counter overflowed\n");
+            return -1;
+        }
+    }
+
+    *bandwidth_r = (sample2 - sample1) * 1000000000 / (tsc2 - tsc1) / 1024;
+    return 0;
+}
+
+static void psr_cmt_print_domain_info(libxl_dominfo *dominfo,
+                                      libxl_psr_cmt_type type,
+                                      libxl_bitmap *socketmap)
+{
+    char *domain_name;
+    uint32_t socketid;
+    uint64_t monitor_data;
+
+    if (!libxl_psr_cmt_domain_attached(ctx, dominfo->domid))
+        return;
+
+    domain_name = libxl_domid_to_name(ctx, dominfo->domid);
+    printf("%-40s %5d", domain_name, dominfo->domid);
+    free(domain_name);
+
+    libxl_for_each_set_bit(socketid, *socketmap) {
+        switch (type) {
+        case LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY:
+            if (!libxl_psr_cmt_get_sample(ctx, dominfo->domid, type, socketid,
+                                          &monitor_data, NULL))
+                printf("%13"PRIu64" KB", monitor_data / 1024);
+            break;
+        case LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT:
+        case LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT:
+            if (!psr_cmt_get_mem_bandwidth(dominfo->domid, type, socketid,
+                                           &monitor_data))
+                printf("%11"PRIu64" KB/s", monitor_data);
+            break;
+        default:
+            return;
+        }
+    }
+
+    printf("\n");
+}
+
+static int psr_cmt_show(libxl_psr_cmt_type type, uint32_t domid)
+{
+    uint32_t i, socketid, total_rmid;
+    uint32_t l3_cache_size;
+    libxl_bitmap socketmap;
+    int rc, nr_domains;
+
+    if (!libxl_psr_cmt_enabled(ctx)) {
+        fprintf(stderr, "CMT is disabled in the system\n");
+        return -1;
+    }
+
+    if (!libxl_psr_cmt_type_supported(ctx, type)) {
+        fprintf(stderr, "Monitor type '%s' is not supported in the system\n",
+                libxl_psr_cmt_type_to_string(type));
+        return -1;
+    }
+
+    libxl_bitmap_init(&socketmap);
+    libxl_socket_bitmap_alloc(ctx, &socketmap, 0);
+    rc = libxl_get_online_socketmap(ctx, &socketmap);
+    if (rc < 0) {
+        fprintf(stderr, "Failed getting available sockets, rc: %d\n", rc);
+        goto out;
+    }
+
+    rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
+    if (rc < 0) {
+        fprintf(stderr, "Failed to get max RMID value\n");
+        goto out;
+    }
+
+    printf("Total RMID: %d\n", total_rmid);
+
+    /* Header */
+    printf("%-40s %5s", "Name", "ID");
+    libxl_for_each_set_bit(socketid, socketmap)
+        printf("%14s %d", "Socket", socketid);
+    printf("\n");
+
+    if (type == LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY) {
+            /* Total L3 cache size */
+            printf("%-46s", "Total L3 Cache Size");
+            libxl_for_each_set_bit(socketid, socketmap) {
+                rc = libxl_psr_cmt_get_l3_cache_size(ctx, socketid,
+                                                     &l3_cache_size);
+                if (rc < 0) {
+                    fprintf(stderr,
+                            "Failed to get system l3 cache size for socket:%d\n",
+                            socketid);
+                    goto out;
+                }
+                printf("%13u KB", l3_cache_size);
+            }
+            printf("\n");
+    }
+
+    /* Each domain */
+    if (domid != INVALID_DOMID) {
+        libxl_dominfo dominfo;
+
+        libxl_dominfo_init(&dominfo);
+        if (libxl_domain_info(ctx, &dominfo, domid)) {
+            fprintf(stderr, "Failed to get domain info for %d\n", domid);
+            rc = -1;
+            goto out;
+        }
+        psr_cmt_print_domain_info(&dominfo, type, &socketmap);
+        libxl_dominfo_dispose(&dominfo);
+    }
+    else
+    {
+        libxl_dominfo *list;
+        if (!(list = libxl_list_domain(ctx, &nr_domains))) {
+            fprintf(stderr, "Failed to get domain info for domain list.\n");
+            rc = -1;
+            goto out;
+        }
+        for (i = 0; i < nr_domains; i++)
+            psr_cmt_print_domain_info(list + i, type, &socketmap);
+        libxl_dominfo_list_free(list, nr_domains);
+    }
+
+out:
+    libxl_bitmap_dispose(&socketmap);
+    return rc;
+}
+
+int main_psr_cmt_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, ret = 0;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-attach", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    ret = libxl_psr_cmt_attach(ctx, domid);
+
+    return ret;
+}
+
+int main_psr_cmt_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, ret = 0;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-detach", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    ret = libxl_psr_cmt_detach(ctx, domid);
+
+    return ret;
+}
+
+int main_psr_cmt_show(int argc, char **argv)
+{
+    int opt, ret = 0;
+    uint32_t domid;
+    libxl_psr_cmt_type type;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-show", 1) {
+        /* No options */
+    }
+
+    if (!strcmp(argv[optind], "cache-occupancy"))
+        type = LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY;
+    else if (!strcmp(argv[optind], "total-mem-bandwidth"))
+        type = LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT;
+    else if (!strcmp(argv[optind], "local-mem-bandwidth"))
+        type = LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT;
+    else {
+        help("psr-cmt-show");
+        return 2;
+    }
+
+    if (optind + 1 >= argc)
+        domid = INVALID_DOMID;
+    else if (optind + 1 == argc - 1)
+        domid = find_domain(argv[optind + 1]);
+    else {
+        help("psr-cmt-show");
+        return 2;
+    }
+
+    ret = psr_cmt_show(type, domid);
+
+    return ret;
+}
+#endif
+
+#ifdef LIBXL_HAVE_PSR_CAT
+static int psr_cat_hwinfo(void)
+{
+    int rc;
+    int i, nr;
+    uint32_t l3_cache_size;
+    libxl_psr_cat_info *info;
+
+    printf("Cache Allocation Technology (CAT):\n");
+
+    rc = libxl_psr_cat_get_l3_info(ctx, &info, &nr);
+    if (rc) {
+        fprintf(stderr, "Failed to get cat info\n");
+        return rc;
+    }
+
+    for (i = 0; i < nr; i++) {
+        rc = libxl_psr_cmt_get_l3_cache_size(ctx, info[i].id, &l3_cache_size);
+        if (rc) {
+            fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
+                    info[i].id);
+            goto out;
+        }
+        printf("%-16s: %u\n", "Socket ID", info[i].id);
+        printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
+        printf("%-16s: %s\n", "CDP Status",
+               info[i].cdp_enabled ? "Enabled" : "Disabled");
+        printf("%-16s: %u\n", "Maximum COS", info[i].cos_max);
+        printf("%-16s: %u\n", "CBM length", info[i].cbm_len);
+        printf("%-16s: %#llx\n", "Default CBM",
+               (1ull << info[i].cbm_len) - 1);
+    }
+
+out:
+    libxl_psr_cat_info_list_free(info, nr);
+    return rc;
+}
+
+static void psr_cat_print_one_domain_cbm_type(uint32_t domid, uint32_t socketid,
+                                              libxl_psr_cbm_type type)
+{
+    uint64_t cbm;
+
+    if (!libxl_psr_cat_get_cbm(ctx, domid, type, socketid, &cbm))
+        printf("%#16"PRIx64, cbm);
+    else
+        printf("%16s", "error");
+}
+
+static void psr_cat_print_one_domain_cbm(uint32_t domid, uint32_t socketid,
+                                         bool cdp_enabled)
+{
+    char *domain_name;
+
+    domain_name = libxl_domid_to_name(ctx, domid);
+    printf("%5d%25s", domid, domain_name);
+    free(domain_name);
+
+    if (!cdp_enabled) {
+        psr_cat_print_one_domain_cbm_type(domid, socketid,
+                                          LIBXL_PSR_CBM_TYPE_L3_CBM);
+    } else {
+        psr_cat_print_one_domain_cbm_type(domid, socketid,
+                                          LIBXL_PSR_CBM_TYPE_L3_CBM_CODE);
+        psr_cat_print_one_domain_cbm_type(domid, socketid,
+                                          LIBXL_PSR_CBM_TYPE_L3_CBM_DATA);
+    }
+
+    printf("\n");
+}
+
+static int psr_cat_print_domain_cbm(uint32_t domid, uint32_t socketid,
+                                    bool cdp_enabled)
+{
+    int i, nr_domains;
+    libxl_dominfo *list;
+
+    if (domid != INVALID_DOMID) {
+        psr_cat_print_one_domain_cbm(domid, socketid, cdp_enabled);
+        return 0;
+    }
+
+    if (!(list = libxl_list_domain(ctx, &nr_domains))) {
+        fprintf(stderr, "Failed to get domain list for cbm display\n");
+        return -1;
+    }
+
+    for (i = 0; i < nr_domains; i++)
+        psr_cat_print_one_domain_cbm(list[i].domid, socketid, cdp_enabled);
+    libxl_dominfo_list_free(list, nr_domains);
+
+    return 0;
+}
+
+static int psr_cat_print_socket(uint32_t domid, libxl_psr_cat_info *info)
+{
+    int rc;
+    uint32_t l3_cache_size;
+
+    rc = libxl_psr_cmt_get_l3_cache_size(ctx, info->id, &l3_cache_size);
+    if (rc) {
+        fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
+                info->id);
+        return -1;
+    }
+
+    printf("%-16s: %u\n", "Socket ID", info->id);
+    printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
+    printf("%-16s: %#llx\n", "Default CBM", (1ull << info->cbm_len) - 1);
+    if (info->cdp_enabled)
+        printf("%5s%25s%16s%16s\n", "ID", "NAME", "CBM (code)", "CBM (data)");
+    else
+        printf("%5s%25s%16s\n", "ID", "NAME", "CBM");
+
+    return psr_cat_print_domain_cbm(domid, info->id, info->cdp_enabled);
+}
+
+static int psr_cat_show(uint32_t domid)
+{
+    int i, nr;
+    int rc;
+    libxl_psr_cat_info *info;
+
+    rc = libxl_psr_cat_get_l3_info(ctx, &info, &nr);
+    if (rc) {
+        fprintf(stderr, "Failed to get cat info\n");
+        return rc;
+    }
+
+    for (i = 0; i < nr; i++) {
+        rc = psr_cat_print_socket(domid, info + i);
+        if (rc)
+            goto out;
+    }
+
+out:
+    libxl_psr_cat_info_list_free(info, nr);
+    return rc;
+}
+
+int main_psr_cat_cbm_set(int argc, char **argv)
+{
+    uint32_t domid;
+    libxl_psr_cbm_type type;
+    uint64_t cbm;
+    int ret, opt = 0;
+    int opt_data = 0, opt_code = 0;
+    libxl_bitmap target_map;
+    char *value;
+    libxl_string_list socket_list;
+    unsigned long start, end;
+    int i, j, len;
+
+    static struct option opts[] = {
+        {"socket", 1, 0, 's'},
+        {"data", 0, 0, 'd'},
+        {"code", 0, 0, 'c'},
+        COMMON_LONG_OPTS
+    };
+
+    libxl_socket_bitmap_alloc(ctx, &target_map, 0);
+    libxl_bitmap_set_none(&target_map);
+
+    SWITCH_FOREACH_OPT(opt, "s:cd", opts, "psr-cat-cbm-set", 2) {
+    case 's':
+        trim(isspace, optarg, &value);
+        split_string_into_string_list(value, ",", &socket_list);
+        len = libxl_string_list_length(&socket_list);
+        for (i = 0; i < len; i++) {
+            parse_range(socket_list[i], &start, &end);
+            for (j = start; j <= end; j++)
+                libxl_bitmap_set(&target_map, j);
+        }
+
+        libxl_string_list_dispose(&socket_list);
+        free(value);
+        break;
+    case 'd':
+        opt_data = 1;
+        break;
+    case 'c':
+        opt_code = 1;
+        break;
+    }
+
+    if (opt_data && opt_code) {
+        fprintf(stderr, "Cannot handle -c and -d at the same time\n");
+        return -1;
+    } else if (opt_data) {
+        type = LIBXL_PSR_CBM_TYPE_L3_CBM_DATA;
+    } else if (opt_code) {
+        type = LIBXL_PSR_CBM_TYPE_L3_CBM_CODE;
+    } else {
+        type = LIBXL_PSR_CBM_TYPE_L3_CBM;
+    }
+
+    if (libxl_bitmap_is_empty(&target_map))
+        libxl_bitmap_set_any(&target_map);
+
+    if (argc != optind + 2) {
+        help("psr-cat-cbm-set");
+        return 2;
+    }
+
+    domid = find_domain(argv[optind]);
+    cbm = strtoll(argv[optind + 1], NULL , 0);
+
+    ret = libxl_psr_cat_set_cbm(ctx, domid, type, &target_map, cbm);
+
+    libxl_bitmap_dispose(&target_map);
+    return ret;
+}
+
+int main_psr_cat_show(int argc, char **argv)
+{
+    int opt;
+    uint32_t domid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cat-show", 0) {
+        /* No options */
+    }
+
+    if (optind >= argc)
+        domid = INVALID_DOMID;
+    else if (optind == argc - 1)
+        domid = find_domain(argv[optind]);
+    else {
+        help("psr-cat-show");
+        return 2;
+    }
+
+    return psr_cat_show(domid);
+}
+
+int main_psr_hwinfo(int argc, char **argv)
+{
+    int opt, ret = 0;
+    bool all = true, cmt = false, cat = false;
+    static struct option opts[] = {
+        {"cmt", 0, 0, 'm'},
+        {"cat", 0, 0, 'a'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "ma", opts, "psr-hwinfo", 0) {
+    case 'm':
+        all = false; cmt = true;
+        break;
+    case 'a':
+        all = false; cat = true;
+        break;
+    }
+
+    if (!ret && (all || cmt))
+        ret = psr_cmt_hwinfo();
+
+    if (!ret && (all || cat))
+        ret = psr_cat_hwinfo();
+
+    return ret;
+}
+
+#endif
+
+int main_qemu_monitor_command(int argc, char **argv)
+{
+    int opt;
+    uint32_t domid;
+    char *cmd;
+    char *output;
+    int ret;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "qemu-monitor-command", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    cmd = argv[optind + 1];
+
+    if (argc - optind > 2) {
+        fprintf(stderr, "Invalid arguments.\n");
+        return EXIT_FAILURE;
+    }
+
+    ret = libxl_qemu_monitor_command(ctx, domid, cmd, &output);
+    if (!ret && output) {
+        printf("%s\n", output);
+        free(output);
+    }
+
+    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_cmdtable.c b/tools/xl/xl_cmdtable.c
new file mode 100644 (file)
index 0000000..588d5d9
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * Author Yang Hongyang <yanghy@cn.fujitsu.com>
+ *
+ * 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 <string.h>
+
+#include "libxl.h"
+#include "xl.h"
+
+struct cmd_spec cmd_table[] = {
+    { "create",
+      &main_create, 1, 1,
+      "Create a domain from config file <filename>",
+      "<ConfigFile> [options] [vars]",
+      "-h                      Print this help.\n"
+      "-p                      Leave the domain paused after it is created.\n"
+      "-c                      Connect to the console after the domain is created.\n"
+      "-f FILE, --defconfig=FILE\n                     Use the given configuration file.\n"
+      "-q, --quiet             Quiet.\n"
+      "-n, --dryrun            Dry run - prints the resulting configuration\n"
+      "                         (deprecated in favour of global -N option).\n"
+      "-d                      Enable debug messages.\n"
+      "-F                      Run in foreground until death of the domain.\n"
+      "-e                      Do not wait in the background for the death of the domain.\n"
+      "-V, --vncviewer         Connect to the VNC display after the domain is created.\n"
+      "-A, --vncviewer-autopass\n"
+      "                        Pass VNC password to viewer via stdin."
+    },
+    { "config-update",
+      &main_config_update, 1, 1,
+      "Update a running domain's saved configuration, used when rebuilding "
+      "the domain after reboot.\n"
+      "WARNING: xl now has better capability to manage domain configuration, "
+      "avoid using this command when possible",
+      "<Domain> <ConfigFile> [options] [vars]",
+      "-h                      Print this help.\n"
+      "-f FILE, --defconfig=FILE\n                     Use the given configuration file.\n"
+      "-d                      Enable debug messages.\n"
+    },
+    { "list",
+      &main_list, 0, 0,
+      "List information about all/some domains",
+      "[options] [Domain]\n",
+      "-l, --long              Output all VM details\n"
+      "-v, --verbose           Prints out UUIDs and security context\n"
+      "-Z, --context           Prints out security context\n"
+      "-c, --cpupool           Prints the cpupool the domain is in\n"
+      "-n, --numa              Prints out NUMA node affinity"
+    },
+    { "destroy",
+      &main_destroy, 0, 1,
+      "Terminate a domain immediately",
+      "[options] <Domain>\n",
+      "-f                      Permit destroying domain 0, which will only succeed\n"
+      "                        when run from disaggregated toolstack domain with a\n"
+      "                        hardware domain distinct from domain 0."
+    },
+    { "shutdown",
+      &main_shutdown, 0, 1,
+      "Issue a shutdown signal to a domain",
+      "[options] <-a|Domain>",
+      "-a, --all               Shutdown all guest domains.\n"
+      "-h                      Print this help.\n"
+      "-F                      Fallback to ACPI power event for HVM guests with\n"
+      "                        no PV drivers.\n"
+      "-w, --wait              Wait for guest(s) to shutdown.\n"
+    },
+    { "reboot",
+      &main_reboot, 0, 1,
+      "Issue a reboot signal to a domain",
+      "[options] <-a|Domain>",
+      "-a, --all               Shutdown all guest domains.\n"
+      "-h                      Print this help.\n"
+      "-F                      Fallback to ACPI reset event for HVM guests with\n"
+      "                        no PV drivers.\n"
+      "-w, --wait              Wait for guest(s) to reboot.\n"
+    },
+    { "pci-attach",
+      &main_pciattach, 0, 1,
+      "Insert a new pass-through pci device",
+      "<Domain> <BDF> [Virtual Slot]",
+    },
+    { "pci-detach",
+      &main_pcidetach, 0, 1,
+      "Remove a domain's pass-through pci device",
+      "<Domain> <BDF>",
+    },
+    { "pci-list",
+      &main_pcilist, 0, 0,
+      "List pass-through pci devices for a domain",
+      "<Domain>",
+    },
+    { "pci-assignable-add",
+      &main_pciassignable_add, 0, 1,
+      "Make a device assignable for pci-passthru",
+      "<BDF>",
+      "-h                      Print this help.\n"
+    },
+    { "pci-assignable-remove",
+      &main_pciassignable_remove, 0, 1,
+      "Remove a device from being assignable",
+      "[options] <BDF>",
+      "-h                      Print this help.\n"
+      "-r                      Attempt to re-assign the device to the\n"
+      "                        original driver"
+    },
+    { "pci-assignable-list",
+      &main_pciassignable_list, 0, 0,
+      "List all the assignable pci devices",
+      "",
+    },
+    { "pause",
+      &main_pause, 0, 1,
+      "Pause execution of a domain",
+      "<Domain>",
+    },
+    { "unpause",
+      &main_unpause, 0, 1,
+      "Unpause a paused domain",
+      "<Domain>",
+    },
+    { "console",
+      &main_console, 0, 0,
+      "Attach to domain's console",
+      "[options] <Domain>\n"
+      "-t <type>       console type, pv or serial\n"
+      "-n <number>     console number"
+    },
+    { "vncviewer",
+      &main_vncviewer, 0, 0,
+      "Attach to domain's VNC server.",
+      "[options] <Domain>\n"
+      "--autopass               Pass VNC password to viewer via stdin and\n"
+      "                         -autopass\n"
+      "--vncviewer-autopass     (consistency alias for --autopass)"
+    },
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+    { "save",
+      &main_save, 0, 1,
+      "Save a domain state to restore later",
+      "[options] <Domain> <CheckpointFile> [<ConfigFile>]",
+      "-h  Print this help.\n"
+      "-c  Leave domain running after creating the snapshot.\n"
+      "-p  Leave domain paused after creating the snapshot."
+    },
+    { "migrate",
+      &main_migrate, 0, 1,
+      "Migrate a domain to another host",
+      "[options] <Domain> <host>",
+      "-h              Print this help.\n"
+      "-C <config>     Send <config> instead of config file from creation.\n"
+      "-s <sshcommand> Use <sshcommand> instead of ssh.  String will be passed\n"
+      "                to sh. If empty, run <host> instead of ssh <host> xl\n"
+      "                migrate-receive [-d -e]\n"
+      "-e              Do not wait in the background (on <host>) for the death\n"
+      "                of the domain.\n"
+      "--debug         Print huge (!) amount of debug during the migration process.\n"
+      "-p              Do not unpause domain after migrating it."
+    },
+    { "restore",
+      &main_restore, 0, 1,
+      "Restore a domain from a saved state",
+      "[options] [<ConfigFile>] <CheckpointFile>",
+      "-h                       Print this help.\n"
+      "-p                       Do not unpause domain after restoring it.\n"
+      "-e                       Do not wait in the background for the death of the domain.\n"
+      "-d                       Enable debug messages.\n"
+      "-V, --vncviewer          Connect to the VNC display after the domain is created.\n"
+      "-A, --vncviewer-autopass Pass VNC password to viewer via stdin."
+    },
+    { "migrate-receive",
+      &main_migrate_receive, 0, 1,
+      "Restore a domain from a saved state",
+      "- for internal use only",
+    },
+#endif
+    { "dump-core",
+      &main_dump_core, 0, 1,
+      "Core dump a domain",
+      "<Domain> <filename>"
+    },
+    { "cd-insert",
+      &main_cd_insert, 1, 1,
+      "Insert a cdrom into a guest's cd drive",
+      "<Domain> <VirtualDevice> <path>",
+    },
+    { "cd-eject",
+      &main_cd_eject, 1, 1,
+      "Eject a cdrom from a guest's cd drive",
+      "<Domain> <VirtualDevice>",
+    },
+    { "mem-max",
+      &main_memmax, 0, 1,
+      "Set the maximum amount reservation for a domain",
+      "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
+    },
+    { "mem-set",
+      &main_memset, 0, 1,
+      "Set the current memory usage for a domain",
+      "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
+    },
+    { "button-press",
+      &main_button_press, 0, 1,
+      "Indicate an ACPI button press to the domain",
+      "<Domain> <Button>",
+      "<Button> may be 'power' or 'sleep'."
+    },
+    { "vcpu-list",
+      &main_vcpulist, 0, 0,
+      "List the VCPUs for all/some domains",
+      "[Domain, ...]",
+    },
+    { "vcpu-pin",
+      &main_vcpupin, 1, 1,
+      "Set which CPUs a VCPU can use",
+      "[option] <Domain> <VCPU|all> <Hard affinity|-|all> <Soft affinity|-|all>",
+      "-f, --force        undo an override pinning done by the kernel",
+    },
+    { "vcpu-set",
+      &main_vcpuset, 0, 1,
+      "Set the number of active VCPUs allowed for the domain",
+      "[option] <Domain> <vCPUs>",
+      "-i, --ignore-host  Don't limit the vCPU based on the host CPU count",
+    },
+    { "vm-list",
+      &main_vm_list, 0, 0,
+      "List guest domains, excluding dom0, stubdoms, etc.",
+      "",
+    },
+    { "info",
+      &main_info, 0, 0,
+      "Get information about Xen host",
+      "-n, --numa         List host NUMA topology information",
+    },
+    { "sharing",
+      &main_sharing, 0, 0,
+      "Get information about page sharing",
+      "[Domain]", 
+    },
+    { "sched-credit",
+      &main_sched_credit, 0, 1,
+      "Get/set credit scheduler parameters",
+      "[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]] [-s [-t TSLICE] [-r RATELIMIT]] [-p CPUPOOL]",
+      "-d DOMAIN, --domain=DOMAIN        Domain to modify\n"
+      "-w WEIGHT, --weight=WEIGHT        Weight (int)\n"
+      "-c CAP, --cap=CAP                 Cap (int)\n"
+      "-s         --schedparam           Query / modify scheduler parameters\n"
+      "-t TSLICE, --tslice_ms=TSLICE     Set the timeslice, in milliseconds\n"
+      "-r RLIMIT, --ratelimit_us=RLIMIT  Set the scheduling rate limit, in microseconds\n"
+      "-p CPUPOOL, --cpupool=CPUPOOL     Restrict output to CPUPOOL"
+    },
+    { "sched-credit2",
+      &main_sched_credit2, 0, 1,
+      "Get/set credit2 scheduler parameters",
+      "[-d <Domain> [-w[=WEIGHT]]] [-p CPUPOOL]",
+      "-d DOMAIN, --domain=DOMAIN     Domain to modify\n"
+      "-w WEIGHT, --weight=WEIGHT     Weight (int)\n"
+      "-s         --schedparam        Query / modify scheduler parameters\n"
+      "-r RLIMIT, --ratelimit_us=RLIMIT Set the scheduling rate limit, in microseconds\n"
+      "-p CPUPOOL, --cpupool=CPUPOOL  Restrict output to CPUPOOL"
+    },
+    { "sched-rtds",
+      &main_sched_rtds, 0, 1,
+      "Get/set rtds scheduler parameters",
+      "[-d <Domain> [-v[=VCPUID/all]] [-p[=PERIOD]] [-b[=BUDGET]]]",
+      "-d DOMAIN, --domain=DOMAIN     Domain to modify\n"
+      "-v VCPUID/all, --vcpuid=VCPUID/all    VCPU to modify or output;\n"
+      "               Using '-v all' to modify/output all vcpus\n"
+      "-p PERIOD, --period=PERIOD     Period (us)\n"
+      "-b BUDGET, --budget=BUDGET     Budget (us)\n"
+    },
+    { "domid",
+      &main_domid, 0, 0,
+      "Convert a domain name to domain id",
+      "<DomainName>",
+    },
+    { "domname",
+      &main_domname, 0, 0,
+      "Convert a domain id to domain name",
+      "<DomainId>",
+    },
+    { "rename",
+      &main_rename, 0, 1,
+      "Rename a domain",
+      "<Domain> <NewDomainName>",
+    },
+    { "trigger",
+      &main_trigger, 0, 1,
+      "Send a trigger to a domain",
+      "<Domain> <nmi|reset|init|power|sleep|s3resume> [<VCPU>]",
+    },
+    { "sysrq",
+      &main_sysrq, 0, 1,
+      "Send a sysrq to a domain",
+      "<Domain> <letter>",
+    },
+    { "debug-keys",
+      &main_debug_keys, 0, 1,
+      "Send debug keys to Xen",
+      "<Keys>",
+    },
+    { "dmesg",
+      &main_dmesg, 0, 0,
+      "Read and/or clear dmesg buffer",
+      "[-c]",
+      "  -c                        Clear dmesg buffer as well as printing it",
+    },
+    { "top",
+      &main_top, 0, 0,
+      "Monitor a host and the domains in real time",
+      "",
+    },
+    { "network-attach",
+      &main_networkattach, 1, 1,
+      "Create a new virtual network device",
+      "<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] "
+      "[ip=<ip>] [script=<script>] [backend=<BackDomain>] [vifname=<name>] "
+      "[rate=<rate>] [model=<model>] [accel=<accel>]",
+    },
+    { "network-list",
+      &main_networklist, 0, 0,
+      "List virtual network interfaces for a domain",
+      "<Domain(s)>",
+    },
+    { "network-detach",
+      &main_networkdetach, 0, 1,
+      "Destroy a domain's virtual network device",
+      "<Domain> <DevId|mac>",
+    },
+    { "channel-list",
+      &main_channellist, 0, 0,
+      "List virtual channel devices for a domain",
+      "<Domain(s)>",
+    },
+    { "block-attach",
+      &main_blockattach, 1, 1,
+      "Create a new virtual block device",
+      "<Domain> <disk-spec-component(s)>...",
+    },
+    { "block-list",
+      &main_blocklist, 0, 0,
+      "List virtual block devices for a domain",
+      "<Domain(s)>",
+    },
+    { "block-detach",
+      &main_blockdetach, 0, 1,
+      "Destroy a domain's virtual block device",
+      "<Domain> <DevId>",
+    },
+    { "vtpm-attach",
+      &main_vtpmattach, 1, 1,
+      "Create a new virtual TPM device",
+      "<Domain> [uuid=<uuid>] [backend=<BackDomain>]",
+    },
+    { "vtpm-list",
+      &main_vtpmlist, 0, 0,
+      "List virtual TPM devices for a domain",
+      "<Domain(s)>",
+    },
+    { "vtpm-detach",
+      &main_vtpmdetach, 0, 1,
+      "Destroy a domain's virtual TPM device",
+      "<Domain> <DevId|uuid>",
+    },
+    { "uptime",
+      &main_uptime, 0, 0,
+      "Print uptime for all/some domains",
+      "[-s] [Domain]",
+    },
+    { "claims",
+      &main_claims, 0, 0,
+      "List outstanding claim information about all domains",
+      "",
+      "",
+    },
+    { "tmem-list",
+      &main_tmem_list, 0, 0,
+      "List tmem pools",
+      "[-l] [<Domain>|-a]",
+      "  -l                             List tmem stats",
+    },
+    { "tmem-freeze",
+      &main_tmem_freeze, 0, 1,
+      "Freeze tmem pools",
+      "[<Domain>|-a]",
+      "  -a                             Freeze all tmem",
+    },
+    { "tmem-thaw",
+      &main_tmem_thaw, 0, 1,
+      "Thaw tmem pools",
+      "[<Domain>|-a]",
+      "  -a                             Thaw all tmem",
+    },
+    { "tmem-set",
+      &main_tmem_set, 0, 1,
+      "Change tmem settings",
+      "[<Domain>|-a] [-w[=WEIGHT]|-c[=CAP]|-p[=COMPRESS]]",
+      "  -a                             Operate on all tmem\n"
+      "  -w WEIGHT                      Weight (int)\n"
+      "  -p COMPRESS                    Compress (int)",
+    },
+    { "tmem-shared-auth",
+      &main_tmem_shared_auth, 0, 1,
+      "De/authenticate shared tmem pool",
+      "[<Domain>|-a] [-u[=UUID] [-A[=AUTH]",
+      "  -a                             Authenticate for all tmem pools\n"
+      "  -u UUID                        Specify uuid\n"
+      "                                 (abcdef01-2345-6789-1234-567890abcdef)\n"
+      "  -A AUTH                        0=auth,1=deauth",
+    },
+    { "tmem-freeable",
+      &main_tmem_freeable, 0, 0,
+      "Get information about how much freeable memory (MB) is in-use by tmem",
+      "",
+    },
+    { "cpupool-create",
+      &main_cpupoolcreate, 1, 1,
+      "Create a new CPU pool",
+      "[options] [<ConfigFile>] [Variable=value ...]",
+      "-h, --help                   Print this help.\n"
+      "-f FILE, --defconfig=FILE    Use the given configuration file.\n"
+      "-n, --dryrun                 Dry run - prints the resulting configuration.\n"
+      "                              (deprecated in favour of global -N option).\n"
+      "\nSee the xlcpupool.cfg(5) manpage for more information.",
+
+    },
+    { "cpupool-list",
+      &main_cpupoollist, 0, 0,
+      "List CPU pools on host",
+      "[-c|--cpus] [<CPU Pool>]",
+      "-c, --cpus                     Output list of CPUs used by a pool"
+    },
+    { "cpupool-destroy",
+      &main_cpupooldestroy, 0, 1,
+      "Deactivates a CPU pool",
+      "<CPU Pool>",
+    },
+    { "cpupool-rename",
+      &main_cpupoolrename, 0, 1,
+      "Renames a CPU pool",
+      "<CPU Pool> <new name>",
+    },
+    { "cpupool-cpu-add",
+      &main_cpupoolcpuadd, 0, 1,
+      "Adds a CPU to a CPU pool",
+      "<CPU Pool> <CPU nr>|node:<node nr>",
+    },
+    { "cpupool-cpu-remove",
+      &main_cpupoolcpuremove, 0, 1,
+      "Removes a CPU from a CPU pool",
+      "<CPU Pool> <CPU nr>|node:<node nr>",
+    },
+    { "cpupool-migrate",
+      &main_cpupoolmigrate, 0, 1,
+      "Moves a domain into a CPU pool",
+      "<Domain> <CPU Pool>",
+    },
+    { "cpupool-numa-split",
+      &main_cpupoolnumasplit, 0, 1,
+      "Splits up the machine into one CPU pool per NUMA node",
+      "",
+    },
+    { "getenforce",
+      &main_getenforce, 0, 0,
+      "Returns the current enforcing mode of the Flask Xen security module",
+      "",
+    },
+    { "setenforce",
+      &main_setenforce, 0, 1,
+      "Sets the current enforcing mode of the Flask Xen security module",
+      "<1|0|Enforcing|Permissive>",
+    },
+    { "loadpolicy",
+      &main_loadpolicy, 0, 1,
+      "Loads a new policy int the Flask Xen security module",
+      "<policy file>",
+    },
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+    { "remus",
+      &main_remus, 0, 1,
+      "Enable Remus HA for domain",
+      "[options] <Domain> [<host>]",
+      "-i MS                   Checkpoint domain memory every MS milliseconds (def. 200ms).\n"
+      "-u                      Disable memory checkpoint compression.\n"
+      "-s <sshcommand>         Use <sshcommand> instead of ssh.  String will be passed\n"
+      "                        to sh. If empty, run <host> instead of \n"
+      "                        ssh <host> xl migrate-receive -r [-e]\n"
+      "-e                      Do not wait in the background (on <host>) for the death\n"
+      "                        of the domain.\n"
+      "-N <netbufscript>       Use netbufscript to setup network buffering instead of the\n"
+      "                        default script (/etc/xen/scripts/remus-netbuf-setup).\n"
+      "-F                      Enable unsafe configurations [-b|-n|-d flags]. Use this option\n"
+      "                        with caution as failover may not work as intended.\n"
+      "-b                      Replicate memory checkpoints to /dev/null (blackhole).\n"
+      "                        Works only in unsafe mode.\n"
+      "-n                      Disable network output buffering. Works only in unsafe mode.\n"
+      "-d                      Disable disk replication. Works only in unsafe mode.\n"
+      "-c                      Enable COLO HA. It is conflict with -i and -b, and memory\n"
+      "                        checkpoint must be disabled"
+    },
+#endif
+    { "devd",
+      &main_devd, 0, 1,
+      "Daemon that listens for devices and launches backends",
+      "[options]",
+      "-F                      Run in the foreground.\n"
+      "-p, --pidfile [FILE]    Write PID to pidfile when daemonizing.",
+    },
+#ifdef LIBXL_HAVE_PSR_CMT
+    { "psr-hwinfo",
+      &main_psr_hwinfo, 0, 1,
+      "Show hardware information for Platform Shared Resource",
+      "[options]",
+      "-m, --cmt       Show Cache Monitoring Technology (CMT) hardware info\n"
+      "-a, --cat       Show Cache Allocation Technology (CAT) hardware info\n"
+    },
+    { "psr-cmt-attach",
+      &main_psr_cmt_attach, 0, 1,
+      "Attach Cache Monitoring Technology service to a domain",
+      "<Domain>",
+    },
+    { "psr-cmt-detach",
+      &main_psr_cmt_detach, 0, 1,
+      "Detach Cache Monitoring Technology service from a domain",
+      "<Domain>",
+    },
+    { "psr-cmt-show",
+      &main_psr_cmt_show, 0, 1,
+      "Show Cache Monitoring Technology information",
+      "<PSR-CMT-Type> <Domain>",
+      "Available monitor types:\n"
+      "\"cache-occupancy\":         Show L3 cache occupancy(KB)\n"
+      "\"total-mem-bandwidth\":     Show total memory bandwidth(KB/s)\n"
+      "\"local-mem-bandwidth\":     Show local memory bandwidth(KB/s)\n",
+    },
+#endif
+#ifdef LIBXL_HAVE_PSR_CAT
+    { "psr-cat-cbm-set",
+      &main_psr_cat_cbm_set, 0, 1,
+      "Set cache capacity bitmasks(CBM) for a domain",
+      "[options] <Domain> <CBM>",
+      "-s <socket>       Specify the socket to process, otherwise all sockets are processed\n"
+      "-c                Set code CBM if CDP is supported\n"
+      "-d                Set data CBM if CDP is supported\n"
+    },
+    { "psr-cat-show",
+      &main_psr_cat_show, 0, 1,
+      "Show Cache Allocation Technology information",
+      "<Domain>",
+    },
+
+#endif
+    { "usbctrl-attach",
+      &main_usbctrl_attach, 0, 1,
+      "Create a virtual USB controller for a domain",
+      "<Domain> [type=pv] [version=<version>] [ports=<number>]",
+    },
+    { "usbctrl-detach",
+      &main_usbctrl_detach, 0, 1,
+      "Remove the virtual USB controller specified by <DevId> for a domain",
+      "<Domain> <DevId>",
+    },
+    { "usbdev-attach",
+      &main_usbdev_attach, 0, 1,
+      "Attach a USB device to a domain",
+      "<Domain> hostbus=<busnum> hostaddr=<devnum> [controller=<DevId> [port=<port>]]",
+    },
+    { "usbdev-detach",
+      &main_usbdev_detach, 0, 1,
+      "Detach a USB device from a domain",
+      "<Domain> <controller> <port>",
+    },
+    { "usb-list",
+      &main_usblist, 0, 0,
+      "List information about all USB controllers and devices for a domain",
+      "<Domain>",
+    },
+    { "qemu-monitor-command",
+      &main_qemu_monitor_command, 0, 1,
+      "Issue a qemu monitor command to the device model of a domain",
+      "<Domain> <Command>",
+    },
+};
+
+int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);
+
+/* Look up a command in the table, allowing unambiguous truncation */
+struct cmd_spec *cmdtable_lookup(const char *s)
+{
+    struct cmd_spec *cmd = NULL;
+    size_t len;
+    int i, count = 0;
+
+    if (!s)
+        return NULL;
+    len = strlen(s);
+    for (i = 0; i < cmdtable_len; i++) {
+        if (!strncmp(s, cmd_table[i].cmd_name, len)) {
+            cmd = &cmd_table[i];
+            /* Take an exact match, even if it also prefixes another command */
+            if (len == strlen(cmd->cmd_name))
+                return cmd;
+            count++;
+        }
+    }
+    return (count == 1) ? cmd : NULL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_sxp.c b/tools/xl/xl_sxp.c
new file mode 100644 (file)
index 0000000..a8c127b
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+ * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
+ *
+ * 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.
+ */
+
+/*
+ * Legacy SXP output handling
+ */
+
+#include "libxl_osdeps.h"
+
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "libxl.h"
+#include "libxl_utils.h"
+#include "xl.h"
+
+/* In general you should not add new output to this function since it
+ * is intended only for legacy use.
+ */
+void printf_info_sexp(int domid, libxl_domain_config *d_config, FILE *fh)
+{
+    int i;
+    libxl_dominfo info;
+
+    libxl_domain_create_info *c_info = &d_config->c_info;
+    libxl_domain_build_info *b_info = &d_config->b_info;
+
+    fprintf(fh, "(domain\n\t(domid %d)\n", domid);
+    fprintf(fh, "\t(create_info)\n");
+    fprintf(fh, "\t(hvm %d)\n", c_info->type == LIBXL_DOMAIN_TYPE_HVM);
+    fprintf(fh, "\t(hap %s)\n", libxl_defbool_to_string(c_info->hap));
+    fprintf(fh, "\t(oos %s)\n", libxl_defbool_to_string(c_info->oos));
+    fprintf(fh, "\t(ssidref %d)\n", c_info->ssidref);
+    fprintf(fh, "\t(name %s)\n", c_info->name);
+
+    /* retrieve the UUID from dominfo, since it is probably generated
+     * during parsing and thus does not match the real one
+     */
+    if (libxl_domain_info(ctx, &info, domid) == 0) {
+        fprintf(fh, "\t(uuid " LIBXL_UUID_FMT ")\n", LIBXL_UUID_BYTES(info.uuid));
+    } else {
+        fprintf(fh, "\t(uuid <unknown>)\n");
+    }
+    if (c_info->pool_name)
+        fprintf(fh, "\t(cpupool %s)\n", c_info->pool_name);
+    if (c_info->xsdata)
+        fprintf(fh, "\t(xsdata contains data)\n");
+    else
+        fprintf(fh, "\t(xsdata (null))\n");
+    if (c_info->platformdata)
+        fprintf(fh, "\t(platformdata contains data)\n");
+    else
+        fprintf(fh, "\t(platformdata (null))\n");
+
+
+    fprintf(fh, "\t(build_info)\n");
+    fprintf(fh, "\t(max_vcpus %d)\n", b_info->max_vcpus);
+    fprintf(fh, "\t(tsc_mode %s)\n", libxl_tsc_mode_to_string(b_info->tsc_mode));
+    fprintf(fh, "\t(max_memkb %"PRId64")\n", b_info->max_memkb);
+    fprintf(fh, "\t(target_memkb %"PRId64")\n", b_info->target_memkb);
+    fprintf(fh, "\t(nomigrate %s)\n",
+           libxl_defbool_to_string(b_info->disable_migrate));
+
+    if (c_info->type == LIBXL_DOMAIN_TYPE_PV && b_info->u.pv.bootloader) {
+        fprintf(fh, "\t(bootloader %s)\n", b_info->u.pv.bootloader);
+        if (b_info->u.pv.bootloader_args) {
+            fprintf(fh, "\t(bootloader_args");
+            for (i=0; b_info->u.pv.bootloader_args[i]; i++)
+                fprintf(fh, " %s", b_info->u.pv.bootloader_args[i]);
+            fprintf(fh, ")\n");
+        }
+    }
+
+    fprintf(fh, "\t(image\n");
+    switch (c_info->type) {
+    case LIBXL_DOMAIN_TYPE_HVM:
+        fprintf(fh, "\t\t(hvm\n");
+        fprintf(fh, "\t\t\t(firmware %s)\n", b_info->u.hvm.firmware);
+        fprintf(fh, "\t\t\t(video_memkb %"PRId64")\n", b_info->video_memkb);
+        fprintf(fh, "\t\t\t(shadow_memkb %"PRId64")\n", b_info->shadow_memkb);
+        fprintf(fh, "\t\t\t(pae %s)\n", libxl_defbool_to_string(b_info->u.hvm.pae));
+        fprintf(fh, "\t\t\t(apic %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.apic));
+        fprintf(fh, "\t\t\t(acpi %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.acpi));
+        fprintf(fh, "\t\t\t(nx %s)\n", libxl_defbool_to_string(b_info->u.hvm.nx));
+        fprintf(fh, "\t\t\t(viridian %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.viridian));
+        fprintf(fh, "\t\t\t(hpet %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.hpet));
+        fprintf(fh, "\t\t\t(vpt_align %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.vpt_align));
+        fprintf(fh, "\t\t\t(timer_mode %s)\n",
+               libxl_timer_mode_to_string(b_info->u.hvm.timer_mode));
+        fprintf(fh, "\t\t\t(nestedhvm %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.nested_hvm));
+        fprintf(fh, "\t\t\t(stdvga %s)\n", b_info->u.hvm.vga.kind ==
+                                      LIBXL_VGA_INTERFACE_TYPE_STD ?
+                                      "True" : "False");
+        fprintf(fh, "\t\t\t(vnc %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.vnc.enable));
+        fprintf(fh, "\t\t\t(vnclisten %s)\n", b_info->u.hvm.vnc.listen);
+        fprintf(fh, "\t\t\t(vncdisplay %d)\n", b_info->u.hvm.vnc.display);
+        fprintf(fh, "\t\t\t(vncunused %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.vnc.findunused));
+        fprintf(fh, "\t\t\t(keymap %s)\n", b_info->u.hvm.keymap);
+        fprintf(fh, "\t\t\t(sdl %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.sdl.enable));
+        fprintf(fh, "\t\t\t(opengl %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.sdl.opengl));
+        fprintf(fh, "\t\t\t(nographic %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.nographic));
+        fprintf(fh, "\t\t\t(spice %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.spice.enable));
+        fprintf(fh, "\t\t\t(spiceport %d)\n", b_info->u.hvm.spice.port);
+        fprintf(fh, "\t\t\t(spicetls_port %d)\n", b_info->u.hvm.spice.tls_port);
+        fprintf(fh, "\t\t\t(spicehost %s)\n", b_info->u.hvm.spice.host);
+        fprintf(fh, "\t\t\t(spicedisable_ticketing %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.spice.disable_ticketing));
+        fprintf(fh, "\t\t\t(spiceagent_mouse %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.spice.agent_mouse));
+
+        fprintf(fh, "\t\t\t(device_model %s)\n", b_info->device_model ? : "default");
+        fprintf(fh, "\t\t\t(gfx_passthru %s)\n",
+               libxl_defbool_to_string(b_info->u.hvm.gfx_passthru));
+        fprintf(fh, "\t\t\t(serial %s)\n", b_info->u.hvm.serial);
+        fprintf(fh, "\t\t\t(boot %s)\n", b_info->u.hvm.boot);
+        fprintf(fh, "\t\t\t(usb %s)\n", libxl_defbool_to_string(b_info->u.hvm.usb));
+        fprintf(fh, "\t\t\t(usbdevice %s)\n", b_info->u.hvm.usbdevice);
+        fprintf(fh, "\t\t)\n");
+        break;
+    case LIBXL_DOMAIN_TYPE_PV:
+        fprintf(fh, "\t\t(linux %d)\n", 0);
+        fprintf(fh, "\t\t\t(kernel %s)\n", b_info->kernel);
+        fprintf(fh, "\t\t\t(cmdline %s)\n", b_info->cmdline);
+        fprintf(fh, "\t\t\t(ramdisk %s)\n", b_info->ramdisk);
+        fprintf(fh, "\t\t\t(e820_host %s)\n",
+               libxl_defbool_to_string(b_info->u.pv.e820_host));
+        fprintf(fh, "\t\t)\n");
+        break;
+    default:
+        fprintf(stderr, "Unknown domain type %d\n", c_info->type);
+        exit(1);
+    }
+    fprintf(fh, "\t)\n");
+
+    for (i = 0; i < d_config->num_disks; i++) {
+        fprintf(fh, "\t(device\n");
+        fprintf(fh, "\t\t(tap\n");
+        fprintf(fh, "\t\t\t(backend_domid %d)\n", d_config->disks[i].backend_domid);
+        fprintf(fh, "\t\t\t(frontend_domid %d)\n", domid);
+        fprintf(fh, "\t\t\t(physpath %s)\n", d_config->disks[i].pdev_path);
+        fprintf(fh, "\t\t\t(phystype %d)\n", d_config->disks[i].backend);
+        fprintf(fh, "\t\t\t(virtpath %s)\n", d_config->disks[i].vdev);
+        fprintf(fh, "\t\t\t(unpluggable %d)\n", d_config->disks[i].removable);
+        fprintf(fh, "\t\t\t(readwrite %d)\n", d_config->disks[i].readwrite);
+        fprintf(fh, "\t\t\t(is_cdrom %d)\n", d_config->disks[i].is_cdrom);
+        fprintf(fh, "\t\t)\n");
+        fprintf(fh, "\t)\n");
+    }
+
+    for (i = 0; i < d_config->num_nics; i++) {
+        fprintf(fh, "\t(device\n");
+        fprintf(fh, "\t\t(vif\n");
+        if (d_config->nics[i].ifname)
+            fprintf(fh, "\t\t\t(vifname %s)\n", d_config->nics[i].ifname);
+        fprintf(fh, "\t\t\t(backend_domid %d)\n", d_config->nics[i].backend_domid);
+        fprintf(fh, "\t\t\t(frontend_domid %d)\n", domid);
+        fprintf(fh, "\t\t\t(devid %d)\n", d_config->nics[i].devid);
+        fprintf(fh, "\t\t\t(mtu %d)\n", d_config->nics[i].mtu);
+        fprintf(fh, "\t\t\t(model %s)\n", d_config->nics[i].model);
+        fprintf(fh, "\t\t\t(mac %02x%02x%02x%02x%02x%02x)\n",
+               d_config->nics[i].mac[0], d_config->nics[i].mac[1],
+               d_config->nics[i].mac[2], d_config->nics[i].mac[3],
+               d_config->nics[i].mac[4], d_config->nics[i].mac[5]);
+        fprintf(fh, "\t\t)\n");
+        fprintf(fh, "\t)\n");
+    }
+
+    for (i = 0; i < d_config->num_pcidevs; i++) {
+        fprintf(fh, "\t(device\n");
+        fprintf(fh, "\t\t(pci\n");
+        fprintf(fh, "\t\t\t(pci dev %04x:%02x:%02x.%01x@%02x)\n",
+               d_config->pcidevs[i].domain, d_config->pcidevs[i].bus,
+               d_config->pcidevs[i].dev, d_config->pcidevs[i].func,
+               d_config->pcidevs[i].vdevfn);
+        fprintf(fh, "\t\t\t(opts msitranslate %d power_mgmt %d)\n",
+               d_config->pcidevs[i].msitranslate,
+               d_config->pcidevs[i].power_mgmt);
+        fprintf(fh, "\t\t)\n");
+        fprintf(fh, "\t)\n");
+    }
+
+    for (i = 0; i < d_config->num_vfbs; i++) {
+        fprintf(fh, "\t(device\n");
+        fprintf(fh, "\t\t(vfb\n");
+        fprintf(fh, "\t\t\t(backend_domid %d)\n", d_config->vfbs[i].backend_domid);
+        fprintf(fh, "\t\t\t(frontend_domid %d)\n", domid);
+        fprintf(fh, "\t\t\t(devid %d)\n", d_config->vfbs[i].devid);
+        fprintf(fh, "\t\t\t(vnc %s)\n",
+               libxl_defbool_to_string(d_config->vfbs[i].vnc.enable));
+        fprintf(fh, "\t\t\t(vnclisten %s)\n", d_config->vfbs[i].vnc.listen);
+        fprintf(fh, "\t\t\t(vncdisplay %d)\n", d_config->vfbs[i].vnc.display);
+        fprintf(fh, "\t\t\t(vncunused %s)\n",
+               libxl_defbool_to_string(d_config->vfbs[i].vnc.findunused));
+        fprintf(fh, "\t\t\t(keymap %s)\n", d_config->vfbs[i].keymap);
+        fprintf(fh, "\t\t\t(sdl %s)\n",
+               libxl_defbool_to_string(d_config->vfbs[i].sdl.enable));
+        fprintf(fh, "\t\t\t(opengl %s)\n",
+               libxl_defbool_to_string(d_config->vfbs[i].sdl.opengl));
+        fprintf(fh, "\t\t\t(display %s)\n", d_config->vfbs[i].sdl.display);
+        fprintf(fh, "\t\t\t(xauthority %s)\n", d_config->vfbs[i].sdl.xauthority);
+        fprintf(fh, "\t\t)\n");
+        fprintf(fh, "\t)\n");
+    }
+    fprintf(fh, ")\n");
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */