$(MAKE) -C src admin/admin_client.h
# List all syntax-check exemptions:
-exclude_file_name_regexp--sc_avoid_strcase = ^tools/virsh\.h$$
+exclude_file_name_regexp--sc_avoid_strcase = ^tools/vsh\.h$$
_src1=libvirt-stream|fdstream|qemu/qemu_monitor|util/(vircommand|virfile)|xen/xend_internal|rpc/virnetsocket|lxc/lxc_controller|locking/lock_daemon
_test1=shunloadtest|virnettlscontexttest|virnettlssessiontest|vircgroupmock
tests/virpolkittest.c
tools/libvirt-guests.sh.in
tools/virsh.c
-tools/virsh.h
tools/virsh-console.c
tools/virsh-domain-monitor.c
tools/virsh-domain.c
tools/virt-host-validate-qemu.c
tools/virt-host-validate.c
tools/virt-login-shell.c
+tools/vsh.c
+tools/vsh.h
virStringSplitCount;
virStringStripControlChars;
virStringStripIPv6Brackets;
+virStringToUpper;
virStrncpy;
virStrndup;
virStrToDouble;
}
str[j] = '\0';
}
+
+/**
+ * virStringToUpper:
+ * @str: string to capitalize
+ * @dst: where to store the new capitalized string
+ *
+ * Capitalize the string with replacement of all '-' characters for '_'
+ * characters. Caller frees the result.
+ *
+ * Returns 0 if src is NULL, 1 if capitalization was successfull, -1 on failure.
+ */
+int
+virStringToUpper(char **dst, const char *src)
+{
+ char *cap = NULL;
+ size_t i;
+
+ if (!src)
+ return 0;
+
+ if (VIR_ALLOC_N(cap, strlen(src) + 1) < 0)
+ return -1;
+
+ for (i = 0; src[i]; i++) {
+ cap[i] = c_toupper(src[i]);
+ if (cap[i] == '-')
+ cap[i] = '_';
+ }
+
+ *dst = cap;
+ return 1;
+}
int virStringSortCompare(const void *a, const void *b);
int virStringSortRevCompare(const void *a, const void *b);
+int virStringToUpper(char **dst, const char *src);
ssize_t virStringSearch(const char *str,
const char *regexp,
$(PIE_CFLAGS) \
$(COVERAGE_CFLAGS)
+virt_shell_SOURCES = \
+ vsh.c vsh.h
+
virsh_SOURCES = \
+ $(virt_shell_SOURCES) \
virsh.c virsh.h \
virsh-console.c virsh-console.h \
virsh-domain.c virsh-domain.h \
static char
-vshGetEscapeChar(const char *s)
+virshGetEscapeChar(const char *s)
{
if (*s == '^')
return CONTROL(c_toupper(s[1]));
int
-vshRunConsole(vshControl *ctl,
- virDomainPtr dom,
- const char *dev_name,
- unsigned int flags)
+virshRunConsole(vshControl *ctl,
+ virDomainPtr dom,
+ const char *dev_name,
+ unsigned int flags)
{
virConsolePtr con = NULL;
+ virshControlPtr priv = ctl->privData;
int ret = -1;
struct sigaction old_sigquit;
if (VIR_ALLOC(con) < 0)
goto cleanup;
- con->escapeChar = vshGetEscapeChar(ctl->escapeChar);
+ con->escapeChar = virshGetEscapeChar(priv->escapeChar);
con->st = virStreamNew(virDomainGetConnect(dom),
VIR_STREAM_NONBLOCK);
if (!con->st)
# include <virsh.h>
-int vshRunConsole(vshControl *ctl,
- virDomainPtr dom,
- const char *dev_name,
- unsigned int flags);
+int virshRunConsole(vshControl *ctl,
+ virDomainPtr dom,
+ const char *dev_name,
+ unsigned int flags);
# endif /* !WIN32 */
#include "virxml.h"
#include "virstring.h"
-VIR_ENUM_DECL(vshDomainIOError)
-VIR_ENUM_IMPL(vshDomainIOError,
+VIR_ENUM_DECL(virshDomainIOError)
+VIR_ENUM_IMPL(virshDomainIOError,
VIR_DOMAIN_DISK_ERROR_LAST,
N_("no error"),
N_("unspecified error"),
N_("no space"))
static const char *
-vshDomainIOErrorToString(int error)
+virshDomainIOErrorToString(int error)
{
- const char *str = vshDomainIOErrorTypeToString(error);
+ const char *str = virshDomainIOErrorTypeToString(error);
return str ? _(str) : _("unknown error");
}
/* extract description or title from domain xml */
char *
-vshGetDomainDescription(vshControl *ctl, virDomainPtr dom, bool title,
- unsigned int flags)
+virshGetDomainDescription(vshControl *ctl, virDomainPtr dom, bool title,
+ unsigned int flags)
{
char *desc = NULL;
char *domxml = NULL;
return desc;
}
-VIR_ENUM_DECL(vshDomainControlState)
-VIR_ENUM_IMPL(vshDomainControlState,
+VIR_ENUM_DECL(virshDomainControlState)
+VIR_ENUM_IMPL(virshDomainControlState,
VIR_DOMAIN_CONTROL_LAST,
N_("ok"),
N_("background job"),
N_("error"))
static const char *
-vshDomainControlStateToString(int state)
+virshDomainControlStateToString(int state)
{
- const char *str = vshDomainControlStateTypeToString(state);
+ const char *str = virshDomainControlStateTypeToString(state);
return str ? _(str) : _("unknown");
}
-VIR_ENUM_DECL(vshDomainControlErrorReason)
-VIR_ENUM_IMPL(vshDomainControlErrorReason,
+VIR_ENUM_DECL(virshDomainControlErrorReason)
+VIR_ENUM_IMPL(virshDomainControlErrorReason,
VIR_DOMAIN_CONTROL_ERROR_REASON_LAST,
"",
N_("unknown"),
N_("internal (locking) error"))
static const char *
-vshDomainControlErrorReasonToString(int reason)
+virshDomainControlErrorReasonToString(int reason)
{
- const char *ret = vshDomainControlErrorReasonTypeToString(reason);
+ const char *ret = virshDomainControlErrorReasonTypeToString(reason);
return ret ? _(ret) : _("unknown");
}
-VIR_ENUM_DECL(vshDomainState)
-VIR_ENUM_IMPL(vshDomainState,
+VIR_ENUM_DECL(virshDomainState)
+VIR_ENUM_IMPL(virshDomainState,
VIR_DOMAIN_LAST,
N_("no state"),
N_("running"),
N_("pmsuspended"))
static const char *
-vshDomainStateToString(int state)
+virshDomainStateToString(int state)
{
- const char *str = vshDomainStateTypeToString(state);
+ const char *str = virshDomainStateTypeToString(state);
return str ? _(str) : _("no state");
}
-VIR_ENUM_DECL(vshDomainNostateReason)
-VIR_ENUM_IMPL(vshDomainNostateReason,
+VIR_ENUM_DECL(virshDomainNostateReason)
+VIR_ENUM_IMPL(virshDomainNostateReason,
VIR_DOMAIN_NOSTATE_LAST,
N_("unknown"))
-VIR_ENUM_DECL(vshDomainRunningReason)
-VIR_ENUM_IMPL(vshDomainRunningReason,
+VIR_ENUM_DECL(virshDomainRunningReason)
+VIR_ENUM_IMPL(virshDomainRunningReason,
VIR_DOMAIN_RUNNING_LAST,
N_("unknown"),
N_("booted"),
N_("event wakeup"),
N_("crashed"))
-VIR_ENUM_DECL(vshDomainBlockedReason)
-VIR_ENUM_IMPL(vshDomainBlockedReason,
+VIR_ENUM_DECL(virshDomainBlockedReason)
+VIR_ENUM_IMPL(virshDomainBlockedReason,
VIR_DOMAIN_BLOCKED_LAST,
N_("unknown"))
-VIR_ENUM_DECL(vshDomainPausedReason)
-VIR_ENUM_IMPL(vshDomainPausedReason,
+VIR_ENUM_DECL(virshDomainPausedReason)
+VIR_ENUM_IMPL(virshDomainPausedReason,
VIR_DOMAIN_PAUSED_LAST,
N_("unknown"),
N_("user"),
N_("crashed"),
N_("starting up"))
-VIR_ENUM_DECL(vshDomainShutdownReason)
-VIR_ENUM_IMPL(vshDomainShutdownReason,
+VIR_ENUM_DECL(virshDomainShutdownReason)
+VIR_ENUM_IMPL(virshDomainShutdownReason,
VIR_DOMAIN_SHUTDOWN_LAST,
N_("unknown"),
N_("user"))
-VIR_ENUM_DECL(vshDomainShutoffReason)
-VIR_ENUM_IMPL(vshDomainShutoffReason,
+VIR_ENUM_DECL(virshDomainShutoffReason)
+VIR_ENUM_IMPL(virshDomainShutoffReason,
VIR_DOMAIN_SHUTOFF_LAST,
N_("unknown"),
N_("shutdown"),
N_("failed"),
N_("from snapshot"))
-VIR_ENUM_DECL(vshDomainCrashedReason)
-VIR_ENUM_IMPL(vshDomainCrashedReason,
+VIR_ENUM_DECL(virshDomainCrashedReason)
+VIR_ENUM_IMPL(virshDomainCrashedReason,
VIR_DOMAIN_CRASHED_LAST,
N_("unknown"),
N_("panicked"))
-VIR_ENUM_DECL(vshDomainPMSuspendedReason)
-VIR_ENUM_IMPL(vshDomainPMSuspendedReason,
+VIR_ENUM_DECL(virshDomainPMSuspendedReason)
+VIR_ENUM_IMPL(virshDomainPMSuspendedReason,
VIR_DOMAIN_PMSUSPENDED_LAST,
N_("unknown"))
static const char *
-vshDomainStateReasonToString(int state, int reason)
+virshDomainStateReasonToString(int state, int reason)
{
const char *str = NULL;
switch ((virDomainState) state) {
case VIR_DOMAIN_NOSTATE:
- str = vshDomainNostateReasonTypeToString(reason);
+ str = virshDomainNostateReasonTypeToString(reason);
break;
case VIR_DOMAIN_RUNNING:
- str = vshDomainRunningReasonTypeToString(reason);
+ str = virshDomainRunningReasonTypeToString(reason);
break;
case VIR_DOMAIN_BLOCKED:
- str = vshDomainBlockedReasonTypeToString(reason);
+ str = virshDomainBlockedReasonTypeToString(reason);
break;
case VIR_DOMAIN_PAUSED:
- str = vshDomainPausedReasonTypeToString(reason);
+ str = virshDomainPausedReasonTypeToString(reason);
break;
case VIR_DOMAIN_SHUTDOWN:
- str = vshDomainShutdownReasonTypeToString(reason);
+ str = virshDomainShutdownReasonTypeToString(reason);
break;
case VIR_DOMAIN_SHUTOFF:
- str = vshDomainShutoffReasonTypeToString(reason);
+ str = virshDomainShutoffReasonTypeToString(reason);
break;
case VIR_DOMAIN_CRASHED:
- str = vshDomainCrashedReasonTypeToString(reason);
+ str = virshDomainCrashedReasonTypeToString(reason);
break;
case VIR_DOMAIN_PMSUSPENDED:
- str = vshDomainPMSuspendedReasonTypeToString(reason);
+ str = virshDomainPMSuspendedReasonTypeToString(reason);
break;
case VIR_DOMAIN_LAST:
;
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
/* If none of the options were specified and we're active
bool ret = false;
const char *device = NULL;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "device", &device) < 0)
details = vshCommandOptBool(cmd, "details");
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
xml = virDomainGetXMLDesc(dom, flags);
if (vshCommandOptBool(cmd, "inactive"))
flags |= VIR_DOMAIN_XML_INACTIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
xml = virDomainGetXMLDesc(dom, flags);
if (vshCommandOptStringReq(ctl, cmd, "interface", &iface) < 0)
return false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptBool(cmd, "config"))
bool ret = true;
virDomainControlInfo info;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (virDomainGetControlInfo(dom, &info, 0) < 0) {
if (info.state != VIR_DOMAIN_CONTROL_OK &&
info.state != VIR_DOMAIN_CONTROL_ERROR) {
vshPrint(ctl, "%s (%0.3fs)\n",
- vshDomainControlStateToString(info.state),
+ virshDomainControlStateToString(info.state),
info.stateTime / 1000.0);
} else if (info.state == VIR_DOMAIN_CONTROL_ERROR && info.details > 0) {
vshPrint(ctl, "%s: %s\n",
- vshDomainControlStateToString(info.state),
- vshDomainControlErrorReasonToString(info.details));
+ virshDomainControlStateToString(info.state),
+ virshDomainControlErrorReasonToString(info.details));
} else {
vshPrint(ctl, "%s\n",
- vshDomainControlStateToString(info.state));
+ virshDomainControlStateToString(info.state));
}
cleanup:
bool ret = false;
bool human = vshCommandOptBool(cmd, "human"); /* human readable output */
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
/* device argument is optional now. if it's missing, supply empty
virDomainInterfaceStatsStruct stats;
bool ret = false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "interface", &device) < 0)
int count;
bool ret = false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if ((count = virDomainGetDiskErrors(dom, NULL, 0, 0)) < 0)
for (i = 0; i < count; i++) {
vshPrint(ctl, "%s: %s\n",
disks[i].disk,
- vshDomainIOErrorToString(disks[i].error));
+ virshDomainIOErrorToString(disks[i].error));
}
}
unsigned int id;
char *str, uuid[VIR_UUID_STRING_BUFLEN];
int has_managed_save = 0;
+ virshControlPtr priv = ctl->privData;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
id = virDomainGetID(dom);
if (virDomainGetInfo(dom, &info) == 0) {
vshPrint(ctl, "%-15s %s\n", _("State:"),
- vshDomainStateToString(info.state));
+ virshDomainStateToString(info.state));
vshPrint(ctl, "%-15s %d\n", _("CPU(s):"), info.nrVirtCpu);
/* Security model and label information */
memset(&secmodel, 0, sizeof(secmodel));
- if (virNodeGetSecurityModel(ctl->conn, &secmodel) == -1) {
+ if (virNodeGetSecurityModel(priv->conn, &secmodel) == -1) {
if (last_error->code != VIR_ERR_NO_SUPPORT) {
virDomainFree(dom);
return false;
bool showReason = vshCommandOptBool(cmd, "reason");
int state, reason;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
- if ((state = vshDomainState(ctl, dom, &reason)) < 0) {
+ if ((state = virshDomainState(ctl, dom, &reason)) < 0) {
ret = false;
goto cleanup;
}
if (showReason) {
vshPrint(ctl, "%s (%s)\n",
- vshDomainStateToString(state),
- vshDomainStateReasonToString(state, reason));
+ virshDomainStateToString(state),
+ virshDomainStateReasonToString(state, reason));
} else {
vshPrint(ctl, "%s\n",
- vshDomainStateToString(state));
+ virshDomainStateToString(state));
}
cleanup:
VSH_EXCLUSIVE_OPTIONS("time", "sync");
VSH_EXCLUSIVE_OPTIONS("now", "sync");
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
rv = vshCommandOptLongLong(ctl, cmd, "time", &seconds);
/* compare domains, pack NULLed ones at the end*/
static int
-vshDomainSorter(const void *a, const void *b)
+virshDomainSorter(const void *a, const void *b)
{
virDomainPtr *da = (virDomainPtr *) a;
virDomainPtr *db = (virDomainPtr *) b;
return 1;
}
-struct vshDomainList {
+struct virshDomainList {
virDomainPtr *domains;
size_t ndomains;
};
-typedef struct vshDomainList *vshDomainListPtr;
+typedef struct virshDomainList *virshDomainListPtr;
static void
-vshDomainListFree(vshDomainListPtr domlist)
+virshDomainListFree(virshDomainListPtr domlist)
{
size_t i;
VIR_FREE(domlist);
}
-static vshDomainListPtr
-vshDomainListCollect(vshControl *ctl, unsigned int flags)
+static virshDomainListPtr
+virshDomainListCollect(vshControl *ctl, unsigned int flags)
{
- vshDomainListPtr list = vshMalloc(ctl, sizeof(*list));
+ virshDomainListPtr list = vshMalloc(ctl, sizeof(*list));
size_t i;
int ret;
int *ids = NULL;
int state;
int nsnap;
int mansave;
+ virshControlPtr priv = ctl->privData;
/* try the list with flags support (0.9.13 and later) */
- if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
+ if ((ret = virConnectListAllDomains(priv->conn, &list->domains,
flags)) >= 0) {
list->ndomains = ret;
goto finished;
VIR_CONNECT_LIST_DOMAINS_INACTIVE);
vshResetLibvirtError();
- if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
+ if ((ret = virConnectListAllDomains(priv->conn, &list->domains,
newflags)) >= 0) {
list->ndomains = ret;
goto filter;
/* list active domains, if necessary */
if (!VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE)) {
- if ((nids = virConnectNumOfDomains(ctl->conn)) < 0) {
+ if ((nids = virConnectNumOfDomains(priv->conn)) < 0) {
vshError(ctl, "%s", _("Failed to list active domains"));
goto cleanup;
}
if (nids) {
ids = vshMalloc(ctl, sizeof(int) * nids);
- if ((nids = virConnectListDomains(ctl->conn, ids, nids)) < 0) {
+ if ((nids = virConnectListDomains(priv->conn, ids, nids)) < 0) {
vshError(ctl, "%s", _("Failed to list active domains"));
goto cleanup;
}
if (!VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE)) {
- if ((nnames = virConnectNumOfDefinedDomains(ctl->conn)) < 0) {
+ if ((nnames = virConnectNumOfDefinedDomains(priv->conn)) < 0) {
vshError(ctl, "%s", _("Failed to list inactive domains"));
goto cleanup;
}
if (nnames) {
names = vshMalloc(ctl, sizeof(char *) * nnames);
- if ((nnames = virConnectListDefinedDomains(ctl->conn, names,
+ if ((nnames = virConnectListDefinedDomains(priv->conn, names,
nnames)) < 0) {
vshError(ctl, "%s", _("Failed to list inactive domains"));
goto cleanup;
/* get active domains */
for (i = 0; i < nids; i++) {
- if (!(dom = virDomainLookupByID(ctl->conn, ids[i])))
+ if (!(dom = virDomainLookupByID(priv->conn, ids[i])))
continue;
list->domains[list->ndomains++] = dom;
}
/* get inactive domains */
for (i = 0; i < nnames; i++) {
- if (!(dom = virDomainLookupByName(ctl->conn, names[i])))
+ if (!(dom = virDomainLookupByName(priv->conn, names[i])))
continue;
list->domains[list->ndomains++] = dom;
}
/* sort the list */
if (list->domains && list->ndomains)
qsort(list->domains, list->ndomains, sizeof(*list->domains),
- vshDomainSorter);
+ virshDomainSorter);
/* truncate the list if filter simulation deleted entries */
if (deleted)
VIR_FREE(names[i]);
if (!success) {
- vshDomainListFree(list);
+ virshDomainListFree(list);
list = NULL;
}
char uuid[VIR_UUID_STRING_BUFLEN];
int state;
bool ret = false;
- vshDomainListPtr list = NULL;
+ virshDomainListPtr list = NULL;
virDomainPtr dom;
char id_buf[INT_BUFSIZE_BOUND(unsigned int)];
unsigned int id;
if (!optUUID && !optName)
optTable = true;
- if (!(list = vshDomainListCollect(ctl, flags)))
+ if (!(list = virshDomainListCollect(ctl, flags)))
goto cleanup;
/* print table header in legacy mode */
else
ignore_value(virStrcpyStatic(id_buf, "-"));
- state = vshDomainState(ctl, dom, NULL);
+ state = virshDomainState(ctl, dom, NULL);
/* Domain could've been removed in the meantime */
if (state < 0)
if (optTable) {
if (optTitle) {
- if (!(title = vshGetDomainDescription(ctl, dom, true, 0)))
+ if (!(title = virshGetDomainDescription(ctl, dom, true, 0)))
goto cleanup;
vshPrint(ctl, " %-5s %-30s %-10s %-20s\n", id_buf,
virDomainGetName(dom),
- state == -2 ? _("saved") : vshDomainStateToString(state),
+ state == -2 ? _("saved")
+ : virshDomainStateToString(state),
title);
VIR_FREE(title);
} else {
vshPrint(ctl, " %-5s %-30s %s\n", id_buf,
virDomainGetName(dom),
- state == -2 ? _("saved") : vshDomainStateToString(state));
+ state == -2 ? _("saved")
+ : virshDomainStateToString(state));
}
} else if (optUUID) {
if (virDomainGetUUIDString(dom, uuid) < 0) {
ret = true;
cleanup:
- vshDomainListFree(list);
+ virshDomainListFree(list);
return ret;
}
#undef FILTER
static bool
-vshDomainStatsPrintRecord(vshControl *ctl ATTRIBUTE_UNUSED,
- virDomainStatsRecordPtr record,
- bool raw ATTRIBUTE_UNUSED)
+virshDomainStatsPrintRecord(vshControl *ctl ATTRIBUTE_UNUSED,
+ virDomainStatsRecordPtr record,
+ bool raw ATTRIBUTE_UNUSED)
{
char *param;
size_t i;
int flags = 0;
const vshCmdOpt *opt = NULL;
bool ret = false;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "state"))
stats |= VIR_DOMAIN_STATS_STATE;
ndoms = 1;
while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
- if (!(dom = vshLookupDomainBy(ctl, opt->data,
- VSH_BYID | VSH_BYUUID | VSH_BYNAME)))
+ if (!(dom = virshLookupDomainBy(ctl, opt->data,
+ VIRSH_BYID |
+ VIRSH_BYUUID | VIRSH_BYNAME)))
goto cleanup;
if (VIR_INSERT_ELEMENT(domlist, ndoms - 1, ndoms, dom) < 0)
flags) < 0)
goto cleanup;
} else {
- if ((virConnectGetAllDomainStats(ctl->conn,
+ if ((virConnectGetAllDomainStats(priv->conn,
stats,
&records,
flags)) < 0)
}
for (next = records; *next; next++) {
- if (!vshDomainStatsPrintRecord(ctl, *next, raw))
+ if (!virshDomainStatsPrintRecord(ctl, *next, raw))
goto cleanup;
}
const char *sourcestr = NULL;
int source = VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptString(ctl, cmd, "interface", &ifacestr) < 0)
# include "virsh.h"
-char *vshGetDomainDescription(vshControl *ctl, virDomainPtr dom,
- bool title, unsigned int flags)
+char *virshGetDomainDescription(vshControl *ctl, virDomainPtr dom,
+ bool title, unsigned int flags)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
extern const vshCmdDef domMonitoringCmds[];
static virDomainPtr
-vshLookupDomainInternal(vshControl *ctl,
- const char *cmdname,
- const char *name,
- unsigned int flags)
+virshLookupDomainInternal(vshControl *ctl,
+ const char *cmdname,
+ const char *name,
+ unsigned int flags)
{
virDomainPtr dom = NULL;
int id;
- virCheckFlags(VSH_BYID | VSH_BYUUID | VSH_BYNAME, NULL);
+ virCheckFlags(VIRSH_BYID | VIRSH_BYUUID | VIRSH_BYNAME, NULL);
+ virshControlPtr priv = ctl->privData;
/* try it by ID */
- if (flags & VSH_BYID) {
+ if (flags & VIRSH_BYID) {
if (virStrToLong_i(name, NULL, 10, &id) == 0 && id >= 0) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <domain> looks like ID\n",
cmdname);
- dom = virDomainLookupByID(ctl->conn, id);
+ dom = virDomainLookupByID(priv->conn, id);
}
}
/* try it by UUID */
- if (!dom && (flags & VSH_BYUUID) &&
+ if (!dom && (flags & VIRSH_BYUUID) &&
strlen(name) == VIR_UUID_STRING_BUFLEN-1) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <domain> trying as domain UUID\n",
cmdname);
- dom = virDomainLookupByUUIDString(ctl->conn, name);
+ dom = virDomainLookupByUUIDString(priv->conn, name);
}
/* try it by NAME */
- if (!dom && (flags & VSH_BYNAME)) {
+ if (!dom && (flags & VIRSH_BYNAME)) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <domain> trying as domain NAME\n",
cmdname);
- dom = virDomainLookupByName(ctl->conn, name);
+ dom = virDomainLookupByName(priv->conn, name);
}
if (!dom)
virDomainPtr
-vshLookupDomainBy(vshControl *ctl,
- const char *name,
- unsigned int flags)
+virshLookupDomainBy(vshControl *ctl,
+ const char *name,
+ unsigned int flags)
{
- return vshLookupDomainInternal(ctl, "unknown", name, flags);
+ return virshLookupDomainInternal(ctl, "unknown", name, flags);
}
virDomainPtr
-vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd,
- const char **name, unsigned int flags)
+virshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd,
+ const char **name, unsigned int flags)
{
const char *n = NULL;
const char *optname = "domain";
if (name)
*name = n;
- return vshLookupDomainInternal(ctl, cmd->def->name, n, flags);
+ return virshLookupDomainInternal(ctl, cmd->def->name, n, flags);
}
static virDomainPtr
-vshDomainDefine(virConnectPtr conn, const char *xml, unsigned int flags)
+virshDomainDefine(virConnectPtr conn, const char *xml, unsigned int flags)
{
virDomainPtr dom;
if (flags) {
return dom;
}
-VIR_ENUM_DECL(vshDomainVcpuState)
-VIR_ENUM_IMPL(vshDomainVcpuState,
+VIR_ENUM_DECL(virshDomainVcpuState)
+VIR_ENUM_IMPL(virshDomainVcpuState,
VIR_VCPU_LAST,
N_("offline"),
N_("running"),
N_("blocked"))
static const char *
-vshDomainVcpuStateToString(int state)
+virshDomainVcpuStateToString(int state)
{
- const char *str = vshDomainVcpuStateTypeToString(state);
+ const char *str = virshDomainVcpuStateTypeToString(state);
return str ? _(str) : _("no state");
}
* if needed.
*/
static int
-vshNodeGetCPUCount(virConnectPtr conn)
+virshNodeGetCPUCount(virConnectPtr conn)
{
int ret;
virNodeInfo nodeinfo;
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
goto cleanup;
}
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
goto cleanup;
if (persistent &&
* 'average,peak,burst,floor', in which peak and burst are optional,
* thus 'average,,burst' and 'average,peak' are also legal. */
-#define VSH_PARSE_RATE_FIELD(index, name) \
+#define VIRSH_PARSE_RATE_FIELD(index, name) \
do { \
if (index < ntok && \
*tok[index] != '\0' && \
} while (0)
static int
-vshParseRateStr(vshControl *ctl,
- const char *rateStr,
- virNetDevBandwidthRatePtr rate)
+virshParseRateStr(vshControl *ctl,
+ const char *rateStr,
+ virNetDevBandwidthRatePtr rate)
{
char **tok = NULL;
size_t ntok;
goto cleanup;
}
- VSH_PARSE_RATE_FIELD(0, average);
- VSH_PARSE_RATE_FIELD(1, peak);
- VSH_PARSE_RATE_FIELD(2, burst);
- VSH_PARSE_RATE_FIELD(3, floor);
+ VIRSH_PARSE_RATE_FIELD(0, average);
+ VIRSH_PARSE_RATE_FIELD(1, peak);
+ VIRSH_PARSE_RATE_FIELD(2, burst);
+ VIRSH_PARSE_RATE_FIELD(3, floor);
ret = 0;
cleanup:
return ret;
}
-#undef VSH_PARSE_RATE_FIELD
+#undef VIRSH_PARSE_RATE_FIELD
static bool
cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
const char *mac = NULL, *target = NULL, *script = NULL,
- *type = NULL, *source = NULL, *model = NULL,
- *inboundStr = NULL, *outboundStr = NULL;
+ *type = NULL, *source = NULL, *model = NULL,
+ *inboundStr = NULL, *outboundStr = NULL;
virNetDevBandwidthRate inbound, outbound;
virDomainNetType typ;
int ret;
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (persistent &&
if (inboundStr) {
memset(&inbound, 0, sizeof(inbound));
- if (vshParseRateStr(ctl, inboundStr, &inbound) < 0)
+ if (virshParseRateStr(ctl, inboundStr, &inbound) < 0)
goto cleanup;
if (!inbound.average && !inbound.floor) {
vshError(ctl, _("either inbound average or floor is mandatory"));
}
if (outboundStr) {
memset(&outbound, 0, sizeof(outbound));
- if (vshParseRateStr(ctl, outboundStr, &outbound) < 0)
+ if (virshParseRateStr(ctl, outboundStr, &outbound) < 0)
goto cleanup;
if (outbound.average == 0) {
vshError(ctl, _("outbound average is mandatory"));
const char *name;
int autostart;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
autostart = !vshCommandOptBool(cmd, "disable");
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
goto cleanup;
if (vshCommandOptStringReq(ctl, cmd, "device", &disk) < 0)
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if ((rv = vshCommandOptInt(ctl, cmd, "weight", &weight)) < 0) {
static void
-vshPrintJobProgress(const char *label, unsigned long long remaining,
- unsigned long long total)
+virshPrintJobProgress(const char *label, unsigned long long remaining,
+ unsigned long long total)
{
int progress;
static volatile sig_atomic_t intCaught;
-static void vshCatchInt(int sig ATTRIBUTE_UNUSED,
- siginfo_t *siginfo ATTRIBUTE_UNUSED,
- void *context ATTRIBUTE_UNUSED)
+static void virshCatchInt(int sig ATTRIBUTE_UNUSED,
+ siginfo_t *siginfo ATTRIBUTE_UNUSED,
+ void *context ATTRIBUTE_UNUSED)
{
intCaught = 1;
}
-typedef struct _vshBlockJobWaitData vshBlockJobWaitData;
-typedef vshBlockJobWaitData *vshBlockJobWaitDataPtr;
-struct _vshBlockJobWaitData {
+typedef struct _virshBlockJobWaitData virshBlockJobWaitData;
+typedef virshBlockJobWaitData *virshBlockJobWaitDataPtr;
+struct _virshBlockJobWaitData {
vshControl *ctl;
virDomainPtr dom;
const char *dev;
static void
-vshBlockJobStatusHandler(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom ATTRIBUTE_UNUSED,
- const char *disk,
- int type ATTRIBUTE_UNUSED,
- int status,
- void *opaque)
+virshBlockJobStatusHandler(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom ATTRIBUTE_UNUSED,
+ const char *disk,
+ int type ATTRIBUTE_UNUSED,
+ int status,
+ void *opaque)
{
- vshBlockJobWaitDataPtr data = opaque;
+ virshBlockJobWaitDataPtr data = opaque;
if (STREQ_NULLABLE(disk, data->dev))
data->status = status;
/**
- * vshBlockJobWaitInit:
+ * virshBlockJobWaitInit:
* @ctl: vsh control structure
* @dom: domain object
* @dev: block device name to wait for
*
* Prepares virsh for waiting for completion of a block job. This function
* registers event handlers for block job events and prepares the data structures
- * for them. A call to vshBlockJobWait then waits for completion of the given
+ * for them. A call to virshBlockJobWait then waits for completion of the given
* block job. This function should be tolerant to different versions of daemon
* and the reporting capabilities of those.
*
* Returns the data structure that holds data needed for block job waiting or
* NULL in case of error.
*/
-static vshBlockJobWaitDataPtr
-vshBlockJobWaitInit(vshControl *ctl,
- virDomainPtr dom,
- const char *dev,
- const char *job_name,
- bool verbose,
- unsigned int timeout,
- bool async_abort)
+static virshBlockJobWaitDataPtr
+virshBlockJobWaitInit(vshControl *ctl,
+ virDomainPtr dom,
+ const char *dev,
+ const char *job_name,
+ bool verbose,
+ unsigned int timeout,
+ bool async_abort)
{
- vshBlockJobWaitDataPtr ret;
+ virshBlockJobWaitDataPtr ret;
+ virshControlPtr priv = ctl->privData;
if (VIR_ALLOC(ret) < 0)
return NULL;
ret->status = -1;
virConnectDomainEventGenericCallback cb =
- VIR_DOMAIN_EVENT_CALLBACK(vshBlockJobStatusHandler);
+ VIR_DOMAIN_EVENT_CALLBACK(virshBlockJobStatusHandler);
- if ((ret->cb_id = virConnectDomainEventRegisterAny(ctl->conn, dom,
+ if ((ret->cb_id = virConnectDomainEventRegisterAny(priv->conn, dom,
VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
cb, ret, NULL)) < 0)
vshResetLibvirtError();
- if ((ret->cb_id2 = virConnectDomainEventRegisterAny(ctl->conn, dom,
+ if ((ret->cb_id2 = virConnectDomainEventRegisterAny(priv->conn, dom,
VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2,
cb, ret, NULL)) < 0)
vshResetLibvirtError();
static void
-vshBlockJobWaitFree(vshBlockJobWaitDataPtr data)
+virshBlockJobWaitFree(virshBlockJobWaitDataPtr data)
{
+ virshControlPtr priv = NULL;
+
if (!data)
return;
+ priv = data->ctl->privData;
if (data->cb_id >= 0)
- virConnectDomainEventDeregisterAny(data->ctl->conn, data->cb_id);
+ virConnectDomainEventDeregisterAny(priv->conn, data->cb_id);
if (data->cb_id2 >= 0)
- virConnectDomainEventDeregisterAny(data->ctl->conn, data->cb_id2);
+ virConnectDomainEventDeregisterAny(priv->conn, data->cb_id2);
VIR_FREE(data);
}
/**
- * vshBlockJobWait:
- * @data: private data initialized by vshBlockJobWaitInit
+ * virshBlockJobWait:
+ * @data: private data initialized by virshBlockJobWaitInit
*
* Waits for the block job to complete. This function prefers to get an event
* from libvirt but still has fallback means if the device name can't be matched
* VIR_DOMAIN_BLOCK_JOB_READY.
*/
static int
-vshBlockJobWait(vshBlockJobWaitDataPtr data)
+virshBlockJobWait(virshBlockJobWaitDataPtr data)
{
/* For two phase jobs like active commit or block copy, the marker reaches
* 100% and an event fires. In case where virsh would not be able to match
sigaddset(&sigmask, SIGINT);
intCaught = 0;
- sig_action.sa_sigaction = vshCatchInt;
+ sig_action.sa_sigaction = virshCatchInt;
sig_action.sa_flags = SA_SIGINFO;
sigemptyset(&sig_action.sa_mask);
sigaction(SIGINT, &sig_action, &old_sig_action);
}
if (data->verbose)
- vshPrintJobProgress(data->job_name, info.end - info.cur, info.end);
+ virshPrintJobProgress(data->job_name, info.end - info.cur,
+ info.end);
if (data->timeout && virTimeMillisNow(&curr) < 0) {
vshSaveLibvirtError();
if (data->verbose &&
(ret == VIR_DOMAIN_BLOCK_JOB_COMPLETED ||
ret == VIR_DOMAIN_BLOCK_JOB_READY))
- vshPrintJobProgress(data->job_name, 0, 1);
+ virshPrintJobProgress(data->job_name, 0, 1);
sigaction(SIGINT, &old_sig_action, NULL);
return ret;
int abort_flags = 0;
unsigned int flags = 0;
unsigned long bandwidth = 0;
- vshBlockJobWaitDataPtr bjWait = NULL;
+ virshBlockJobWaitDataPtr bjWait = NULL;
VSH_EXCLUSIVE_OPTIONS("pivot", "keep-overlay");
if (async)
abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (blocking &&
- !(bjWait = vshBlockJobWaitInit(ctl, dom, path, _("Block commit"),
- verbose, timeout, async)))
+ !(bjWait = virshBlockJobWaitInit(ctl, dom, path, _("Block commit"),
+ verbose, timeout, async)))
goto cleanup;
if (virDomainBlockCommit(dom, path, base, top, bandwidth, flags) < 0)
}
/* Execution continues here only if --wait or friends were specified */
- switch (vshBlockJobWait(bjWait)) {
+ switch (virshBlockJobWait(bjWait)) {
case -1:
goto cleanup;
ret = true;
cleanup:
virDomainFree(dom);
- vshBlockJobWaitFree(bjWait);
+ virshBlockJobWaitFree(bjWait);
return ret;
}
const char *xml = NULL;
char *xmlstr = NULL;
virTypedParameterPtr params = NULL;
- vshBlockJobWaitDataPtr bjWait = NULL;
+ virshBlockJobWaitDataPtr bjWait = NULL;
int nparams = 0;
if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0)
}
}
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
goto cleanup;
if (blocking &&
- !(bjWait = vshBlockJobWaitInit(ctl, dom, path, _("Block Copy"), verbose,
- timeout, async)))
+ !(bjWait = virshBlockJobWaitInit(ctl, dom, path, _("Block Copy"),
+ verbose, timeout, async)))
goto cleanup;
if (xml) {
}
/* Execution continues here only if --wait or friends were specified */
- switch (vshBlockJobWait(bjWait)) {
+ switch (virshBlockJobWait(bjWait)) {
case -1:
goto cleanup;
VIR_FREE(xmlstr);
virTypedParamsFree(params, nparams);
virDomainFree(dom);
- vshBlockJobWaitFree(bjWait);
+ virshBlockJobWaitFree(bjWait);
return ret;
}
{.name = NULL}
};
-VIR_ENUM_DECL(vshDomainBlockJob)
-VIR_ENUM_IMPL(vshDomainBlockJob,
+VIR_ENUM_DECL(virshDomainBlockJob)
+VIR_ENUM_IMPL(virshDomainBlockJob,
VIR_DOMAIN_BLOCK_JOB_TYPE_LAST,
N_("Unknown job"),
N_("Block Pull"),
N_("Active Block Commit"))
static const char *
-vshDomainBlockJobToString(int type)
+virshDomainBlockJobToString(int type)
{
- const char *str = vshDomainBlockJobTypeToString(type);
+ const char *str = virshDomainBlockJobTypeToString(type);
return str ? _(str) : _("Unknown job");
}
static bool
-vshBlockJobInfo(vshControl *ctl,
- virDomainPtr dom,
- const char *path,
- bool raw,
- bool bytes)
+virshBlockJobInfo(vshControl *ctl,
+ virDomainPtr dom,
+ const char *path,
+ bool raw,
+ bool bytes)
{
virDomainBlockJobInfo info;
+ virshControlPtr priv = ctl->privData;
unsigned long long speed;
unsigned int flags = 0;
bool ret = false;
/* If bytes were requested, or if raw mode is not forcing a MiB/s
* query and cache can't prove failure, then query bytes/sec. */
- if (bytes || !(raw || ctl->blockJobNoBytes)) {
+ if (bytes || !(raw || priv->blockJobNoBytes)) {
flags |= VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES;
rc = virDomainGetBlockJobInfo(dom, path, &info, flags);
if (rc < 0) {
/* Check for particular errors, let all the rest be fatal. */
switch (last_error->code) {
case VIR_ERR_INVALID_ARG:
- ctl->blockJobNoBytes = true;
+ priv->blockJobNoBytes = true;
/* fallthrough */
case VIR_ERR_OVERFLOW:
if (!bytes && !raw) {
if (raw) {
vshPrint(ctl, _(" type=%s\n bandwidth=%lu\n cur=%llu\n end=%llu\n"),
- vshDomainBlockJobTypeToString(info.type),
+ virshDomainBlockJobTypeToString(info.type),
info.bandwidth, info.cur, info.end);
} else {
- vshPrintJobProgress(vshDomainBlockJobToString(info.type),
- info.end - info.cur, info.end);
+ virshPrintJobProgress(virshDomainBlockJobToString(info.type),
+ info.end - info.cur, info.end);
if (speed) {
const char *unit;
double val = vshPrettyCapacity(speed, &unit);
static bool
-vshBlockJobSetSpeed(vshControl *ctl,
- const vshCmd *cmd,
- virDomainPtr dom,
- const char *path)
+virshBlockJobSetSpeed(vshControl *ctl,
+ const vshCmd *cmd,
+ virDomainPtr dom,
+ const char *path)
{
unsigned long bandwidth;
static bool
-vshBlockJobAbort(virDomainPtr dom,
- const char *path,
- bool pivot,
- bool async)
+virshBlockJobAbort(virDomainPtr dom,
+ const char *path,
+ bool pivot,
+ bool async)
{
unsigned int flags = 0;
/* XXX also support --bytes with bandwidth mode */
VSH_EXCLUSIVE_OPTIONS_VAR(bytes, bandwidth);
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
goto cleanup;
/* XXX Allow path to be optional to list info on all devices at once */
goto cleanup;
if (bandwidth)
- ret = vshBlockJobSetSpeed(ctl, cmd, dom, path);
+ ret = virshBlockJobSetSpeed(ctl, cmd, dom, path);
else if (abortMode || pivot || async)
- ret = vshBlockJobAbort(dom, path, pivot, async);
+ ret = virshBlockJobAbort(dom, path, pivot, async);
else
- ret = vshBlockJobInfo(ctl, dom, path, raw, bytes);
+ ret = virshBlockJobInfo(ctl, dom, path, raw, bytes);
cleanup:
if (dom)
const char *base = NULL;
unsigned long bandwidth = 0;
unsigned int flags = 0;
- vshBlockJobWaitDataPtr bjWait = NULL;
+ virshBlockJobWaitDataPtr bjWait = NULL;
VSH_REQUIRE_OPTION("verbose", "wait");
VSH_REQUIRE_OPTION("async", "wait");
if (vshCommandOptBool(cmd, "keep-relative"))
flags |= VIR_DOMAIN_BLOCK_REBASE_RELATIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (blocking &&
- !(bjWait = vshBlockJobWaitInit(ctl, dom, path, _("Block Pull"), verbose,
- timeout, async)))
+ !(bjWait = virshBlockJobWaitInit(ctl, dom, path, _("Block Pull"),
+ verbose, timeout, async)))
goto cleanup;
if (base || flags) {
}
/* Execution continues here only if --wait or friends were specified */
- switch (vshBlockJobWait(bjWait)) {
+ switch (virshBlockJobWait(bjWait)) {
case -1:
goto cleanup;
cleanup:
virDomainFree(dom);
- vshBlockJobWaitFree(bjWait);
+ virshBlockJobWaitFree(bjWait);
return ret;
}
else
flags |= VIR_DOMAIN_BLOCK_RESIZE_BYTES;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (virDomainBlockResize(dom, path, size, flags) < 0) {
{
bool ret = false;
int state;
+ virshControlPtr priv = ctl->privData;
- if ((state = vshDomainState(ctl, dom, NULL)) < 0) {
+ if ((state = virshDomainState(ctl, dom, NULL)) < 0) {
vshError(ctl, "%s", _("Unable to get domain status"));
goto cleanup;
}
}
vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom));
- vshPrintExtra(ctl, _("Escape character is %s\n"), ctl->escapeChar);
+ vshPrintExtra(ctl, _("Escape character is %s\n"), priv->escapeChar);
fflush(stdout);
- if (vshRunConsole(ctl, dom, name, flags) == 0)
+ if (virshRunConsole(ctl, dom, name, flags) == 0)
ret = true;
cleanup:
unsigned int flags = 0;
const char *name = NULL;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "devname", &name) < 0) /* sc_prohibit_devname */
xmlNodePtr cur = NULL;
char *xml_buf = NULL;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "interface", &iface) < 0 ||
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "interface", &device) < 0)
memset(&outbound, 0, sizeof(outbound));
if (inboundStr) {
- if (vshParseRateStr(ctl, inboundStr, &inbound) < 0)
+ if (virshParseRateStr(ctl, inboundStr, &inbound) < 0)
goto cleanup;
/* we parse the rate as unsigned long long, but the API
* only accepts UINT */
}
if (outboundStr) {
- if (vshParseRateStr(ctl, outboundStr, &outbound) < 0)
+ if (virshParseRateStr(ctl, outboundStr, &outbound) < 0)
goto cleanup;
if (outbound.average > UINT_MAX || outbound.peak > UINT_MAX ||
outbound.burst > UINT_MAX) {
const char *name;
bool ret = true;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (virDomainSuspend(dom) == 0) {
unsigned int suspendTarget;
unsigned long long duration = 0;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (vshCommandOptULongLong(ctl, cmd, "duration", &duration) < 0)
bool ret = false;
unsigned int flags = 0;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (virDomainPMWakeup(dom, flags) < 0) {
virStorageVolPtr vol;
char *source;
char *target;
-} vshUndefineVolume;
+} virshUndefineVolume;
static bool
cmdUndefine(vshControl *ctl, const vshCmd *cmd)
const char *vol_string = NULL; /* string containing volumes to delete */
char **vol_list = NULL; /* tokenized vol_string */
int nvol_list = 0;
- vshUndefineVolume *vols = NULL; /* info about the volumes to delete*/
+ virshUndefineVolume *vols = NULL; /* info about the volumes to delete*/
size_t nvols = 0;
char *def = NULL; /* domain def */
xmlDocPtr doc = NULL;
char *pool = NULL;
size_t i;
size_t j;
+ virshControlPtr priv = ctl->privData;
ignore_value(vshCommandOptString(ctl, cmd, "storage", &vol_string));
if (nvram)
flags |= VIR_DOMAIN_UNDEFINE_NVRAM;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
/* Do some flag manipulation. The goal here is to disable bits
for (i = 0; i < nvol_nodes; i++) {
ctxt->node = vol_nodes[i];
- vshUndefineVolume vol;
+ virshUndefineVolume vol;
VIR_FREE(source);
VIR_FREE(target);
VIR_FREE(pool);
continue;
}
- if (!(storagepool = virStoragePoolLookupByName(ctl->conn,
+ if (!(storagepool = virStoragePoolLookupByName(priv->conn,
pool))) {
vshPrint(ctl,
_("Storage pool '%s' for volume '%s' not found."),
virStoragePoolFree(storagepool);
} else {
- vol.vol = virStorageVolLookupByPath(ctl->conn, source);
+ vol.vol = virStorageVolLookupByPath(priv->conn, source);
}
if (!vol.vol) {
size_t nfds = 0;
int *fds = NULL;
- if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL,
- VSH_BYNAME | VSH_BYUUID)))
+ if (!(dom = virshCommandOptDomainBy(ctl, cmd, NULL,
+ VIRSH_BYNAME | VIRSH_BYUUID)))
return false;
if (virDomainGetID(dom) != (unsigned int)-1) {
static void
doSave(void *opaque)
{
- vshCtrlData *data = opaque;
+ virshCtrlData *data = opaque;
vshControl *ctl = data->ctl;
const vshCmd *cmd = data->cmd;
char ret = '1';
if (vshCommandOptStringReq(ctl, cmd, "xml", &xmlfile) < 0)
goto out;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
goto out;
if (xmlfile &&
void *opaque);
static bool
-vshWatchJob(vshControl *ctl,
- virDomainPtr dom,
- bool verbose,
- int pipe_fd,
- int timeout_ms,
- jobWatchTimeoutFunc timeout_func,
- void *opaque,
- const char *label)
+virshWatchJob(vshControl *ctl,
+ virDomainPtr dom,
+ bool verbose,
+ int pipe_fd,
+ int timeout_ms,
+ jobWatchTimeoutFunc timeout_func,
+ void *opaque,
+ const char *label)
{
struct sigaction sig_action;
struct sigaction old_sig_action;
sigaddset(&sigmask, SIGINT);
intCaught = 0;
- sig_action.sa_sigaction = vshCatchInt;
+ sig_action.sa_sigaction = virshCatchInt;
sig_action.sa_flags = SA_SIGINFO;
sigemptyset(&sig_action.sa_mask);
sigaction(SIGINT, &sig_action, &old_sig_action);
retchar == '0') {
if (verbose) {
/* print [100 %] */
- vshPrintJobProgress(label, 0, 1);
+ virshPrintJobProgress(label, 0, 1);
}
break;
}
pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL);
if (ret == 0) {
if (verbose)
- vshPrintJobProgress(label, jobinfo.dataRemaining,
- jobinfo.dataTotal);
+ virshPrintJobProgress(label, jobinfo.dataRemaining,
+ jobinfo.dataTotal);
if (!jobStarted &&
(jobinfo.type == VIR_DOMAIN_JOB_BOUNDED ||
int p[2] = {-1. -1};
virThread workerThread;
bool verbose = false;
- vshCtrlData data;
+ virshCtrlData data;
const char *to = NULL;
const char *name = NULL;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "file", &to) < 0)
&data) < 0)
goto cleanup;
- ret = vshWatchJob(ctl, dom, verbose, p[0], 0, NULL, NULL, _("Save"));
+ ret = virshWatchJob(ctl, dom, verbose, p[0], 0, NULL, NULL, _("Save"));
virThreadJoin(&workerThread);
bool ret = false;
unsigned int flags = 0;
char *xml = NULL;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "security-info"))
flags |= VIR_DOMAIN_XML_SECURE;
if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0)
return false;
- xml = virDomainSaveImageGetXMLDesc(ctl->conn, file, flags);
+ xml = virDomainSaveImageGetXMLDesc(priv->conn, file, flags);
if (!xml)
goto cleanup;
const char *xmlfile = NULL;
char *xml = NULL;
unsigned int flags = 0;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "running"))
flags |= VIR_DOMAIN_SAVE_RUNNING;
if (virFileReadAll(xmlfile, VSH_MAX_XML_FILE, &xml) < 0)
goto cleanup;
- if (virDomainSaveImageDefineXML(ctl->conn, file, xml, flags) < 0) {
+ if (virDomainSaveImageDefineXML(priv->conn, file, xml, flags) < 0) {
vshError(ctl, _("Failed to update %s"), file);
goto cleanup;
}
bool ret = false;
unsigned int getxml_flags = VIR_DOMAIN_XML_SECURE;
unsigned int define_flags = 0;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "running"))
define_flags |= VIR_DOMAIN_SAVE_RUNNING;
return false;
#define EDIT_GET_XML \
- virDomainSaveImageGetXMLDesc(ctl->conn, file, getxml_flags)
+ virDomainSaveImageGetXMLDesc(priv->conn, file, getxml_flags)
#define EDIT_NOT_CHANGED \
do { \
vshPrint(ctl, _("Saved image %s XML configuration " \
goto edit_cleanup; \
} while (0)
#define EDIT_DEFINE \
- (virDomainSaveImageDefineXML(ctl->conn, file, doc_edited, define_flags) == 0)
+ (virDomainSaveImageDefineXML(priv->conn, file, doc_edited, define_flags) == 0)
#include "virsh-edit.c"
vshPrint(ctl, _("State file %s edited.\n"), file);
doManagedsave(void *opaque)
{
char ret = '1';
- vshCtrlData *data = opaque;
+ virshCtrlData *data = opaque;
vshControl *ctl = data->ctl;
const vshCmd *cmd = data->cmd;
virDomainPtr dom = NULL;
if (vshCommandOptBool(cmd, "paused"))
flags |= VIR_DOMAIN_SAVE_PAUSED;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
goto out;
if (virDomainManagedSave(dom, flags) < 0) {
bool ret = false;
bool verbose = false;
const char *name = NULL;
- vshCtrlData data;
+ virshCtrlData data;
virThread workerThread;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (vshCommandOptBool(cmd, "verbose"))
&data) < 0)
goto cleanup;
- ret = vshWatchJob(ctl, dom, verbose, p[0], 0,
- NULL, NULL, _("Managedsave"));
+ ret = virshWatchJob(ctl, dom, verbose, p[0], 0,
+ NULL, NULL, _("Managedsave"));
virThreadJoin(&workerThread);
bool ret = false;
int hassave;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
hassave = virDomainHasManagedSaveImage(dom, 0);
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
/* Print SchedulerType */
unsigned int flags = 0;
const char *xmlfile = NULL;
char *xml = NULL;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
goto cleanup;
if (((flags || xml)
- ? virDomainRestoreFlags(ctl->conn, from, xml, flags)
- : virDomainRestore(ctl->conn, from)) < 0) {
+ ? virDomainRestoreFlags(priv->conn, from, xml, flags)
+ : virDomainRestore(priv->conn, from)) < 0) {
vshError(ctl, _("Failed to restore domain from %s"), from);
goto cleanup;
}
doDump(void *opaque)
{
char ret = '1';
- vshCtrlData *data = opaque;
+ virshCtrlData *data = opaque;
vshControl *ctl = data->ctl;
const vshCmd *cmd = data->cmd;
virDomainPtr dom = NULL;
if (vshCommandOptStringReq(ctl, cmd, "file", &to) < 0)
goto out;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
goto out;
if (vshCommandOptBool(cmd, "live"))
bool verbose = false;
const char *name = NULL;
const char *to = NULL;
- vshCtrlData data;
+ virshCtrlData data;
virThread workerThread;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "file", &to) < 0)
&data) < 0)
goto cleanup;
- ret = vshWatchJob(ctl, dom, verbose, p[0], 0, NULL, NULL, _("Dump"));
+ ret = virshWatchJob(ctl, dom, verbose, p[0], 0, NULL, NULL, _("Dump"));
virThreadJoin(&workerThread);
* Generate string: '<domain name>-<timestamp>[<extension>]'
*/
static char *
-vshGenFileName(vshControl *ctl, virDomainPtr dom, const char *mime)
+virshGenFileName(vshControl *ctl, virDomainPtr dom, const char *mime)
{
char timestr[100];
time_t cur_time;
bool created = false;
bool generated = false;
char *mime = NULL;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", (const char **) &file) < 0)
return false;
if (vshCommandOptUInt(ctl, cmd, "screen", &screen) < 0)
return false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
- if (!(st = virStreamNew(ctl->conn, 0)))
+ if (!(st = virStreamNew(priv->conn, 0)))
goto cleanup;
mime = virDomainScreenshot(dom, st, screen, flags);
}
if (!file) {
- if (!(file = vshGenFileName(ctl, dom, mime)))
+ if (!(file = virshGenFileName(ctl, dom, mime)))
goto cleanup;
generated = true;
}
created = true;
}
- if (virStreamRecvAll(st, vshStreamSink, &fd) < 0) {
+ if (virStreamRecvAll(st, virshStreamSink, &fd) < 0) {
vshError(ctl, _("could not receive data from domain %s"), name);
goto cleanup;
}
if (vshCommandOptStringReq(ctl, cmd, "password", &password) < 0)
return false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (virDomainSetUserPassword(dom, user, password, flags) < 0)
bool ret = true;
const char *name;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (virDomainResume(dom) == 0) {
tmp++;
}
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
goto cleanup;
if (flags)
tmp++;
}
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
goto cleanup;
if (virDomainReboot(dom, flags) == 0) {
bool ret = true;
const char *name;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (virDomainReset(dom, 0) == 0) {
{.name = NULL}
};
-VIR_ENUM_DECL(vshDomainJob)
-VIR_ENUM_IMPL(vshDomainJob,
+VIR_ENUM_DECL(virshDomainJob)
+VIR_ENUM_IMPL(virshDomainJob,
VIR_DOMAIN_JOB_LAST,
N_("None"),
N_("Bounded"),
N_("Cancelled"))
static const char *
-vshDomainJobToString(int type)
+virshDomainJobToString(int type)
{
- const char *str = vshDomainJobTypeToString(type);
+ const char *str = virshDomainJobTypeToString(type);
return str ? _(str) : _("unknown");
}
unsigned int flags = 0;
int rc;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptBool(cmd, "completed"))
goto cleanup;
vshPrint(ctl, "%-17s %-12s\n", _("Job type:"),
- vshDomainJobToString(info.type));
+ virshDomainJobToString(info.type));
if (info.type != VIR_DOMAIN_JOB_BOUNDED &&
info.type != VIR_DOMAIN_JOB_UNBOUNDED &&
(!(flags & VIR_DOMAIN_JOB_STATS_COMPLETED) ||
virDomainPtr dom;
bool ret = true;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (virDomainAbortJob(dom) < 0)
*/
static int
-vshCPUCountCollect(vshControl *ctl,
- virDomainPtr dom,
- unsigned int flags,
- bool checkState)
+virshCPUCountCollect(vshControl *ctl,
+ virDomainPtr dom,
+ unsigned int flags,
+ bool checkState)
{
int ret = -2;
virDomainInfo info;
if (guest)
flags |= VIR_DOMAIN_VCPU_GUEST;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (all) {
- int conf_max = vshCPUCountCollect(ctl, dom, VIR_DOMAIN_AFFECT_CONFIG |
- VIR_DOMAIN_VCPU_MAXIMUM, true);
- int conf_cur = vshCPUCountCollect(ctl, dom, VIR_DOMAIN_AFFECT_CONFIG, true);
- int live_max = vshCPUCountCollect(ctl, dom, VIR_DOMAIN_AFFECT_LIVE |
- VIR_DOMAIN_VCPU_MAXIMUM, true);
- int live_cur = vshCPUCountCollect(ctl, dom, VIR_DOMAIN_AFFECT_LIVE, true);
+ int conf_max = virshCPUCountCollect(ctl, dom,
+ VIR_DOMAIN_AFFECT_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, true);
+ int conf_cur = virshCPUCountCollect(ctl, dom,
+ VIR_DOMAIN_AFFECT_CONFIG, true);
+ int live_max = virshCPUCountCollect(ctl, dom,
+ VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM, true);
+ int live_cur = virshCPUCountCollect(ctl, dom,
+ VIR_DOMAIN_AFFECT_LIVE, true);
if (conf_max == -2 || conf_cur == -2 || live_max == -2 || live_cur == -2)
goto cleanup;
#undef PRINT_COUNT
} else {
- int count = vshCPUCountCollect(ctl, dom, flags, false);
+ int count = virshCPUCountCollect(ctl, dom, flags, false);
if (count < 0)
goto cleanup;
bool ret = false;
bool pretty = vshCommandOptBool(cmd, "pretty");
int n, m;
+ virshControlPtr priv = ctl->privData;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
- if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0)
+ if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0)
goto cleanup;
if (virDomainGetInfo(dom, &info) != 0)
if (cpuinfo) {
vshPrint(ctl, "%-15s %d\n", _("CPU:"), cpuinfo[n].cpu);
vshPrint(ctl, "%-15s %s\n", _("State:"),
- vshDomainVcpuStateToString(cpuinfo[n].state));
+ virshDomainVcpuStateToString(cpuinfo[n].state));
if (cpuinfo[n].cpuTime != 0) {
double cpuUsed = cpuinfo[n].cpuTime;
* Helper function to print vcpupin info.
*/
static bool
-vshPrintPinInfo(unsigned char *cpumap, size_t cpumaplen)
+virshPrintPinInfo(unsigned char *cpumap, size_t cpumaplen)
{
char *str = NULL;
}
static unsigned char *
-vshParseCPUList(vshControl *ctl, int *cpumaplen, const char *cpulist, int maxcpu)
+virshParseCPUList(vshControl *ctl, int *cpumaplen,
+ const char *cpulist, int maxcpu)
{
unsigned char *cpumap = NULL;
virBitmapPtr map = NULL;
bool current = vshCommandOptBool(cmd, "current");
int got_vcpu;
unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+ virshControlPtr priv = ctl->privData;
VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
return false;
}
- if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0)
+ if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0)
return false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
/* Query mode: show CPU affinity information then exit.*/
if (flags == -1)
flags = VIR_DOMAIN_AFFECT_CURRENT;
- if ((ncpus = vshCPUCountCollect(ctl, dom, flags, true)) < 0) {
+ if ((ncpus = virshCPUCountCollect(ctl, dom, flags, true)) < 0) {
if (ncpus == -1) {
if (flags & VIR_DOMAIN_AFFECT_LIVE)
vshError(ctl, "%s", _("cannot get vcpupin for offline domain"));
continue;
vshPrint(ctl, "%4zu: ", i);
- ret = vshPrintPinInfo(VIR_GET_CPUMAP(cpumap, cpumaplen, i),
- cpumaplen);
+ ret = virshPrintPinInfo(VIR_GET_CPUMAP(cpumap, cpumaplen, i),
+ cpumaplen);
vshPrint(ctl, "\n");
if (!ret)
break;
}
} else {
/* Pin mode: pinning specified vcpu to specified physical cpus*/
- if (!(cpumap = vshParseCPUList(ctl, &cpumaplen, cpulist, maxcpu)))
+ if (!(cpumap = virshParseCPUList(ctl, &cpumaplen, cpulist, maxcpu)))
goto cleanup;
if (flags == -1) {
bool current = vshCommandOptBool(cmd, "current");
bool query = false; /* Query mode if no cpulist */
unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+ virshControlPtr priv = ctl->privData;
VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
if (!current && !live && !config)
flags = -1;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "cpulist", &cpulist) < 0) {
}
query = !cpulist;
- if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0) {
+ if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0) {
virDomainFree(dom);
return false;
}
vshPrintExtra(ctl, "%s %s\n", _("emulator:"), _("CPU Affinity"));
vshPrintExtra(ctl, "----------------------------------\n");
vshPrintExtra(ctl, " *: ");
- ret = vshPrintPinInfo(cpumap, cpumaplen);
+ ret = virshPrintPinInfo(cpumap, cpumaplen);
vshPrint(ctl, "\n");
}
goto cleanup;
}
/* Pin mode: pinning emulator threads to specified physical cpus*/
- if (!(cpumap = vshParseCPUList(ctl, &cpumaplen, cpulist, maxcpu)))
+ if (!(cpumap = virshParseCPUList(ctl, &cpumaplen, cpulist, maxcpu)))
goto cleanup;
if (flags == -1)
if (maximum)
flags |= VIR_DOMAIN_VCPU_MAXIMUM;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptInt(ctl, cmd, "count", &count) < 0 || count <= 0)
size_t i;
int maxcpu;
unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+ virshControlPtr priv = ctl->privData;
VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
- if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0)
+ if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0)
goto cleanup;
if ((niothreads = virDomainGetIOThreadInfo(dom, &info, flags)) < 0) {
for (i = 0; i < niothreads; i++) {
vshPrint(ctl, " %-15u ", info[i]->iothread_id);
- ignore_value(vshPrintPinInfo(info[i]->cpumap, info[i]->cpumaplen));
+ ignore_value(virshPrintPinInfo(info[i]->cpumap, info[i]->cpumaplen));
vshPrint(ctl, "\n");
virDomainIOThreadInfoFree(info[i]);
}
unsigned char *cpumap = NULL;
int cpumaplen;
unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+ virshControlPtr priv = ctl->privData;
VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptUInt(ctl, cmd, "iothread", &iothread_id) < 0)
goto cleanup;
}
- if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0)
+ if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0)
goto cleanup;
- if (!(cpumap = vshParseCPUList(ctl, &cpumaplen, cpulist, maxcpu)))
+ if (!(cpumap = virshParseCPUList(ctl, &cpumaplen, cpulist, maxcpu)))
goto cleanup;
if (virDomainPinIOThread(dom, iothread_id,
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptInt(ctl, cmd, "id", &iothread_id) < 0)
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptInt(ctl, cmd, "id", &iothread_id) < 0)
xmlDocPtr xml = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlNodePtr node;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "error"))
flags |= VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE;
goto cleanup;
}
- result = virConnectCompareCPU(ctl->conn, snippet, flags);
+ result = virConnectCompareCPU(priv->conn, snippet, flags);
switch (result) {
case VIR_CPU_COMPARE_INCOMPATIBLE:
xmlXPathContextPtr ctxt = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
size_t i;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "features"))
flags |= VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES;
}
}
- result = virConnectBaselineCPU(ctl->conn,
+ result = virConnectBaselineCPU(priv->conn,
(const char **)list, count, flags);
if (result) {
bool ret = false;
int rv = 0;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
show_total = vshCommandOptBool(cmd, "total");
unsigned int flags = 0;
size_t nfds = 0;
int *fds = NULL;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
flags |= VIR_DOMAIN_START_VALIDATE;
if (nfds)
- dom = virDomainCreateXMLWithFiles(ctl->conn, buffer, nfds, fds, flags);
+ dom = virDomainCreateXMLWithFiles(priv->conn, buffer, nfds, fds, flags);
else
- dom = virDomainCreateXML(ctl->conn, buffer, flags);
+ dom = virDomainCreateXML(priv->conn, buffer, flags);
if (!dom) {
vshError(ctl, _("Failed to create domain from %s"), from);
bool ret = true;
char *buffer;
unsigned int flags = 0;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
return false;
if (flags)
- dom = virDomainDefineXMLFlags(ctl->conn, buffer, flags);
+ dom = virDomainDefineXMLFlags(priv->conn, buffer, flags);
else
- dom = virDomainDefineXML(ctl->conn, buffer);
+ dom = virDomainDefineXML(priv->conn, buffer);
VIR_FREE(buffer);
if (dom != NULL) {
unsigned int flags = 0;
int result;
- if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
return false;
if (vshCommandOptBool(cmd, "graceful"))
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
- if ((state = vshDomainState(ctl, dom, NULL)) < 0)
+ if ((state = virshDomainState(ctl, dom, NULL)) < 0)
goto cleanup;
while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
if (edit || desc) {
if (!desc) {
- desc = vshGetDomainDescription(ctl, dom, title,
+ desc = virshGetDomainDescription(ctl, dom, title,
config?VIR_DOMAIN_XML_INACTIVE:0);
if (!desc)
goto cleanup;
title ? _("Domain title updated successfully") :
_("Domain description updated successfully"));
} else {
- desc = vshGetDomainDescription(ctl, dom, title,
+ desc = virshGetDomainDescription(ctl, dom, title,
config?VIR_DOMAIN_XML_INACTIVE:0);
if (!desc)
goto cleanup;
/* helper to add new metadata using the --edit option */
static char *
-vshDomainGetEditMetadata(vshControl *ctl,
- virDomainPtr dom,
- const char *uri,
- unsigned int flags)
+virshDomainGetEditMetadata(vshControl *ctl,
+ virDomainPtr dom,
+ const char *uri,
+ unsigned int flags)
{
char *ret;
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "uri", &uri) < 0 ||
vshPrint("%s\n", _("Metadata modified"));
} else if (edit) {
#define EDIT_GET_XML \
- vshDomainGetEditMetadata(ctl, dom, uri, flags)
+ virshDomainGetEditMetadata(ctl, dom, uri, flags)
#define EDIT_NOT_CHANGED \
do { \
vshPrint(ctl, "%s", _("Metadata not changed")); \
virDomainPtr dom;
bool ret = true;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (virDomainInjectNMI(dom, 0) < 0)
};
static int
-vshKeyCodeGetInt(const char *key_name)
+virshKeyCodeGetInt(const char *key_name)
{
unsigned int val;
int keycode;
unsigned int keycodes[VIR_DOMAIN_SEND_KEY_MAX_KEYS];
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptString(ctl, cmd, "codeset", &codeset_option) <= 0)
goto cleanup;
}
- if ((keycode = vshKeyCodeGetInt(opt->data)) < 0) {
+ if ((keycode = virshKeyCodeGetInt(opt->data)) < 0) {
if ((keycode = virKeycodeValueFromString(codeset, opt->data)) < 0) {
vshError(ctl, _("invalid keycode: '%s'"), opt->data);
goto cleanup;
long long pid_value;
int signum;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptLongLong(ctl, cmd, "pid", &pid_value) < 0)
if (!current && !live && !config)
flags = -1;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
/* The API expects 'unsigned long' KiB, so depending on whether we
if (!current && !live && !config)
flags = -1;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
/* The API expects 'unsigned long' KiB, so depending on whether we
};
/**
- * vshMemtuneGetSize
+ * virshMemtuneGetSize
*
* @cmd: pointer to vshCmd
* @name: name of a parameter for which we would like to get a value
* <0 in all other cases
*/
static int
-vshMemtuneGetSize(vshControl *ctl, const vshCmd *cmd, const char *name, long long *value)
+virshMemtuneGetSize(vshControl *ctl, const vshCmd *cmd,
+ const char *name, long long *value)
{
int ret;
unsigned long long tmp;
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
#define PARSE_MEMTUNE_PARAM(NAME, FIELD) \
- if ((rc = vshMemtuneGetSize(ctl, cmd, NAME, &tmpVal)) < 0) { \
+ if ((rc = virshMemtuneGetSize(ctl, cmd, NAME, &tmpVal)) < 0) { \
vshError(ctl, _("Unable to parse integer parameter %s"), NAME); \
goto cleanup; \
} \
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "nodeset", &nodeset) < 0)
bool pad = false;
virJSONValuePtr pretty = NULL;
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
* "qemu-monitor-event" command
*/
-struct vshQemuEventData {
+struct virshQemuEventData {
vshControl *ctl;
bool loop;
bool pretty;
int count;
};
-typedef struct vshQemuEventData vshQemuEventData;
+typedef struct virshQemuEventData virshQemuEventData;
static void
-vshEventPrint(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom,
- const char *event, long long seconds, unsigned int micros,
- const char *details, void *opaque)
+virshEventPrint(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom,
+ const char *event, long long seconds, unsigned int micros,
+ const char *details, void *opaque)
{
- vshQemuEventData *data = opaque;
+ virshQemuEventData *data = opaque;
virJSONValuePtr pretty = NULL;
char *str = NULL;
int eventId = -1;
int timeout = 0;
const char *event = NULL;
- vshQemuEventData data;
+ virshQemuEventData data;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "regex"))
flags |= VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_REGEX;
return false;
if (vshCommandOptBool(cmd, "domain"))
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (vshEventStart(ctl, timeout) < 0)
goto cleanup;
- if ((eventId = virConnectDomainQemuMonitorEventRegister(ctl->conn, dom,
+ if ((eventId = virConnectDomainQemuMonitorEventRegister(priv->conn, dom,
event,
- vshEventPrint,
+ virshEventPrint,
&data, NULL,
flags)) < 0)
goto cleanup;
cleanup:
vshEventCleanup(ctl);
if (eventId >= 0 &&
- virConnectDomainQemuMonitorEventDeregister(ctl->conn, eventId) < 0)
+ virConnectDomainQemuMonitorEventDeregister(priv->conn, eventId) < 0)
ret = false;
if (dom)
virDomainFree(dom);
bool ret = false;
unsigned int flags = 0;
unsigned int pid_value; /* API uses unsigned int, not pid_t */
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptUInt(ctl, cmd, "pid", &pid_value) <= 0)
goto cleanup;
- if (!(dom = virDomainQemuAttach(ctl->conn, pid_value, flags))) {
+ if (!(dom = virDomainQemuAttach(priv->conn, pid_value, flags))) {
vshError(ctl, _("Failed to attach to pid %u"), pid_value);
goto cleanup;
}
bool pad = false;
virJSONValuePtr pretty = NULL;
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
bool setlabel = true;
virSecurityModelPtr secmodel = NULL;
virSecurityLabelPtr seclabel = NULL;
+ virshControlPtr priv = ctl->privData;
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
vshError(ctl, "%s", _("Failed to allocate security label"));
goto cleanup;
}
- if (virNodeGetSecurityModel(ctl->conn, secmodel) < 0)
+ if (virNodeGetSecurityModel(priv->conn, secmodel) < 0)
goto cleanup;
if (virDomainGetSecurityLabel(dom, seclabel) < 0)
goto cleanup;
if (migratable)
flags |= VIR_DOMAIN_XML_MIGRATABLE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
dump = virDomainGetXMLDesc(dom, flags);
char *configData;
char *xmlData;
unsigned int flags = 0;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "format", &format) < 0 ||
vshCommandOptStringReq(ctl, cmd, "config", &configFile) < 0)
if (virFileReadAll(configFile, VSH_MAX_XML_FILE, &configData) < 0)
return false;
- xmlData = virConnectDomainXMLFromNative(ctl->conn, format, configData, flags);
+ xmlData = virConnectDomainXMLFromNative(priv->conn, format, configData, flags);
if (xmlData != NULL) {
vshPrint(ctl, "%s", xmlData);
VIR_FREE(xmlData);
char *configData;
char *xmlData;
unsigned int flags = 0;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "format", &format) < 0 ||
vshCommandOptStringReq(ctl, cmd, "xml", &xmlFile) < 0)
if (virFileReadAll(xmlFile, VSH_MAX_XML_FILE, &xmlData) < 0)
return false;
- configData = virConnectDomainXMLToNative(ctl->conn, format, xmlData, flags);
+ configData = virConnectDomainXMLToNative(priv->conn, format, xmlData, flags);
if (configData != NULL) {
vshPrint(ctl, "%s", configData);
VIR_FREE(configData);
{
virDomainPtr dom;
- if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL,
- VSH_BYID|VSH_BYUUID)))
+ if (!(dom = virshCommandOptDomainBy(ctl, cmd, NULL,
+ VIRSH_BYID|VIRSH_BYUUID)))
return false;
vshPrint(ctl, "%s\n", virDomainGetName(dom));
const char *new_name = NULL;
bool ret = false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return ret;
if (vshCommandOptStringReq(ctl, cmd, "new-name", &new_name) < 0)
virDomainPtr dom;
unsigned int id;
- if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL,
- VSH_BYNAME|VSH_BYUUID)))
+ if (!(dom = virshCommandOptDomainBy(ctl, cmd, NULL,
+ VIRSH_BYNAME|VIRSH_BYUUID)))
return false;
id = virDomainGetID(dom);
virDomainPtr dom;
char uuid[VIR_UUID_STRING_BUFLEN];
- if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL,
- VSH_BYNAME|VSH_BYID)))
+ if (!(dom = virshCommandOptDomainBy(ctl, cmd, NULL,
+ VIRSH_BYNAME|VIRSH_BYID)))
return false;
if (virDomainGetUUIDString(dom, uuid) != -1)
const char *desturi = NULL;
const char *opt = NULL;
unsigned int flags = 0;
- vshCtrlData *data = opaque;
+ virshCtrlData *data = opaque;
vshControl *ctl = data->ctl;
const vshCmd *cmd = data->cmd;
sigset_t sigmask, oldsigmask;
if (pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask) < 0)
goto out_sig;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
goto out;
if (vshCommandOptStringReq(ctl, cmd, "desturi", &desturi) < 0)
}
static void
-vshMigrationTimeout(vshControl *ctl,
- virDomainPtr dom,
- void *opaque ATTRIBUTE_UNUSED)
+virshMigrationTimeout(vshControl *ctl,
+ virDomainPtr dom,
+ void *opaque ATTRIBUTE_UNUSED)
{
vshDebug(ctl, VSH_ERR_DEBUG, "suspending the domain, "
"since migration timed out\n");
bool functionReturn = false;
int timeout = 0;
bool live_flag = false;
- vshCtrlData data = { .dconn = NULL };
+ virshCtrlData data = { .dconn = NULL };
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptBool(cmd, "verbose"))
if (vshCommandOptStringReq(ctl, cmd, "desturi", &desturi) < 0)
goto cleanup;
- dconn = vshConnect(ctl, desturi, false);
+ dconn = virshConnect(ctl, desturi, false);
if (!dconn)
goto cleanup;
doMigrate,
&data) < 0)
goto cleanup;
- functionReturn = vshWatchJob(ctl, dom, verbose, p[0], timeout,
- vshMigrationTimeout, NULL, _("Migration"));
+ functionReturn = virshWatchJob(ctl, dom, verbose, p[0], timeout,
+ virshMigrationTimeout, NULL, _("Migration"));
virThreadJoin(&workerThread);
long long downtime = 0;
bool ret = false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptLongLong(ctl, cmd, "downtime", &downtime) < 0)
double value;
int rc;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
rc = vshCommandOptULongLong(ctl, cmd, "size", &size);
unsigned long bandwidth = 0;
bool ret = false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptULWrap(ctl, cmd, "bandwidth", &bandwidth) < 0)
unsigned long bandwidth;
bool ret = false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (virDomainMigrateGetMaxSpeed(dom, &bandwidth, 0) < 0)
const char *xpath_fmt = "string(/domain/devices/graphics[@type='%s']/%s)";
virSocketAddr addr;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (!virDomainIsActive(dom)) {
char *doc = NULL;
char *listen_addr = NULL;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
/* Check if the domain is active and don't rely on -1 for this */
bool ret = false;
char *doc;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
doc = virDomainGetXMLDesc(dom, 0);
virDomainPtr dom;
bool ret = false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
hostname = virDomainGetHostname(dom, 0);
*/
ATTRIBUTE_UNUSED
static bool
-vshNodeIsSuperset(xmlNodePtr n1, xmlNodePtr n2)
+virshNodeIsSuperset(xmlNodePtr n1, xmlNodePtr n2)
{
xmlNodePtr child1, child2;
xmlAttrPtr attr;
goto cleanup;
}
- if (!vshNodeIsSuperset(child1, child2))
+ if (!virshNodeIsSuperset(child1, child2))
goto cleanup;
break;
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (persistent &&
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "type", &type) < 0)
}
typedef enum {
- VSH_FIND_DISK_NORMAL,
- VSH_FIND_DISK_CHANGEABLE,
-} vshFindDiskType;
+ VIRSH_FIND_DISK_NORMAL,
+ VIRSH_FIND_DISK_CHANGEABLE,
+} virshFindDiskType;
/* Helper function to find disk device in XML doc. Returns the disk
* node on success, or NULL on failure. Caller must free the result
* @path: Fully-qualified path or target of disk device.
- * @type: Either VSH_FIND_DISK_NORMAL or VSH_FIND_DISK_CHANGEABLE.
+ * @type: Either VIRSH_FIND_DISK_NORMAL or VIRSH_FIND_DISK_CHANGEABLE.
*/
static xmlNodePtr
-vshFindDisk(const char *doc,
- const char *path,
- int type)
+virshFindDisk(const char *doc,
+ const char *path,
+ int type)
{
xmlDocPtr xml = NULL;
xmlXPathObjectPtr obj = NULL;
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
bool is_supported = true;
- if (type == VSH_FIND_DISK_CHANGEABLE) {
+ if (type == VIRSH_FIND_DISK_CHANGEABLE) {
xmlNodePtr n = obj->nodesetval->nodeTab[i];
is_supported = false;
}
typedef enum {
- VSH_UPDATE_DISK_XML_EJECT,
- VSH_UPDATE_DISK_XML_INSERT,
- VSH_UPDATE_DISK_XML_UPDATE,
-} vshUpdateDiskXMLType;
+ VIRSH_UPDATE_DISK_XML_EJECT,
+ VIRSH_UPDATE_DISK_XML_INSERT,
+ VIRSH_UPDATE_DISK_XML_UPDATE,
+} virshUpdateDiskXMLType;
/* Helper function to prepare disk XML. Could be used for disk
* detaching, media changing(ejecting, inserting, updating)
* success, or NULL on failure. Caller must free the result.
*/
static char *
-vshUpdateDiskXML(xmlNodePtr disk_node,
- const char *new_source,
- bool source_block,
- const char *target,
- vshUpdateDiskXMLType type)
+virshUpdateDiskXML(xmlNodePtr disk_node,
+ const char *new_source,
+ bool source_block,
+ const char *target,
+ virshUpdateDiskXMLType type)
{
xmlNodePtr source = NULL;
char *device_type = NULL;
break;
}
- if (type == VSH_UPDATE_DISK_XML_EJECT) {
+ if (type == VIRSH_UPDATE_DISK_XML_EJECT) {
if (!source) {
vshError(NULL, _("The disk device '%s' doesn't have media"), target);
goto cleanup;
goto cleanup;
}
- if (type == VSH_UPDATE_DISK_XML_INSERT && source) {
+ if (type == VIRSH_UPDATE_DISK_XML_INSERT && source) {
vshError(NULL, _("The disk device '%s' already has media"), target);
goto cleanup;
}
if (live)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "target", &target) < 0)
virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_AFFECT_LIVE;
- if (!(disk_node = vshFindDisk(doc, target, VSH_FIND_DISK_NORMAL)))
+ if (!(disk_node = virshFindDisk(doc, target, VIRSH_FIND_DISK_NORMAL)))
goto cleanup;
if (!(disk_xml = virXMLNodeToString(NULL, disk_node))) {
virDomainPtr dom_edited = NULL;
unsigned int query_flags = VIR_DOMAIN_XML_SECURE | VIR_DOMAIN_XML_INACTIVE;
unsigned int define_flags = VIR_DOMAIN_DEFINE_VALIDATE;
+ virshControlPtr priv = ctl->privData;
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
goto edit_cleanup; \
} while (0)
#define EDIT_DEFINE \
- (dom_edited = vshDomainDefine(ctl->conn, doc_edited, define_flags))
+ (dom_edited = virshDomainDefine(priv->conn, doc_edited, define_flags))
#define EDIT_RELAX \
do { \
define_flags &= ~VIR_DOMAIN_DEFINE_VALIDATE; \
/*
* "event" command
*/
-VIR_ENUM_DECL(vshDomainEvent)
-VIR_ENUM_IMPL(vshDomainEvent,
+VIR_ENUM_DECL(virshDomainEvent)
+VIR_ENUM_IMPL(virshDomainEvent,
VIR_DOMAIN_EVENT_LAST,
N_("Defined"),
N_("Undefined"),
N_("Crashed"))
static const char *
-vshDomainEventToString(int event)
+virshDomainEventToString(int event)
{
- const char *str = vshDomainEventTypeToString(event);
+ const char *str = virshDomainEventTypeToString(event);
return str ? _(str) : _("unknown");
}
-VIR_ENUM_DECL(vshDomainEventDefined)
-VIR_ENUM_IMPL(vshDomainEventDefined,
+VIR_ENUM_DECL(virshDomainEventDefined)
+VIR_ENUM_IMPL(virshDomainEventDefined,
VIR_DOMAIN_EVENT_DEFINED_LAST,
N_("Added"),
N_("Updated"),
N_("Renamed"))
-VIR_ENUM_DECL(vshDomainEventUndefined)
-VIR_ENUM_IMPL(vshDomainEventUndefined,
+VIR_ENUM_DECL(virshDomainEventUndefined)
+VIR_ENUM_IMPL(virshDomainEventUndefined,
VIR_DOMAIN_EVENT_UNDEFINED_LAST,
N_("Removed"),
N_("Renamed"))
-VIR_ENUM_DECL(vshDomainEventStarted)
-VIR_ENUM_IMPL(vshDomainEventStarted,
+VIR_ENUM_DECL(virshDomainEventStarted)
+VIR_ENUM_IMPL(virshDomainEventStarted,
VIR_DOMAIN_EVENT_STARTED_LAST,
N_("Booted"),
N_("Migrated"),
N_("Snapshot"),
N_("Event wakeup"))
-VIR_ENUM_DECL(vshDomainEventSuspended)
-VIR_ENUM_IMPL(vshDomainEventSuspended,
+VIR_ENUM_DECL(virshDomainEventSuspended)
+VIR_ENUM_IMPL(virshDomainEventSuspended,
VIR_DOMAIN_EVENT_SUSPENDED_LAST,
N_("Paused"),
N_("Migrated"),
N_("Snapshot"),
N_("API error"))
-VIR_ENUM_DECL(vshDomainEventResumed)
-VIR_ENUM_IMPL(vshDomainEventResumed,
+VIR_ENUM_DECL(virshDomainEventResumed)
+VIR_ENUM_IMPL(virshDomainEventResumed,
VIR_DOMAIN_EVENT_RESUMED_LAST,
N_("Unpaused"),
N_("Migrated"),
N_("Snapshot"))
-VIR_ENUM_DECL(vshDomainEventStopped)
-VIR_ENUM_IMPL(vshDomainEventStopped,
+VIR_ENUM_DECL(virshDomainEventStopped)
+VIR_ENUM_IMPL(virshDomainEventStopped,
VIR_DOMAIN_EVENT_STOPPED_LAST,
N_("Shutdown"),
N_("Destroyed"),
N_("Failed"),
N_("Snapshot"))
-VIR_ENUM_DECL(vshDomainEventShutdown)
-VIR_ENUM_IMPL(vshDomainEventShutdown,
+VIR_ENUM_DECL(virshDomainEventShutdown)
+VIR_ENUM_IMPL(virshDomainEventShutdown,
VIR_DOMAIN_EVENT_SHUTDOWN_LAST,
N_("Finished"))
-VIR_ENUM_DECL(vshDomainEventPMSuspended)
-VIR_ENUM_IMPL(vshDomainEventPMSuspended,
+VIR_ENUM_DECL(virshDomainEventPMSuspended)
+VIR_ENUM_IMPL(virshDomainEventPMSuspended,
VIR_DOMAIN_EVENT_PMSUSPENDED_LAST,
N_("Memory"),
N_("Disk"))
-VIR_ENUM_DECL(vshDomainEventCrashed)
-VIR_ENUM_IMPL(vshDomainEventCrashed,
+VIR_ENUM_DECL(virshDomainEventCrashed)
+VIR_ENUM_IMPL(virshDomainEventCrashed,
VIR_DOMAIN_EVENT_CRASHED_LAST,
N_("Panicked"))
static const char *
-vshDomainEventDetailToString(int event, int detail)
+virshDomainEventDetailToString(int event, int detail)
{
const char *str = NULL;
switch ((virDomainEventType) event) {
case VIR_DOMAIN_EVENT_DEFINED:
- str = vshDomainEventDefinedTypeToString(detail);
+ str = virshDomainEventDefinedTypeToString(detail);
break;
case VIR_DOMAIN_EVENT_UNDEFINED:
- str = vshDomainEventUndefinedTypeToString(detail);
+ str = virshDomainEventUndefinedTypeToString(detail);
break;
case VIR_DOMAIN_EVENT_STARTED:
- str = vshDomainEventStartedTypeToString(detail);
+ str = virshDomainEventStartedTypeToString(detail);
break;
case VIR_DOMAIN_EVENT_SUSPENDED:
- str = vshDomainEventSuspendedTypeToString(detail);
+ str = virshDomainEventSuspendedTypeToString(detail);
break;
case VIR_DOMAIN_EVENT_RESUMED:
- str = vshDomainEventResumedTypeToString(detail);
+ str = virshDomainEventResumedTypeToString(detail);
break;
case VIR_DOMAIN_EVENT_STOPPED:
- str = vshDomainEventStoppedTypeToString(detail);
+ str = virshDomainEventStoppedTypeToString(detail);
break;
case VIR_DOMAIN_EVENT_SHUTDOWN:
- str = vshDomainEventShutdownTypeToString(detail);
+ str = virshDomainEventShutdownTypeToString(detail);
break;
case VIR_DOMAIN_EVENT_PMSUSPENDED:
- str = vshDomainEventPMSuspendedTypeToString(detail);
+ str = virshDomainEventPMSuspendedTypeToString(detail);
break;
case VIR_DOMAIN_EVENT_CRASHED:
- str = vshDomainEventCrashedTypeToString(detail);
+ str = virshDomainEventCrashedTypeToString(detail);
break;
case VIR_DOMAIN_EVENT_LAST:
break;
return str ? _(str) : _("unknown");
}
-VIR_ENUM_DECL(vshDomainEventWatchdog)
-VIR_ENUM_IMPL(vshDomainEventWatchdog,
+VIR_ENUM_DECL(virshDomainEventWatchdog)
+VIR_ENUM_IMPL(virshDomainEventWatchdog,
VIR_DOMAIN_EVENT_WATCHDOG_LAST,
N_("none"),
N_("pause"),
N_("inject-nmi"))
static const char *
-vshDomainEventWatchdogToString(int action)
+virshDomainEventWatchdogToString(int action)
{
- const char *str = vshDomainEventWatchdogTypeToString(action);
+ const char *str = virshDomainEventWatchdogTypeToString(action);
return str ? _(str) : _("unknown");
}
-VIR_ENUM_DECL(vshDomainEventIOError)
-VIR_ENUM_IMPL(vshDomainEventIOError,
+VIR_ENUM_DECL(virshDomainEventIOError)
+VIR_ENUM_IMPL(virshDomainEventIOError,
VIR_DOMAIN_EVENT_IO_ERROR_LAST,
N_("none"),
N_("pause"),
N_("report"))
static const char *
-vshDomainEventIOErrorToString(int action)
+virshDomainEventIOErrorToString(int action)
{
- const char *str = vshDomainEventIOErrorTypeToString(action);
+ const char *str = virshDomainEventIOErrorTypeToString(action);
return str ? _(str) : _("unknown");
}
-VIR_ENUM_DECL(vshGraphicsPhase)
-VIR_ENUM_IMPL(vshGraphicsPhase,
+VIR_ENUM_DECL(virshGraphicsPhase)
+VIR_ENUM_IMPL(virshGraphicsPhase,
VIR_DOMAIN_EVENT_GRAPHICS_LAST,
N_("connect"),
N_("initialize"),
N_("disconnect"))
static const char *
-vshGraphicsPhaseToString(int phase)
+virshGraphicsPhaseToString(int phase)
{
- const char *str = vshGraphicsPhaseTypeToString(phase);
+ const char *str = virshGraphicsPhaseTypeToString(phase);
return str ? _(str) : _("unknown");
}
-VIR_ENUM_DECL(vshGraphicsAddress)
-VIR_ENUM_IMPL(vshGraphicsAddress,
+VIR_ENUM_DECL(virshGraphicsAddress)
+VIR_ENUM_IMPL(virshGraphicsAddress,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_LAST,
N_("IPv4"),
N_("IPv6"),
N_("unix"))
static const char *
-vshGraphicsAddressToString(int family)
+virshGraphicsAddressToString(int family)
{
- const char *str = vshGraphicsAddressTypeToString(family);
+ const char *str = virshGraphicsAddressTypeToString(family);
return str ? _(str) : _("unknown");
}
-VIR_ENUM_DECL(vshDomainBlockJobStatus)
-VIR_ENUM_IMPL(vshDomainBlockJobStatus,
+VIR_ENUM_DECL(virshDomainBlockJobStatus)
+VIR_ENUM_IMPL(virshDomainBlockJobStatus,
VIR_DOMAIN_BLOCK_JOB_LAST,
N_("completed"),
N_("failed"),
N_("ready"))
static const char *
-vshDomainBlockJobStatusToString(int status)
+virshDomainBlockJobStatusToString(int status)
{
- const char *str = vshDomainBlockJobStatusTypeToString(status);
+ const char *str = virshDomainBlockJobStatusTypeToString(status);
return str ? _(str) : _("unknown");
}
-VIR_ENUM_DECL(vshDomainEventDiskChange)
-VIR_ENUM_IMPL(vshDomainEventDiskChange,
+VIR_ENUM_DECL(virshDomainEventDiskChange)
+VIR_ENUM_IMPL(virshDomainEventDiskChange,
VIR_DOMAIN_EVENT_DISK_CHANGE_LAST,
N_("changed"),
N_("dropped"))
static const char *
-vshDomainEventDiskChangeToString(int reason)
+virshDomainEventDiskChangeToString(int reason)
{
- const char *str = vshDomainEventDiskChangeTypeToString(reason);
+ const char *str = virshDomainEventDiskChangeTypeToString(reason);
return str ? _(str) : _("unknown");
}
-VIR_ENUM_DECL(vshDomainEventTrayChange)
-VIR_ENUM_IMPL(vshDomainEventTrayChange,
+VIR_ENUM_DECL(virshDomainEventTrayChange)
+VIR_ENUM_IMPL(virshDomainEventTrayChange,
VIR_DOMAIN_EVENT_TRAY_CHANGE_LAST,
N_("opened"),
N_("closed"))
static const char *
-vshDomainEventTrayChangeToString(int reason)
+virshDomainEventTrayChangeToString(int reason)
{
- const char *str = vshDomainEventTrayChangeTypeToString(reason);
+ const char *str = virshDomainEventTrayChangeTypeToString(reason);
return str ? _(str) : _("unknown");
}
};
typedef struct vshEventCallback vshEventCallback;
-struct vshDomEventData {
+struct virshDomEventData {
vshControl *ctl;
bool loop;
int *count;
vshEventCallback *cb;
int id;
};
-typedef struct vshDomEventData vshDomEventData;
+typedef struct virshDomEventData virshDomEventData;
static void
-vshEventGenericPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- void *opaque)
+virshEventGenericPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
}
static void
-vshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- int event,
- int detail,
- void *opaque)
+virshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int event,
+ int detail,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
vshPrint(data->ctl, _("event 'lifecycle' for domain %s: %s %s\n"),
- virDomainGetName(dom), vshDomainEventToString(event),
- vshDomainEventDetailToString(event, detail));
+ virDomainGetName(dom), virshDomainEventToString(event),
+ virshDomainEventDetailToString(event, detail));
(*data->count)++;
if (!data->loop)
vshEventDone(data->ctl);
}
static void
-vshEventRTCChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- long long utcoffset,
- void *opaque)
+virshEventRTCChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ long long utcoffset,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
}
static void
-vshEventWatchdogPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- int action,
- void *opaque)
+virshEventWatchdogPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int action,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
vshPrint(data->ctl, _("event 'watchdog' for domain %s: %s\n"),
- virDomainGetName(dom), vshDomainEventWatchdogToString(action));
+ virDomainGetName(dom), virshDomainEventWatchdogToString(action));
(*data->count)++;
if (!data->loop)
vshEventDone(data->ctl);
}
static void
-vshEventIOErrorPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- const char *srcPath,
- const char *devAlias,
- int action,
- void *opaque)
+virshEventIOErrorPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
vshPrint(data->ctl, _("event 'io-error' for domain %s: %s (%s) %s\n"),
virDomainGetName(dom), srcPath, devAlias,
- vshDomainEventIOErrorToString(action));
+ virshDomainEventIOErrorToString(action));
(*data->count)++;
if (!data->loop)
vshEventDone(data->ctl);
}
static void
-vshEventGraphicsPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- int phase,
- const virDomainEventGraphicsAddress *local,
- const virDomainEventGraphicsAddress *remote,
- const char *authScheme,
- const virDomainEventGraphicsSubject *subject,
- void *opaque)
-{
- vshDomEventData *data = opaque;
+virshEventGraphicsPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int phase,
+ const virDomainEventGraphicsAddress *local,
+ const virDomainEventGraphicsAddress *remote,
+ const char *authScheme,
+ const virDomainEventGraphicsSubject *subject,
+ void *opaque)
+{
+ virshDomEventData *data = opaque;
size_t i;
if (!data->loop && *data->count)
return;
vshPrint(data->ctl, _("event 'graphics' for domain %s: "
"%s local[%s %s %s] remote[%s %s %s] %s"),
- virDomainGetName(dom), vshGraphicsPhaseToString(phase),
- vshGraphicsAddressToString(local->family),
+ virDomainGetName(dom), virshGraphicsPhaseToString(phase),
+ virshGraphicsAddressToString(local->family),
local->node, local->service,
- vshGraphicsAddressToString(remote->family),
+ virshGraphicsAddressToString(remote->family),
remote->node, remote->service,
authScheme);
for (i = 0; i < subject->nidentity; i++)
}
static void
-vshEventIOErrorReasonPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- const char *srcPath,
- const char *devAlias,
- int action,
- const char *reason,
- void *opaque)
+virshEventIOErrorReasonPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *srcPath,
+ const char *devAlias,
+ int action,
+ const char *reason,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
vshPrint(data->ctl, _("event 'io-error-reason' for domain %s: "
"%s (%s) %s due to %s\n"),
virDomainGetName(dom), srcPath, devAlias,
- vshDomainEventIOErrorToString(action), reason);
+ virshDomainEventIOErrorToString(action), reason);
(*data->count)++;
if (!data->loop)
vshEventDone(data->ctl);
}
static void
-vshEventBlockJobPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- const char *disk,
- int type,
- int status,
- void *opaque)
+virshEventBlockJobPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *disk,
+ int type,
+ int status,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
vshPrint(data->ctl, _("event '%s' for domain %s: %s for %s %s\n"),
data->cb->name, virDomainGetName(dom),
- vshDomainBlockJobToString(type),
- disk, vshDomainBlockJobStatusToString(status));
+ virshDomainBlockJobToString(type),
+ disk, virshDomainBlockJobStatusToString(status));
(*data->count)++;
if (!data->loop)
vshEventDone(data->ctl);
}
static void
-vshEventDiskChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- const char *oldSrc,
- const char *newSrc,
- const char *alias,
- int reason,
- void *opaque)
+virshEventDiskChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *oldSrc,
+ const char *newSrc,
+ const char *alias,
+ int reason,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
vshPrint(data->ctl,
_("event 'disk-change' for domain %s disk %s: %s -> %s: %s\n"),
virDomainGetName(dom), alias, NULLSTR(oldSrc), NULLSTR(newSrc),
- vshDomainEventDiskChangeToString(reason));
+ virshDomainEventDiskChangeToString(reason));
(*data->count)++;
if (!data->loop)
vshEventDone(data->ctl);
}
static void
-vshEventTrayChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- const char *alias,
- int reason,
- void *opaque)
+virshEventTrayChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *alias,
+ int reason,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
vshPrint(data->ctl,
_("event 'tray-change' for domain %s disk %s: %s\n"),
virDomainGetName(dom), alias,
- vshDomainEventTrayChangeToString(reason));
+ virshDomainEventTrayChangeToString(reason));
(*data->count)++;
if (!data->loop)
vshEventDone(data->ctl);
}
static void
-vshEventPMChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- int reason ATTRIBUTE_UNUSED,
- void *opaque)
+virshEventPMChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int reason ATTRIBUTE_UNUSED,
+ void *opaque)
{
/* As long as libvirt.h doesn't define any reasons, we might as
* well treat all PM state changes as generic events. */
- vshEventGenericPrint(conn, dom, opaque);
+ virshEventGenericPrint(conn, dom, opaque);
}
static void
-vshEventBalloonChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- unsigned long long actual,
- void *opaque)
+virshEventBalloonChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ unsigned long long actual,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
}
static void
-vshEventDeviceRemovedPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- const char *alias,
- void *opaque)
+virshEventDeviceRemovedPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *alias,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
}
static void
-vshEventDeviceAddedPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+virshEventDeviceAddedPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainPtr dom,
const char *alias,
void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
}
static void
-vshEventTunablePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- virTypedParameterPtr params,
- int nparams,
- void *opaque)
+virshEventTunablePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ virTypedParameterPtr params,
+ int nparams,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
size_t i;
char *value = NULL;
vshEventDone(data->ctl);
}
-VIR_ENUM_DECL(vshEventAgentLifecycleState)
-VIR_ENUM_IMPL(vshEventAgentLifecycleState,
+VIR_ENUM_DECL(virshEventAgentLifecycleState)
+VIR_ENUM_IMPL(virshEventAgentLifecycleState,
VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_LAST,
N_("unknown"),
N_("connected"),
N_("disconnected"))
-VIR_ENUM_DECL(vshEventAgentLifecycleReason)
-VIR_ENUM_IMPL(vshEventAgentLifecycleReason,
+VIR_ENUM_DECL(virshEventAgentLifecycleReason)
+VIR_ENUM_IMPL(virshEventAgentLifecycleReason,
VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_LAST,
N_("unknown"),
N_("domain started"),
#define UNKNOWNSTR(str) (str ? str : N_("unsupported value"))
static void
-vshEventAgentLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- int state,
- int reason,
- void *opaque)
+virshEventAgentLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int state,
+ int reason,
+ void *opaque)
{
- vshDomEventData *data = opaque;
+ virshDomEventData *data = opaque;
if (!data->loop && *data->count)
return;
vshPrint(data->ctl,
_("event 'agent-lifecycle' for domain %s: state: '%s' reason: '%s'\n"),
virDomainGetName(dom),
- UNKNOWNSTR(vshEventAgentLifecycleStateTypeToString(state)),
- UNKNOWNSTR(vshEventAgentLifecycleReasonTypeToString(reason)));
+ UNKNOWNSTR(virshEventAgentLifecycleStateTypeToString(state)),
+ UNKNOWNSTR(virshEventAgentLifecycleReasonTypeToString(reason)));
(*data->count)++;
if (!data->loop)
static vshEventCallback vshEventCallbacks[] = {
{ "lifecycle",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventLifecyclePrint), },
- { "reboot", vshEventGenericPrint, },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
+ { "reboot", virshEventGenericPrint, },
{ "rtc-change",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventRTCChangePrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventRTCChangePrint), },
{ "watchdog",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventWatchdogPrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventWatchdogPrint), },
{ "io-error",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventIOErrorPrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventIOErrorPrint), },
{ "graphics",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventGraphicsPrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventGraphicsPrint), },
{ "io-error-reason",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventIOErrorReasonPrint), },
- { "control-error", vshEventGenericPrint, },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventIOErrorReasonPrint), },
+ { "control-error", virshEventGenericPrint, },
{ "block-job",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventBlockJobPrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockJobPrint), },
{ "disk-change",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventDiskChangePrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventDiskChangePrint), },
{ "tray-change",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventTrayChangePrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventTrayChangePrint), },
{ "pm-wakeup",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventPMChangePrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventPMChangePrint), },
{ "pm-suspend",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventPMChangePrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventPMChangePrint), },
{ "balloon-change",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventBalloonChangePrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventBalloonChangePrint), },
{ "pm-suspend-disk",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventPMChangePrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventPMChangePrint), },
{ "device-removed",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventDeviceRemovedPrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventDeviceRemovedPrint), },
{ "block-job-2",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventBlockJobPrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockJobPrint), },
{ "tunable",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventTunablePrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventTunablePrint), },
{ "agent-lifecycle",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventAgentLifecyclePrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventAgentLifecyclePrint), },
{ "device-added",
- VIR_DOMAIN_EVENT_CALLBACK(vshEventDeviceAddedPrint), },
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventDeviceAddedPrint), },
};
verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));
virDomainPtr dom = NULL;
bool ret = false;
int timeout = 0;
- vshDomEventData *data = NULL;
+ virshDomEventData *data = NULL;
size_t i;
const char *eventName = NULL;
int event = -1;
bool all = vshCommandOptBool(cmd, "all");
bool loop = vshCommandOptBool(cmd, "loop");
int count = 0;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "list")) {
for (event = 0; event < VIR_DOMAIN_EVENT_ID_LAST; event++)
goto cleanup;
if (vshCommandOptBool(cmd, "domain"))
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (vshEventStart(ctl, timeout) < 0)
goto cleanup;
for (i = 0; i < (all ? VIR_DOMAIN_EVENT_ID_LAST : 1); i++) {
- if ((data[i].id = virConnectDomainEventRegisterAny(ctl->conn, dom,
+ if ((data[i].id = virConnectDomainEventRegisterAny(priv->conn, dom,
all ? i : event,
data[i].cb->cb,
&data[i],
if (data) {
for (i = 0; i < (all ? VIR_DOMAIN_EVENT_ID_LAST : 1); i++) {
if (data[i].id >= 0 &&
- virConnectDomainEventDeregisterAny(ctl->conn, data[i].id) < 0)
+ virConnectDomainEventDeregisterAny(priv->conn, data[i].id) < 0)
ret = false;
}
VIR_FREE(data);
xmlNodePtr disk_node = NULL;
char *disk_xml = NULL;
bool ret = false;
- vshUpdateDiskXMLType update_type;
+ virshUpdateDiskXMLType update_type;
const char *action = NULL;
const char *success_msg = NULL;
bool config = vshCommandOptBool(cmd, "config");
}
if (eject) {
- update_type = VSH_UPDATE_DISK_XML_EJECT;
+ update_type = VIRSH_UPDATE_DISK_XML_EJECT;
action = "eject";
success_msg = _("Successfully ejected media.");
}
if (insert) {
- update_type = VSH_UPDATE_DISK_XML_INSERT;
+ update_type = VIRSH_UPDATE_DISK_XML_INSERT;
action = "insert";
success_msg = _("Successfully inserted media.");
}
if (update || (!eject && !insert)) {
- update_type = VSH_UPDATE_DISK_XML_UPDATE;
+ update_type = VIRSH_UPDATE_DISK_XML_UPDATE;
action = "update";
success_msg = _("Successfully updated media.");
}
if (force)
flags |= VIR_DOMAIN_DEVICE_MODIFY_FORCE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0)
if (!doc)
goto cleanup;
- if (!(disk_node = vshFindDisk(doc, path, VSH_FIND_DISK_CHANGEABLE)))
+ if (!(disk_node = virshFindDisk(doc, path, VIRSH_FIND_DISK_CHANGEABLE)))
goto cleanup;
- if (!(disk_xml = vshUpdateDiskXML(disk_node, source, block, path,
- update_type)))
+ if (!(disk_xml = virshUpdateDiskXML(disk_node, source, block, path,
+ update_type)))
goto cleanup;
if (vshCommandOptBool(cmd, "print-xml")) {
const char *mountPoint = NULL;
unsigned int flags = 0;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return ret;
if (vshCommandOptULongLong(ctl, cmd, "minimum", &minimum) < 0)
const char **mountpoints = NULL;
size_t nmountpoints = 0;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
const char **mountpoints = NULL;
size_t nmountpoints = 0;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
size_t i, j;
virDomainFSInfoPtr *info;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
ret = virDomainGetFSInfo(dom, &info, 0);
# include "virsh.h"
-virDomainPtr vshLookupDomainBy(vshControl *ctl,
- const char *name,
- unsigned int flags);
+virDomainPtr virshLookupDomainBy(vshControl *ctl,
+ const char *name,
+ unsigned int flags);
-virDomainPtr vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd,
- const char **name, unsigned int flags);
+virDomainPtr virshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd,
+ const char **name, unsigned int flags);
/* default is lookup by Id, Name and UUID */
-# define vshCommandOptDomain(_ctl, _cmd, _name) \
- vshCommandOptDomainBy(_ctl, _cmd, _name, VSH_BYID|VSH_BYUUID|VSH_BYNAME)
+# define virshCommandOptDomain(_ctl, _cmd, _name) \
+ virshCommandOptDomainBy(_ctl, _cmd, _name, \
+ VIRSH_BYID | VIRSH_BYUUID | VIRSH_BYNAME)
extern const vshCmdDef domManagementCmds[];
cmdCapabilities(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *caps;
+ virshControlPtr priv = ctl->privData;
- if ((caps = virConnectGetCapabilities(ctl->conn)) == NULL) {
+ if ((caps = virConnectGetCapabilities(priv->conn)) == NULL) {
vshError(ctl, "%s", _("failed to get capabilities"));
return false;
}
const char *arch = NULL;
const char *machine = NULL;
const unsigned int flags = 0; /* No flags so far */
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "virttype", &virttype) < 0 ||
vshCommandOptStringReq(ctl, cmd, "emulatorbin", &emulatorbin) < 0 ||
vshCommandOptStringReq(ctl, cmd, "machine", &machine) < 0)
return ret;
- caps = virConnectGetDomainCapabilities(ctl->conn, emulatorbin,
+ caps = virConnectGetDomainCapabilities(priv->conn, emulatorbin,
arch, machine, virttype, flags);
if (!caps) {
vshError(ctl, "%s", _("failed to get emulator capabilities"));
char *cap_xml = NULL;
xmlDocPtr xml = NULL;
xmlXPathContextPtr ctxt = NULL;
+ virshControlPtr priv = ctl->privData;
VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno);
return false;
if (all) {
- if (!(cap_xml = virConnectGetCapabilities(ctl->conn))) {
+ if (!(cap_xml = virConnectGetCapabilities(priv->conn))) {
vshError(ctl, "%s", _("unable to get node capabilities"));
goto cleanup;
}
}
VIR_FREE(val);
nodes_id[i] = id;
- if (virNodeGetCellsFreeMemory(ctl->conn, &(nodes_free[i]),
+ if (virNodeGetCellsFreeMemory(priv->conn, &(nodes_free[i]),
id, 1) != 1) {
vshError(ctl, _("failed to get free memory for NUMA node "
"number: %lu"), id);
vshPrintExtra(ctl, "%5s: %10llu KiB\n", _("Total"), memory/1024);
} else {
if (cellno) {
- if (virNodeGetCellsFreeMemory(ctl->conn, &memory, cell, 1) != 1)
+ if (virNodeGetCellsFreeMemory(priv->conn, &memory, cell, 1) != 1)
goto cleanup;
vshPrint(ctl, "%d: %llu KiB\n", cell, (memory/1024));
} else {
- if ((memory = virNodeGetFreeMemory(ctl->conn)) == 0)
+ if ((memory = virNodeGetFreeMemory(priv->conn)) == 0)
goto cleanup;
vshPrint(ctl, "%s: %llu KiB\n", _("Total"), (memory/1024));
bool all = vshCommandOptBool(cmd, "all");
bool cellno = vshCommandOptBool(cmd, "cellno");
bool pagesz = vshCommandOptBool(cmd, "pagesize");
+ virshControlPtr priv = ctl->privData;
VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno);
kibibytes = VIR_DIV_UP(bytes, 1024);
if (all) {
- if (!(cap_xml = virConnectGetCapabilities(ctl->conn))) {
+ if (!(cap_xml = virConnectGetCapabilities(priv->conn))) {
vshError(ctl, "%s", _("unable to get node capabilities"));
goto cleanup;
}
}
VIR_FREE(val);
- if (virNodeGetFreePages(ctl->conn, npages, pagesize,
+ if (virNodeGetFreePages(priv->conn, npages, pagesize,
cell, 1, counts, 0) < 0)
goto cleanup;
counts = vshMalloc(ctl, sizeof(*counts));
- if (virNodeGetFreePages(ctl->conn, 1, pagesize, cell, 1, counts, 0) < 0)
+ if (virNodeGetFreePages(priv->conn, 1, pagesize,
+ cell, 1, counts, 0) < 0)
goto cleanup;
vshPrint(ctl, "%uKiB: %lld\n", *pagesize, counts[0]);
xmlDocPtr xml = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlNodePtr *nodes = NULL;
+ virshControlPtr priv = ctl->privData;
VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno);
unsigned long nodes_cnt;
size_t i;
- if (!(cap_xml = virConnectGetCapabilities(ctl->conn))) {
+ if (!(cap_xml = virConnectGetCapabilities(priv->conn))) {
vshError(ctl, "%s", _("unable to get node capabilities"));
goto cleanup;
}
}
VIR_FREE(val);
- if (virNodeAllocPages(ctl->conn, 1, pageSizes,
+ if (virNodeAllocPages(priv->conn, 1, pageSizes,
pageCounts, id, 1, flags) < 0)
goto cleanup;
}
} else {
- if (virNodeAllocPages(ctl->conn, 1, pageSizes, pageCounts,
+ if (virNodeAllocPages(priv->conn, 1, pageSizes, pageCounts,
startCell, cellCount, flags) < 0)
goto cleanup;
}
{
const char *type = NULL;
int vcpus;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "type", &type) < 0)
return false;
- if ((vcpus = virConnectGetMaxVcpus(ctl->conn, type)) < 0)
+ if ((vcpus = virConnectGetMaxVcpus(priv->conn, type)) < 0)
return false;
vshPrint(ctl, "%d\n", vcpus);
cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
virNodeInfo info;
+ virshControlPtr priv = ctl->privData;
- if (virNodeGetInfo(ctl->conn, &info) < 0) {
+ if (virNodeGetInfo(priv->conn, &info) < 0) {
vshError(ctl, "%s", _("failed to get node information"));
return false;
}
unsigned int online;
bool pretty = vshCommandOptBool(cmd, "pretty");
bool ret = false;
+ virshControlPtr priv = ctl->privData;
- cpunum = virNodeGetCPUMap(ctl->conn, &cpumap, &online, 0);
+ cpunum = virNodeGetCPUMap(priv->conn, &cpumap, &online, 0);
if (cpunum < 0) {
vshError(ctl, "%s", _("Unable to get cpu map"));
goto cleanup;
};
typedef enum {
- VSH_CPU_USER,
- VSH_CPU_SYSTEM,
- VSH_CPU_IDLE,
- VSH_CPU_IOWAIT,
- VSH_CPU_INTR,
- VSH_CPU_USAGE,
- VSH_CPU_LAST
-} vshCPUStats;
-
-VIR_ENUM_DECL(vshCPUStats);
-VIR_ENUM_IMPL(vshCPUStats, VSH_CPU_LAST,
+ VIRSH_CPU_USER,
+ VIRSH_CPU_SYSTEM,
+ VIRSH_CPU_IDLE,
+ VIRSH_CPU_IOWAIT,
+ VIRSH_CPU_INTR,
+ VIRSH_CPU_USAGE,
+ VIRSH_CPU_LAST
+} virshCPUStats;
+
+VIR_ENUM_DECL(virshCPUStats);
+VIR_ENUM_IMPL(virshCPUStats, VIRSH_CPU_LAST,
VIR_NODE_CPU_STATS_USER,
VIR_NODE_CPU_STATS_KERNEL,
VIR_NODE_CPU_STATS_IDLE,
VIR_NODE_CPU_STATS_INTR,
VIR_NODE_CPU_STATS_UTILIZATION);
-const char *vshCPUOutput[] = {
+const char *virshCPUOutput[] = {
N_("user:"),
N_("system:"),
N_("idle:"),
virNodeCPUStatsPtr params;
int nparams = 0;
bool ret = false;
- unsigned long long cpu_stats[VSH_CPU_LAST] = { 0 };
- bool present[VSH_CPU_LAST] = { false };
+ unsigned long long cpu_stats[VIRSH_CPU_LAST] = { 0 };
+ bool present[VIRSH_CPU_LAST] = { false };
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptInt(ctl, cmd, "cpu", &cpuNum) < 0)
return false;
- if (virNodeGetCPUStats(ctl->conn, cpuNum, NULL, &nparams, 0) != 0) {
+ if (virNodeGetCPUStats(priv->conn, cpuNum, NULL, &nparams, 0) != 0) {
vshError(ctl, "%s",
_("Unable to get number of cpu stats"));
return false;
params = vshCalloc(ctl, nparams, sizeof(*params));
for (i = 0; i < 2; i++) {
- if (virNodeGetCPUStats(ctl->conn, cpuNum, params, &nparams, 0) != 0) {
+ if (virNodeGetCPUStats(priv->conn, cpuNum, params, &nparams, 0) != 0) {
vshError(ctl, "%s", _("Unable to get node cpu stats"));
goto cleanup;
}
for (j = 0; j < nparams; j++) {
- int field = vshCPUStatsTypeFromString(params[j].field);
+ int field = virshCPUStatsTypeFromString(params[j].field);
if (field < 0)
continue;
}
}
- if (present[VSH_CPU_USAGE] || !flag_percent)
+ if (present[VIRSH_CPU_USAGE] || !flag_percent)
break;
sleep(1);
}
if (!flag_percent) {
- for (i = 0; i < VSH_CPU_USAGE; i++) {
+ for (i = 0; i < VIRSH_CPU_USAGE; i++) {
if (present[i]) {
- vshPrint(ctl, "%-15s %20llu\n", _(vshCPUOutput[i]),
+ vshPrint(ctl, "%-15s %20llu\n", _(virshCPUOutput[i]),
cpu_stats[i]);
}
}
} else {
- if (present[VSH_CPU_USAGE]) {
- vshPrint(ctl, "%-15s %5.1llu%%\n", _("usage:"), cpu_stats[VSH_CPU_USAGE]);
- vshPrint(ctl, "%-15s %5.1llu%%\n", _("idle:"), 100 - cpu_stats[VSH_CPU_USAGE]);
+ if (present[VIRSH_CPU_USAGE]) {
+ vshPrint(ctl, "%-15s %5.1llu%%\n",
+ _("usage:"), cpu_stats[VIRSH_CPU_USAGE]);
+ vshPrint(ctl, "%-15s %5.1llu%%\n",
+ _("idle:"), 100 - cpu_stats[VIRSH_CPU_USAGE]);
} else {
double usage, total_time = 0;
- for (i = 0; i < VSH_CPU_USAGE; i++)
+ for (i = 0; i < VIRSH_CPU_USAGE; i++)
total_time += cpu_stats[i];
- usage = (cpu_stats[VSH_CPU_USER] + cpu_stats[VSH_CPU_SYSTEM]) / total_time * 100;
+ usage = (cpu_stats[VIRSH_CPU_USER] + cpu_stats[VIRSH_CPU_SYSTEM])
+ / total_time * 100;
vshPrint(ctl, "%-15s %5.1lf%%\n", _("usage:"), usage);
- for (i = 0; i < VSH_CPU_USAGE; i++) {
+ for (i = 0; i < VIRSH_CPU_USAGE; i++) {
if (present[i]) {
- vshPrint(ctl, "%-15s %5.1lf%%\n", _(vshCPUOutput[i]),
+ vshPrint(ctl, "%-15s %5.1lf%%\n", _(virshCPUOutput[i]),
cpu_stats[i] / total_time * 100);
}
}
int cellNum = VIR_NODE_MEMORY_STATS_ALL_CELLS;
virNodeMemoryStatsPtr params = NULL;
bool ret = false;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptInt(ctl, cmd, "cell", &cellNum) < 0)
return false;
/* get the number of memory parameters */
- if (virNodeGetMemoryStats(ctl->conn, cellNum, NULL, &nparams, 0) != 0) {
+ if (virNodeGetMemoryStats(priv->conn, cellNum, NULL, &nparams, 0) != 0) {
vshError(ctl, "%s",
_("Unable to get number of memory stats"));
goto cleanup;
/* now go get all the memory parameters */
params = vshCalloc(ctl, nparams, sizeof(*params));
- if (virNodeGetMemoryStats(ctl->conn, cellNum, params, &nparams, 0) != 0) {
+ if (virNodeGetMemoryStats(priv->conn, cellNum, params, &nparams, 0) != 0) {
vshError(ctl, "%s", _("Unable to get memory stats"));
goto cleanup;
}
const char *target = NULL;
unsigned int suspendTarget;
long long duration;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "target", &target) < 0)
return false;
return false;
}
- if (virNodeSuspendForDuration(ctl->conn, suspendTarget, duration, 0) < 0) {
+ if (virNodeSuspendForDuration(priv->conn, suspendTarget, duration, 0) < 0) {
vshError(ctl, "%s", _("The host was not suspended"));
return false;
}
cmdSysinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *sysinfo;
+ virshControlPtr priv = ctl->privData;
- sysinfo = virConnectGetSysinfo(ctl->conn, 0);
+ sysinfo = virConnectGetSysinfo(priv->conn, 0);
if (sysinfo == NULL) {
vshError(ctl, "%s", _("failed to get sysinfo"));
return false;
cmdHostname(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *hostname;
+ virshControlPtr priv = ctl->privData;
- hostname = virConnectGetHostname(ctl->conn);
+ hostname = virConnectGetHostname(priv->conn);
if (hostname == NULL) {
vshError(ctl, "%s", _("failed to get hostname"));
return false;
cmdURI(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *uri;
+ virshControlPtr priv = ctl->privData;
- uri = virConnectGetURI(ctl->conn);
+ uri = virConnectGetURI(priv->conn);
if (uri == NULL) {
vshError(ctl, "%s", _("failed to get URI"));
return false;
size_t i;
int nmodels;
const char *arch = NULL;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "arch", &arch) < 0)
return false;
- nmodels = virConnectGetCPUModelNames(ctl->conn, arch, &models, 0);
+ nmodels = virConnectGetCPUModelNames(priv->conn, arch, &models, 0);
if (nmodels < 0) {
vshError(ctl, "%s", _("failed to get CPU model names"));
return false;
unsigned int major;
unsigned int minor;
unsigned int rel;
+ virshControlPtr priv = ctl->privData;
- hvType = virConnectGetType(ctl->conn);
+ hvType = virConnectGetType(priv->conn);
if (hvType == NULL) {
vshError(ctl, "%s", _("failed to get hypervisor type"));
return false;
vshPrint(ctl, _("Using API: %s %d.%d.%d\n"), hvType,
major, minor, rel);
- ret = virConnectGetVersion(ctl->conn, &hvVersion);
+ ret = virConnectGetVersion(priv->conn, &hvVersion);
if (ret < 0) {
vshError(ctl, "%s", _("failed to get the hypervisor version"));
return false;
}
if (vshCommandOptBool(cmd, "daemon")) {
- ret = virConnectGetLibVersion(ctl->conn, &daemonVersion);
+ ret = virConnectGetLibVersion(priv->conn, &daemonVersion);
if (ret < 0) {
vshError(ctl, "%s", _("failed to get the daemon version"));
} else {
bool ret = false;
int rc = -1;
size_t i;
+ virshControlPtr priv = ctl->privData;
if ((rc = vshCommandOptUInt(ctl, cmd, "shm-pages-to-scan", &value)) < 0) {
goto cleanup;
if (nparams == 0) {
/* Get the number of memory parameters */
- if (virNodeGetMemoryParameters(ctl->conn, NULL, &nparams, flags) != 0) {
+ if (virNodeGetMemoryParameters(priv->conn, NULL, &nparams, flags) != 0) {
vshError(ctl, "%s",
_("Unable to get number of memory parameters"));
goto cleanup;
/* Now go get all the memory parameters */
params = vshCalloc(ctl, nparams, sizeof(*params));
- if (virNodeGetMemoryParameters(ctl->conn, params, &nparams, flags) != 0) {
+ if (virNodeGetMemoryParameters(priv->conn, params, &nparams, flags) != 0) {
vshError(ctl, "%s", _("Unable to get memory parameters"));
goto cleanup;
}
VIR_FREE(str);
}
} else {
- if (virNodeSetMemoryParameters(ctl->conn, params, nparams, flags) != 0)
+ if (virNodeSetMemoryParameters(priv->conn, params, nparams, flags) != 0)
goto error;
}
#include "virstring.h"
virInterfacePtr
-vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
- const char *optname,
- const char **name, unsigned int flags)
+virshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
+ const char *optname,
+ const char **name, unsigned int flags)
{
virInterfacePtr iface = NULL;
const char *n = NULL;
bool is_mac = false;
virMacAddr dummy;
- virCheckFlags(VSH_BYNAME | VSH_BYMAC, NULL);
+ virCheckFlags(VIRSH_BYNAME | VIRSH_BYMAC, NULL);
+ virshControlPtr priv = ctl->privData;
if (!optname)
optname = "interface";
is_mac = true;
/* try it by NAME */
- if (!is_mac && (flags & VSH_BYNAME)) {
+ if (!is_mac && (flags & VIRSH_BYNAME)) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as interface NAME\n",
cmd->def->name, optname);
- iface = virInterfaceLookupByName(ctl->conn, n);
+ iface = virInterfaceLookupByName(priv->conn, n);
/* try it by MAC */
- } else if (is_mac && (flags & VSH_BYMAC)) {
+ } else if (is_mac && (flags & VIRSH_BYMAC)) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as interface MAC\n",
cmd->def->name, optname);
- iface = virInterfaceLookupByMACString(ctl->conn, n);
+ iface = virInterfaceLookupByMACString(priv->conn, n);
}
if (!iface)
virInterfacePtr iface = NULL;
virInterfacePtr iface_edited = NULL;
unsigned int flags = VIR_INTERFACE_XML_INACTIVE;
+ virshControlPtr priv = ctl->privData;
- iface = vshCommandOptInterface(ctl, cmd, NULL);
+ iface = virshCommandOptInterface(ctl, cmd, NULL);
if (iface == NULL)
goto cleanup;
goto edit_cleanup; \
} while (0)
#define EDIT_DEFINE \
- (iface_edited = virInterfaceDefineXML(ctl->conn, doc_edited, 0))
+ (iface_edited = virInterfaceDefineXML(priv->conn, doc_edited, 0))
#include "virsh-edit.c"
vshPrint(ctl, _("Interface %s XML configuration edited.\n"),
}
static int
-vshInterfaceSorter(const void *a, const void *b)
+virshInterfaceSorter(const void *a, const void *b)
{
virInterfacePtr *ia = (virInterfacePtr *) a;
virInterfacePtr *ib = (virInterfacePtr *) b;
virInterfaceGetName(*ib));
}
-struct vshInterfaceList {
+struct virshInterfaceList {
virInterfacePtr *ifaces;
size_t nifaces;
};
-typedef struct vshInterfaceList *vshInterfaceListPtr;
+typedef struct virshInterfaceList *virshInterfaceListPtr;
static void
-vshInterfaceListFree(vshInterfaceListPtr list)
+virshInterfaceListFree(virshInterfaceListPtr list)
{
size_t i;
VIR_FREE(list);
}
-static vshInterfaceListPtr
-vshInterfaceListCollect(vshControl *ctl,
- unsigned int flags)
+static virshInterfaceListPtr
+virshInterfaceListCollect(vshControl *ctl,
+ unsigned int flags)
{
- vshInterfaceListPtr list = vshMalloc(ctl, sizeof(*list));
+ virshInterfaceListPtr list = vshMalloc(ctl, sizeof(*list));
size_t i;
int ret;
char **activeNames = NULL;
int nActiveIfaces = 0;
int nInactiveIfaces = 0;
int nAllIfaces = 0;
+ virshControlPtr priv = ctl->privData;
/* try the list with flags support (0.10.2 and later) */
- if ((ret = virConnectListAllInterfaces(ctl->conn,
+ if ((ret = virConnectListAllInterfaces(priv->conn,
&list->ifaces,
flags)) >= 0) {
list->nifaces = ret;
vshResetLibvirtError();
if (flags & VIR_CONNECT_LIST_INTERFACES_ACTIVE) {
- nActiveIfaces = virConnectNumOfInterfaces(ctl->conn);
+ nActiveIfaces = virConnectNumOfInterfaces(priv->conn);
if (nActiveIfaces < 0) {
vshError(ctl, "%s", _("Failed to list active interfaces"));
goto cleanup;
if (nActiveIfaces) {
activeNames = vshMalloc(ctl, sizeof(char *) * nActiveIfaces);
- if ((nActiveIfaces = virConnectListInterfaces(ctl->conn, activeNames,
+ if ((nActiveIfaces = virConnectListInterfaces(priv->conn, activeNames,
nActiveIfaces)) < 0) {
vshError(ctl, "%s", _("Failed to list active interfaces"));
goto cleanup;
}
if (flags & VIR_CONNECT_LIST_INTERFACES_INACTIVE) {
- nInactiveIfaces = virConnectNumOfDefinedInterfaces(ctl->conn);
+ nInactiveIfaces = virConnectNumOfDefinedInterfaces(priv->conn);
if (nInactiveIfaces < 0) {
vshError(ctl, "%s", _("Failed to list inactive interfaces"));
goto cleanup;
inactiveNames = vshMalloc(ctl, sizeof(char *) * nInactiveIfaces);
if ((nInactiveIfaces =
- virConnectListDefinedInterfaces(ctl->conn, inactiveNames,
+ virConnectListDefinedInterfaces(priv->conn, inactiveNames,
nInactiveIfaces)) < 0) {
vshError(ctl, "%s", _("Failed to list inactive interfaces"));
goto cleanup;
/* get active interfaces */
for (i = 0; i < nActiveIfaces; i++) {
- if (!(iface = virInterfaceLookupByName(ctl->conn, activeNames[i]))) {
+ if (!(iface = virInterfaceLookupByName(priv->conn, activeNames[i]))) {
vshResetLibvirtError();
continue;
}
/* get inactive interfaces */
for (i = 0; i < nInactiveIfaces; i++) {
- if (!(iface = virInterfaceLookupByName(ctl->conn, inactiveNames[i]))) {
+ if (!(iface = virInterfaceLookupByName(priv->conn, inactiveNames[i]))) {
vshResetLibvirtError();
continue;
}
/* sort the list */
if (list->ifaces && list->nifaces)
qsort(list->ifaces, list->nifaces,
- sizeof(*list->ifaces), vshInterfaceSorter);
+ sizeof(*list->ifaces), virshInterfaceSorter);
/* truncate the list if filter simulation deleted entries */
if (deleted)
VIR_FREE(inactiveNames);
if (!success) {
- vshInterfaceListFree(list);
+ virshInterfaceListFree(list);
list = NULL;
}
bool inactive = vshCommandOptBool(cmd, "inactive");
bool all = vshCommandOptBool(cmd, "all");
unsigned int flags = VIR_CONNECT_LIST_INTERFACES_ACTIVE;
- vshInterfaceListPtr list = NULL;
+ virshInterfaceListPtr list = NULL;
size_t i;
if (inactive)
flags = VIR_CONNECT_LIST_INTERFACES_INACTIVE |
VIR_CONNECT_LIST_INTERFACES_ACTIVE;
- if (!(list = vshInterfaceListCollect(ctl, flags)))
+ if (!(list = virshInterfaceListCollect(ctl, flags)))
return false;
vshPrintExtra(ctl, " %-20s %-10s %s\n", _("Name"), _("State"),
virInterfaceGetMACString(iface));
}
- vshInterfaceListFree(list);
+ virshInterfaceListFree(list);
return true;
}
{
virInterfacePtr iface;
- if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
- VSH_BYMAC)))
+ if (!(iface = virshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
+ VIRSH_BYMAC)))
return false;
vshPrint(ctl, "%s\n", virInterfaceGetName(iface));
{
virInterfacePtr iface;
- if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
- VSH_BYNAME)))
+ if (!(iface = virshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
+ VIRSH_BYNAME)))
return false;
vshPrint(ctl, "%s\n", virInterfaceGetMACString(iface));
if (inactive)
flags |= VIR_INTERFACE_XML_INACTIVE;
- if (!(iface = vshCommandOptInterface(ctl, cmd, NULL)))
+ if (!(iface = virshCommandOptInterface(ctl, cmd, NULL)))
return false;
dump = virInterfaceGetXMLDesc(iface, flags);
const char *from = NULL;
bool ret = true;
char *buffer;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
return false;
- iface = virInterfaceDefineXML(ctl->conn, buffer, 0);
+ iface = virInterfaceDefineXML(priv->conn, buffer, 0);
VIR_FREE(buffer);
if (iface != NULL) {
bool ret = true;
const char *name;
- if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
+ if (!(iface = virshCommandOptInterface(ctl, cmd, &name)))
return false;
if (virInterfaceUndefine(iface) == 0) {
bool ret = true;
const char *name;
- if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
+ if (!(iface = virshCommandOptInterface(ctl, cmd, &name)))
return false;
if (virInterfaceCreate(iface, 0) == 0) {
bool ret = true;
const char *name;
- if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
+ if (!(iface = virshCommandOptInterface(ctl, cmd, &name)))
return false;
if (virInterfaceDestroy(iface, 0) == 0) {
static bool
cmdInterfaceBegin(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
- if (virInterfaceChangeBegin(ctl->conn, 0) < 0) {
+ virshControlPtr priv = ctl->privData;
+
+ if (virInterfaceChangeBegin(priv->conn, 0) < 0) {
vshError(ctl, "%s", _("Failed to begin network config change transaction"));
return false;
}
static bool
cmdInterfaceCommit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
- if (virInterfaceChangeCommit(ctl->conn, 0) < 0) {
+ virshControlPtr priv = ctl->privData;
+
+ if (virInterfaceChangeCommit(priv->conn, 0) < 0) {
vshError(ctl, "%s", _("Failed to commit network config change transaction"));
return false;
}
static bool
cmdInterfaceRollback(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
- if (virInterfaceChangeRollback(ctl->conn, 0) < 0) {
+ virshControlPtr priv = ctl->privData;
+
+ if (virInterfaceChangeRollback(priv->conn, 0) < 0) {
vshError(ctl, "%s", _("Failed to rollback network config change transaction"));
return false;
}
xmlDocPtr xml_doc = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlNodePtr top_node, br_node, if_node, cur;
+ virshControlPtr priv = ctl->privData;
/* Get a handle to the original device */
- if (!(if_handle = vshCommandOptInterfaceBy(ctl, cmd, "interface",
- &if_name, VSH_BYNAME))) {
+ if (!(if_handle = virshCommandOptInterfaceBy(ctl, cmd, "interface",
+ &if_name, VIRSH_BYNAME))) {
goto cleanup;
}
goto cleanup;
/* make sure "new" device doesn't already exist */
- if ((br_handle = virInterfaceLookupByName(ctl->conn, br_name))) {
+ if ((br_handle = virInterfaceLookupByName(priv->conn, br_name))) {
vshError(ctl, _("Network device %s already exists"), br_name);
goto cleanup;
}
/* br_xml is the new interface to define. It will automatically undefine the
* independent original interface.
*/
- if (!(br_handle = virInterfaceDefineXML(ctl->conn, (char *) br_xml, 0))) {
+ if (!(br_handle = virInterfaceDefineXML(priv->conn, (char *) br_xml, 0))) {
vshError(ctl, _("Failed to define new bridge interface %s"),
br_name);
goto cleanup;
xmlDocPtr xml_doc = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlNodePtr top_node, if_node, cur;
+ virshControlPtr priv = ctl->privData;
/* Get a handle to the original device */
- if (!(br_handle = vshCommandOptInterfaceBy(ctl, cmd, "bridge",
- &br_name, VSH_BYNAME))) {
+ if (!(br_handle = virshCommandOptInterfaceBy(ctl, cmd, "bridge",
+ &br_name, VIRSH_BYNAME))) {
goto cleanup;
}
/* if_xml is the new interface to define.
*/
- if (!(if_handle = virInterfaceDefineXML(ctl->conn, (char *) if_xml, 0))) {
+ if (!(if_handle = virInterfaceDefineXML(priv->conn, (char *) if_xml, 0))) {
vshError(ctl, _("Failed to define new interface %s"), if_name);
goto cleanup;
}
# include "virsh.h"
-virInterfacePtr vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
- const char *optname,
- const char **name, unsigned int flags);
+virInterfacePtr virshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
+ const char *optname,
+ const char **name, unsigned int flags);
/* default is lookup by Name and MAC */
-# define vshCommandOptInterface(_ctl, _cmd, _name) \
- vshCommandOptInterfaceBy(_ctl, _cmd, NULL, _name, \
- VSH_BYMAC|VSH_BYNAME)
+# define virshCommandOptInterface(_ctl, _cmd, _name) \
+ virshCommandOptInterfaceBy(_ctl, _cmd, NULL, _name, \
+ VIRSH_BYMAC | VIRSH_BYNAME)
extern const vshCmdDef ifaceCmds[];
#include "conf/network_conf.h"
virNetworkPtr
-vshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
- const char **name, unsigned int flags)
+virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
+ const char **name, unsigned int flags)
{
virNetworkPtr network = NULL;
const char *n = NULL;
const char *optname = "network";
- virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL);
+ virCheckFlags(VIRSH_BYUUID | VIRSH_BYNAME, NULL);
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
return NULL;
*name = n;
/* try it by UUID */
- if ((flags & VSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) {
+ if ((flags & VIRSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network UUID\n",
cmd->def->name, optname);
- network = virNetworkLookupByUUIDString(ctl->conn, n);
+ network = virNetworkLookupByUUIDString(priv->conn, n);
}
/* try it by NAME */
- if (!network && (flags & VSH_BYNAME)) {
+ if (!network && (flags & VIRSH_BYNAME)) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network NAME\n",
cmd->def->name, optname);
- network = virNetworkLookupByName(ctl->conn, n);
+ network = virNetworkLookupByName(priv->conn, n);
}
if (!network)
const char *name;
int autostart;
- if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
+ if (!(network = virshCommandOptNetwork(ctl, cmd, &name)))
return false;
autostart = !vshCommandOptBool(cmd, "disable");
const char *from = NULL;
bool ret = true;
char *buffer;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
return false;
- network = virNetworkCreateXML(ctl->conn, buffer);
+ network = virNetworkCreateXML(priv->conn, buffer);
VIR_FREE(buffer);
if (network != NULL) {
const char *from = NULL;
bool ret = true;
char *buffer;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
return false;
- network = virNetworkDefineXML(ctl->conn, buffer);
+ network = virNetworkDefineXML(priv->conn, buffer);
VIR_FREE(buffer);
if (network != NULL) {
bool ret = true;
const char *name;
- if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
+ if (!(network = virshCommandOptNetwork(ctl, cmd, &name)))
return false;
if (virNetworkDestroy(network) == 0) {
unsigned int flags = 0;
int inactive;
- if (!(network = vshCommandOptNetwork(ctl, cmd, NULL)))
+ if (!(network = virshCommandOptNetwork(ctl, cmd, NULL)))
return false;
inactive = vshCommandOptBool(cmd, "inactive");
int active = -1;
char *bridge = NULL;
- if (!(network = vshCommandOptNetwork(ctl, cmd, NULL)))
+ if (!(network = virshCommandOptNetwork(ctl, cmd, NULL)))
return false;
vshPrint(ctl, "%-15s %s\n", _("Name:"), virNetworkGetName(network));
}
static int
-vshNetworkSorter(const void *a, const void *b)
+virshNetworkSorter(const void *a, const void *b)
{
virNetworkPtr *na = (virNetworkPtr *) a;
virNetworkPtr *nb = (virNetworkPtr *) b;
virNetworkGetName(*nb));
}
-struct vshNetworkList {
+struct virshNetworkList {
virNetworkPtr *nets;
size_t nnets;
};
-typedef struct vshNetworkList *vshNetworkListPtr;
+typedef struct virshNetworkList *virshNetworkListPtr;
static void
-vshNetworkListFree(vshNetworkListPtr list)
+virshNetworkListFree(virshNetworkListPtr list)
{
size_t i;
VIR_FREE(list);
}
-static vshNetworkListPtr
-vshNetworkListCollect(vshControl *ctl,
- unsigned int flags)
+static virshNetworkListPtr
+virshNetworkListCollect(vshControl *ctl,
+ unsigned int flags)
{
- vshNetworkListPtr list = vshMalloc(ctl, sizeof(*list));
+ virshNetworkListPtr list = vshMalloc(ctl, sizeof(*list));
size_t i;
int ret;
char **names = NULL;
int nActiveNets = 0;
int nInactiveNets = 0;
int nAllNets = 0;
+ virshControlPtr priv = ctl->privData;
/* try the list with flags support (0.10.2 and later) */
- if ((ret = virConnectListAllNetworks(ctl->conn,
+ if ((ret = virConnectListAllNetworks(priv->conn,
&list->nets,
flags)) >= 0) {
list->nnets = ret;
VIR_CONNECT_LIST_NETWORKS_INACTIVE);
vshResetLibvirtError();
- if ((ret = virConnectListAllNetworks(ctl->conn, &list->nets,
+ if ((ret = virConnectListAllNetworks(priv->conn, &list->nets,
newflags)) >= 0) {
list->nnets = ret;
goto filter;
/* Get the number of active networks */
if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) {
- if ((nActiveNets = virConnectNumOfNetworks(ctl->conn)) < 0) {
+ if ((nActiveNets = virConnectNumOfNetworks(priv->conn)) < 0) {
vshError(ctl, "%s", _("Failed to get the number of active networks"));
goto cleanup;
}
/* Get the number of inactive networks */
if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_INACTIVE)) {
- if ((nInactiveNets = virConnectNumOfDefinedNetworks(ctl->conn)) < 0) {
+ if ((nInactiveNets = virConnectNumOfDefinedNetworks(priv->conn)) < 0) {
vshError(ctl, "%s", _("Failed to get the number of inactive networks"));
goto cleanup;
}
/* Retrieve a list of active network names */
if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) {
- if (virConnectListNetworks(ctl->conn,
+ if (virConnectListNetworks(priv->conn,
names, nActiveNets) < 0) {
vshError(ctl, "%s", _("Failed to list active networks"));
goto cleanup;
/* Add the inactive networks to the end of the name list */
if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) {
- if (virConnectListDefinedNetworks(ctl->conn,
+ if (virConnectListDefinedNetworks(priv->conn,
&names[nActiveNets],
nInactiveNets) < 0) {
vshError(ctl, "%s", _("Failed to list inactive networks"));
/* get active networks */
for (i = 0; i < nActiveNets; i++) {
- if (!(net = virNetworkLookupByName(ctl->conn, names[i])))
+ if (!(net = virNetworkLookupByName(priv->conn, names[i])))
continue;
list->nets[list->nnets++] = net;
}
/* get inactive networks */
for (i = 0; i < nInactiveNets; i++) {
- if (!(net = virNetworkLookupByName(ctl->conn, names[i])))
+ if (!(net = virNetworkLookupByName(priv->conn, names[i])))
continue;
list->nets[list->nnets++] = net;
}
/* sort the list */
if (list->nets && list->nnets)
qsort(list->nets, list->nnets,
- sizeof(*list->nets), vshNetworkSorter);
+ sizeof(*list->nets), virshNetworkSorter);
/* truncate the list if filter simulation deleted entries */
if (deleted)
VIR_FREE(names);
if (!success) {
- vshNetworkListFree(list);
+ virshNetworkListFree(list);
list = NULL;
}
static bool
cmdNetworkList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
- vshNetworkListPtr list = NULL;
+ virshNetworkListPtr list = NULL;
size_t i;
bool ret = false;
bool optName = vshCommandOptBool(cmd, "name");
if (!optUUID && !optName)
optTable = true;
- if (!(list = vshNetworkListCollect(ctl, flags)))
+ if (!(list = virshNetworkListCollect(ctl, flags)))
return false;
if (optTable) {
ret = true;
cleanup:
- vshNetworkListFree(list);
+ virshNetworkListFree(list);
return ret;
}
#undef FILTER
{
virNetworkPtr network;
- if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL,
- VSH_BYUUID)))
+ if (!(network = virshCommandOptNetworkBy(ctl, cmd, NULL,
+ VIRSH_BYUUID)))
return false;
vshPrint(ctl, "%s\n", virNetworkGetName(network));
bool ret = true;
const char *name = NULL;
- if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
+ if (!(network = virshCommandOptNetwork(ctl, cmd, &name)))
return false;
if (virNetworkCreate(network) == 0) {
bool ret = true;
const char *name;
- if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
+ if (!(network = virshCommandOptNetwork(ctl, cmd, &name)))
return false;
if (virNetworkUndefine(network) == 0) {
unsigned int flags = 0;
const char *affected;
- if (!(network = vshCommandOptNetwork(ctl, cmd, NULL)))
+ if (!(network = virshCommandOptNetwork(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "command", &commandStr) < 0)
virNetworkPtr network;
char uuid[VIR_UUID_STRING_BUFLEN];
- if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL,
- VSH_BYNAME)))
+ if (!(network = virshCommandOptNetworkBy(ctl, cmd, NULL,
+ VIRSH_BYNAME)))
return false;
if (virNetworkGetUUIDString(network, uuid) != -1)
{.name = NULL}
};
-static char *vshNetworkGetXMLDesc(virNetworkPtr network)
+static char *virshNetworkGetXMLDesc(virNetworkPtr network)
{
unsigned int flags = VIR_NETWORK_XML_INACTIVE;
char *doc = virNetworkGetXMLDesc(network, flags);
bool ret = false;
virNetworkPtr network = NULL;
virNetworkPtr network_edited = NULL;
+ virshControlPtr priv = ctl->privData;
- network = vshCommandOptNetwork(ctl, cmd, NULL);
+ network = virshCommandOptNetwork(ctl, cmd, NULL);
if (network == NULL)
goto cleanup;
-#define EDIT_GET_XML vshNetworkGetXMLDesc(network)
+#define EDIT_GET_XML virshNetworkGetXMLDesc(network)
#define EDIT_NOT_CHANGED \
do { \
vshPrint(ctl, _("Network %s XML configuration not changed.\n"), \
goto edit_cleanup; \
} while (0)
#define EDIT_DEFINE \
- (network_edited = virNetworkDefineXML(ctl->conn, doc_edited))
+ (network_edited = virNetworkDefineXML(priv->conn, doc_edited))
#include "virsh-edit.c"
vshPrint(ctl, _("Network %s XML configuration edited.\n"),
/*
* "net-event" command
*/
-VIR_ENUM_DECL(vshNetworkEvent)
-VIR_ENUM_IMPL(vshNetworkEvent,
+VIR_ENUM_DECL(virshNetworkEvent)
+VIR_ENUM_IMPL(virshNetworkEvent,
VIR_NETWORK_EVENT_LAST,
N_("Defined"),
N_("Undefined"),
N_("Stopped"))
static const char *
-vshNetworkEventToString(int event)
+virshNetworkEventToString(int event)
{
- const char *str = vshNetworkEventTypeToString(event);
+ const char *str = virshNetworkEventTypeToString(event);
return str ? _(str) : _("unknown");
}
-struct vshNetEventData {
+struct virshNetEventData {
vshControl *ctl;
bool loop;
int count;
};
-typedef struct vshNetEventData vshNetEventData;
+typedef struct virshNetEventData virshNetEventData;
-VIR_ENUM_DECL(vshNetworkEventId)
-VIR_ENUM_IMPL(vshNetworkEventId,
+VIR_ENUM_DECL(virshNetworkEventId)
+VIR_ENUM_IMPL(virshNetworkEventId,
VIR_NETWORK_EVENT_ID_LAST,
"lifecycle")
int detail ATTRIBUTE_UNUSED,
void *opaque)
{
- vshNetEventData *data = opaque;
+ virshNetEventData *data = opaque;
if (!data->loop && data->count)
return;
vshPrint(data->ctl, _("event 'lifecycle' for network %s: %s\n"),
- virNetworkGetName(net), vshNetworkEventToString(event));
+ virNetworkGetName(net), virshNetworkEventToString(event));
data->count++;
if (!data->loop)
vshEventDone(data->ctl);
bool ret = false;
int eventId = -1;
int timeout = 0;
- vshNetEventData data;
+ virshNetEventData data;
const char *eventName = NULL;
int event;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "list")) {
size_t i;
for (i = 0; i < VIR_NETWORK_EVENT_ID_LAST; i++)
- vshPrint(ctl, "%s\n", vshNetworkEventIdTypeToString(i));
+ vshPrint(ctl, "%s\n", virshNetworkEventIdTypeToString(i));
return true;
}
vshError(ctl, "%s", _("either --list or event type is required"));
return false;
}
- if ((event = vshNetworkEventIdTypeFromString(eventName)) < 0) {
+ if ((event = virshNetworkEventIdTypeFromString(eventName)) < 0) {
vshError(ctl, _("unknown event type %s"), eventName);
return false;
}
return false;
if (vshCommandOptBool(cmd, "network"))
- net = vshCommandOptNetwork(ctl, cmd, NULL);
+ net = virshCommandOptNetwork(ctl, cmd, NULL);
if (vshEventStart(ctl, timeout) < 0)
goto cleanup;
- if ((eventId = virConnectNetworkEventRegisterAny(ctl->conn, net, event,
+ if ((eventId = virConnectNetworkEventRegisterAny(priv->conn, net, event,
VIR_NETWORK_EVENT_CALLBACK(vshEventLifecyclePrint),
&data, NULL)) < 0)
goto cleanup;
cleanup:
vshEventCleanup(ctl);
if (eventId >= 0 &&
- virConnectNetworkEventDeregisterAny(ctl->conn, eventId) < 0)
+ virConnectNetworkEventDeregisterAny(priv->conn, eventId) < 0)
ret = false;
if (net)
virNetworkFree(net);
};
static int
-vshNetworkDHCPLeaseSorter(const void *a, const void *b)
+virshNetworkDHCPLeaseSorter(const void *a, const void *b)
{
int rv = -1;
if (vshCommandOptString(ctl, cmd, "mac", &mac) < 0)
return false;
- if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
+ if (!(network = virshCommandOptNetwork(ctl, cmd, &name)))
return false;
if ((nleases = virNetworkGetDHCPLeases(network, mac, &leases, flags)) < 0) {
}
/* Sort the list according to MAC Address/IAID */
- qsort(leases, nleases, sizeof(*leases), vshNetworkDHCPLeaseSorter);
+ qsort(leases, nleases, sizeof(*leases), virshNetworkDHCPLeaseSorter);
vshPrintExtra(ctl, " %-20s %-18s %-9s %-25s %-15s %s\n%s%s\n",
_("Expiry Time"), _("MAC address"), _("Protocol"),
# include "virsh.h"
virNetworkPtr
-vshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
- const char **name, unsigned int flags);
+virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
+ const char **name, unsigned int flags);
/* default is lookup by Name and UUID */
-# define vshCommandOptNetwork(_ctl, _cmd, _name) \
- vshCommandOptNetworkBy(_ctl, _cmd, _name, \
- VSH_BYUUID|VSH_BYNAME)
+# define virshCommandOptNetwork(_ctl, _cmd, _name) \
+ virshCommandOptNetworkBy(_ctl, _cmd, _name, \
+ VIRSH_BYUUID | VIRSH_BYNAME)
extern const vshCmdDef networkCmds[];
const char *from = NULL;
bool ret = true;
char *buffer;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
return false;
- dev = virNodeDeviceCreateXML(ctl->conn, buffer, 0);
+ dev = virNodeDeviceCreateXML(priv->conn, buffer, 0);
VIR_FREE(buffer);
if (dev != NULL) {
const char *device_value = NULL;
char **arr = NULL;
int narr;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "device", &device_value) < 0)
return false;
if (!virValidateWWN(arr[0]) || !virValidateWWN(arr[1]))
goto cleanup;
- dev = virNodeDeviceLookupSCSIHostByWWN(ctl->conn, arr[0], arr[1], 0);
+ dev = virNodeDeviceLookupSCSIHostByWWN(priv->conn, arr[0], arr[1], 0);
} else {
- dev = virNodeDeviceLookupByName(ctl->conn, device_value);
+ dev = virNodeDeviceLookupByName(priv->conn, device_value);
}
if (!dev) {
return ret;
}
-struct vshNodeList {
+struct virshNodeList {
char **names;
char **parents;
};
static const char *
-vshNodeListLookup(int devid, bool parent, void *opaque)
+virshNodeListLookup(int devid, bool parent, void *opaque)
{
- struct vshNodeList *arrays = opaque;
+ struct virshNodeList *arrays = opaque;
if (parent)
return arrays->parents[devid];
return arrays->names[devid];
}
static int
-vshNodeDeviceSorter(const void *a, const void *b)
+virshNodeDeviceSorter(const void *a, const void *b)
{
virNodeDevicePtr *na = (virNodeDevicePtr *) a;
virNodeDevicePtr *nb = (virNodeDevicePtr *) b;
virNodeDeviceGetName(*nb));
}
-struct vshNodeDeviceList {
+struct virshNodeDeviceList {
virNodeDevicePtr *devices;
size_t ndevices;
};
-typedef struct vshNodeDeviceList *vshNodeDeviceListPtr;
+typedef struct virshNodeDeviceList *virshNodeDeviceListPtr;
static void
-vshNodeDeviceListFree(vshNodeDeviceListPtr list)
+virshNodeDeviceListFree(virshNodeDeviceListPtr list)
{
size_t i;
VIR_FREE(list);
}
-static vshNodeDeviceListPtr
-vshNodeDeviceListCollect(vshControl *ctl,
+static virshNodeDeviceListPtr
+virshNodeDeviceListCollect(vshControl *ctl,
char **capnames,
int ncapnames,
unsigned int flags)
{
- vshNodeDeviceListPtr list = vshMalloc(ctl, sizeof(*list));
+ virshNodeDeviceListPtr list = vshMalloc(ctl, sizeof(*list));
size_t i;
int ret;
virNodeDevicePtr device;
size_t deleted = 0;
int ndevices = 0;
char **names = NULL;
+ virshControlPtr priv = ctl->privData;
/* try the list with flags support (0.10.2 and later) */
- if ((ret = virConnectListAllNodeDevices(ctl->conn,
+ if ((ret = virConnectListAllNodeDevices(priv->conn,
&list->devices,
flags)) >= 0) {
list->ndevices = ret;
/* fall back to old method (0.10.1 and older) */
vshResetLibvirtError();
- ndevices = virNodeNumOfDevices(ctl->conn, NULL, 0);
+ ndevices = virNodeNumOfDevices(priv->conn, NULL, 0);
if (ndevices < 0) {
vshError(ctl, "%s", _("Failed to count node devices"));
goto cleanup;
names = vshMalloc(ctl, sizeof(char *) * ndevices);
- ndevices = virNodeListDevices(ctl->conn, NULL, names, ndevices, 0);
+ ndevices = virNodeListDevices(priv->conn, NULL, names, ndevices, 0);
if (ndevices < 0) {
vshError(ctl, "%s", _("Failed to list node devices"));
goto cleanup;
/* get the node devices */
for (i = 0; i < ndevices; i++) {
- if (!(device = virNodeDeviceLookupByName(ctl->conn, names[i])))
+ if (!(device = virNodeDeviceLookupByName(priv->conn, names[i])))
continue;
list->devices[list->ndevices++] = device;
}
/* sort the list */
if (list->devices && list->ndevices)
qsort(list->devices, list->ndevices,
- sizeof(*list->devices), vshNodeDeviceSorter);
+ sizeof(*list->devices), virshNodeDeviceSorter);
/* truncate the list if filter simulation deleted entries */
if (deleted)
VIR_FREE(names);
if (!success) {
- vshNodeDeviceListFree(list);
+ virshNodeDeviceListFree(list);
list = NULL;
}
unsigned int flags = 0;
char **caps = NULL;
int ncaps = 0;
- vshNodeDeviceListPtr list = NULL;
+ virshNodeDeviceListPtr list = NULL;
int cap_type = -1;
ignore_value(vshCommandOptString(ctl, cmd, "cap", &cap_str));
}
}
- if (!(list = vshNodeDeviceListCollect(ctl, caps, ncaps, flags))) {
+ if (!(list = virshNodeDeviceListCollect(ctl, caps, ncaps, flags))) {
ret = false;
goto cleanup;
}
if (tree) {
char **parents = vshMalloc(ctl, sizeof(char *) * list->ndevices);
char **names = vshMalloc(ctl, sizeof(char *) * list->ndevices);
- struct vshNodeList arrays = { names, parents };
+ struct virshNodeList arrays = { names, parents };
for (i = 0; i < list->ndevices; i++)
names[i] = vshStrdup(ctl, virNodeDeviceGetName(list->devices[i]));
for (i = 0; i < list->ndevices; i++) {
if (parents[i] == NULL &&
- vshTreePrint(ctl, vshNodeListLookup, &arrays,
+ vshTreePrint(ctl, virshNodeListLookup, &arrays,
list->ndevices, i) < 0)
ret = false;
}
cleanup:
virStringFreeList(caps);
- vshNodeDeviceListFree(list);
+ virshNodeDeviceListFree(list);
return ret;
}
char **arr = NULL;
int narr;
bool ret = false;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "device", &device_value) < 0)
return false;
if (!virValidateWWN(arr[0]) || !virValidateWWN(arr[1]))
goto cleanup;
- device = virNodeDeviceLookupSCSIHostByWWN(ctl->conn, arr[0], arr[1], 0);
+ device = virNodeDeviceLookupSCSIHostByWWN(priv->conn, arr[0], arr[1], 0);
} else {
- device = virNodeDeviceLookupByName(ctl->conn, device_value);
+ device = virNodeDeviceLookupByName(priv->conn, device_value);
}
if (!device) {
const char *driverName = NULL;
virNodeDevicePtr device;
bool ret = true;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "device", &name) < 0)
return false;
ignore_value(vshCommandOptString(ctl, cmd, "driver", &driverName));
- if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) {
+ if (!(device = virNodeDeviceLookupByName(priv->conn, name))) {
vshError(ctl, _("Could not find matching device '%s'"), name);
return false;
}
const char *name = NULL;
virNodeDevicePtr device;
bool ret = true;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "device", &name) < 0)
return false;
- if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) {
+ if (!(device = virNodeDeviceLookupByName(priv->conn, name))) {
vshError(ctl, _("Could not find matching device '%s'"), name);
return false;
}
const char *name = NULL;
virNodeDevicePtr device;
bool ret = true;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "device", &name) < 0)
return false;
- if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) {
+ if (!(device = virNodeDeviceLookupByName(priv->conn, name))) {
vshError(ctl, _("Could not find matching device '%s'"), name);
return false;
}
#include "virutil.h"
virNWFilterPtr
-vshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd,
- const char **name, unsigned int flags)
+virshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd,
+ const char **name, unsigned int flags)
{
virNWFilterPtr nwfilter = NULL;
const char *n = NULL;
const char *optname = "nwfilter";
- virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL);
+ virshControlPtr priv = ctl->privData;
+
+ virCheckFlags(VIRSH_BYUUID | VIRSH_BYNAME, NULL);
if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
return NULL;
*name = n;
/* try it by UUID */
- if ((flags & VSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) {
+ if ((flags & VIRSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as nwfilter UUID\n",
cmd->def->name, optname);
- nwfilter = virNWFilterLookupByUUIDString(ctl->conn, n);
+ nwfilter = virNWFilterLookupByUUIDString(priv->conn, n);
}
/* try it by NAME */
- if (!nwfilter && (flags & VSH_BYNAME)) {
+ if (!nwfilter && (flags & VIRSH_BYNAME)) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as nwfilter NAME\n",
cmd->def->name, optname);
- nwfilter = virNWFilterLookupByName(ctl->conn, n);
+ nwfilter = virNWFilterLookupByName(priv->conn, n);
}
if (!nwfilter)
const char *from = NULL;
bool ret = true;
char *buffer;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
return false;
- nwfilter = virNWFilterDefineXML(ctl->conn, buffer);
+ nwfilter = virNWFilterDefineXML(priv->conn, buffer);
VIR_FREE(buffer);
if (nwfilter != NULL) {
bool ret = true;
const char *name;
- if (!(nwfilter = vshCommandOptNWFilter(ctl, cmd, &name)))
+ if (!(nwfilter = virshCommandOptNWFilter(ctl, cmd, &name)))
return false;
if (virNWFilterUndefine(nwfilter) == 0) {
bool ret = true;
char *dump;
- if (!(nwfilter = vshCommandOptNWFilter(ctl, cmd, NULL)))
+ if (!(nwfilter = virshCommandOptNWFilter(ctl, cmd, NULL)))
return false;
dump = virNWFilterGetXMLDesc(nwfilter, 0);
}
static int
-vshNWFilterSorter(const void *a, const void *b)
+virshNWFilterSorter(const void *a, const void *b)
{
virNWFilterPtr *fa = (virNWFilterPtr *) a;
virNWFilterPtr *fb = (virNWFilterPtr *) b;
virNWFilterGetName(*fb));
}
-struct vshNWFilterList {
+struct virshNWFilterList {
virNWFilterPtr *filters;
size_t nfilters;
};
-typedef struct vshNWFilterList *vshNWFilterListPtr;
+typedef struct virshNWFilterList *virshNWFilterListPtr;
static void
-vshNWFilterListFree(vshNWFilterListPtr list)
+virshNWFilterListFree(virshNWFilterListPtr list)
{
size_t i;
VIR_FREE(list);
}
-static vshNWFilterListPtr
-vshNWFilterListCollect(vshControl *ctl,
- unsigned int flags)
+static virshNWFilterListPtr
+virshNWFilterListCollect(vshControl *ctl,
+ unsigned int flags)
{
- vshNWFilterListPtr list = vshMalloc(ctl, sizeof(*list));
+ virshNWFilterListPtr list = vshMalloc(ctl, sizeof(*list));
size_t i;
int ret;
virNWFilterPtr filter;
size_t deleted = 0;
int nfilters = 0;
char **names = NULL;
+ virshControlPtr priv = ctl->privData;
/* try the list with flags support (0.10.2 and later) */
- if ((ret = virConnectListAllNWFilters(ctl->conn,
+ if ((ret = virConnectListAllNWFilters(priv->conn,
&list->filters,
flags)) >= 0) {
list->nfilters = ret;
/* fall back to old method (0.9.13 and older) */
vshResetLibvirtError();
- nfilters = virConnectNumOfNWFilters(ctl->conn);
+ nfilters = virConnectNumOfNWFilters(priv->conn);
if (nfilters < 0) {
vshError(ctl, "%s", _("Failed to count network filters"));
goto cleanup;
names = vshMalloc(ctl, sizeof(char *) * nfilters);
- nfilters = virConnectListNWFilters(ctl->conn, names, nfilters);
+ nfilters = virConnectListNWFilters(priv->conn, names, nfilters);
if (nfilters < 0) {
vshError(ctl, "%s", _("Failed to list network filters"));
goto cleanup;
/* get the network filters */
for (i = 0; i < nfilters; i++) {
- if (!(filter = virNWFilterLookupByName(ctl->conn, names[i])))
+ if (!(filter = virNWFilterLookupByName(priv->conn, names[i])))
continue;
list->filters[list->nfilters++] = filter;
}
/* sort the list */
if (list->filters && list->nfilters)
qsort(list->filters, list->nfilters,
- sizeof(*list->filters), vshNWFilterSorter);
+ sizeof(*list->filters), virshNWFilterSorter);
/* truncate the list for not found filter objects */
if (deleted)
VIR_FREE(names);
if (!success) {
- vshNWFilterListFree(list);
+ virshNWFilterListFree(list);
list = NULL;
}
{
size_t i;
char uuid[VIR_UUID_STRING_BUFLEN];
- vshNWFilterListPtr list = NULL;
+ virshNWFilterListPtr list = NULL;
- if (!(list = vshNWFilterListCollect(ctl, 0)))
+ if (!(list = virshNWFilterListCollect(ctl, 0)))
return false;
vshPrintExtra(ctl, " %-36s %-20s \n", _("UUID"), _("Name"));
virNWFilterGetName(nwfilter));
}
- vshNWFilterListFree(list);
+ virshNWFilterListFree(list);
return true;
}
bool ret = false;
virNWFilterPtr nwfilter = NULL;
virNWFilterPtr nwfilter_edited = NULL;
+ virshControlPtr priv = ctl->privData;
- nwfilter = vshCommandOptNWFilter(ctl, cmd, NULL);
+ nwfilter = virshCommandOptNWFilter(ctl, cmd, NULL);
if (nwfilter == NULL)
goto cleanup;
goto edit_cleanup; \
} while (0)
#define EDIT_DEFINE \
- (nwfilter_edited = virNWFilterDefineXML(ctl->conn, doc_edited))
+ (nwfilter_edited = virNWFilterDefineXML(priv->conn, doc_edited))
#include "virsh-edit.c"
vshPrint(ctl, _("Network filter %s XML configuration edited.\n"),
# include "virsh.h"
virNWFilterPtr
-vshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd,
- const char **name, unsigned int flags);
+virshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd,
+ const char **name, unsigned int flags);
/* default is lookup by Name and UUID */
-# define vshCommandOptNWFilter(_ctl, _cmd, _name) \
- vshCommandOptNWFilterBy(_ctl, _cmd, _name, \
- VSH_BYUUID|VSH_BYNAME)
+# define virshCommandOptNWFilter(_ctl, _cmd, _name) \
+ virshCommandOptNWFilterBy(_ctl, _cmd, _name, \
+ VIRSH_BYUUID | VIRSH_BYNAME)
extern const vshCmdDef nwfilterCmds[];
#include "virstring.h"
virStoragePoolPtr
-vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname,
- const char **name, unsigned int flags)
+virshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname,
+ const char **name, unsigned int flags)
{
virStoragePoolPtr pool = NULL;
const char *n = NULL;
- virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL);
+ virshControlPtr priv = ctl->privData;
+
+ virCheckFlags(VIRSH_BYUUID | VIRSH_BYNAME, NULL);
if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
return NULL;
*name = n;
/* try it by UUID */
- if ((flags & VSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) {
+ if ((flags & VIRSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as pool UUID\n",
cmd->def->name, optname);
- pool = virStoragePoolLookupByUUIDString(ctl->conn, n);
+ pool = virStoragePoolLookupByUUIDString(priv->conn, n);
}
/* try it by NAME */
- if (!pool && (flags & VSH_BYNAME)) {
+ if (!pool && (flags & VIRSH_BYNAME)) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as pool NAME\n",
cmd->def->name, optname);
- pool = virStoragePoolLookupByName(ctl->conn, n);
+ pool = virStoragePoolLookupByName(priv->conn, n);
}
if (!pool)
const char *name;
int autostart;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name)))
return false;
autostart = !vshCommandOptBool(cmd, "disable");
const char *from = NULL;
bool ret = true;
char *buffer;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
return false;
- pool = virStoragePoolCreateXML(ctl->conn, buffer, 0);
+ pool = virStoragePoolCreateXML(priv->conn, buffer, 0);
VIR_FREE(buffer);
if (pool != NULL) {
};
static int
-vshBuildPoolXML(vshControl *ctl,
- const vshCmd *cmd,
- const char **retname,
- char **xml)
+virshBuildPoolXML(vshControl *ctl,
+ const vshCmd *cmd,
+ const char **retname,
+ char **xml)
{
const char *name = NULL, *type = NULL, *srcHost = NULL, *srcPath = NULL,
*srcDev = NULL, *srcName = NULL, *srcFormat = NULL,
const char *name;
char *xml;
bool printXML = vshCommandOptBool(cmd, "print-xml");
+ virshControlPtr priv = ctl->privData;
- if (!vshBuildPoolXML(ctl, cmd, &name, &xml))
+ if (!virshBuildPoolXML(ctl, cmd, &name, &xml))
return false;
if (printXML) {
vshPrint(ctl, "%s", xml);
VIR_FREE(xml);
} else {
- pool = virStoragePoolCreateXML(ctl->conn, xml, 0);
+ pool = virStoragePoolCreateXML(priv->conn, xml, 0);
VIR_FREE(xml);
if (pool != NULL) {
const char *from = NULL;
bool ret = true;
char *buffer;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
return false;
- pool = virStoragePoolDefineXML(ctl->conn, buffer, 0);
+ pool = virStoragePoolDefineXML(priv->conn, buffer, 0);
VIR_FREE(buffer);
if (pool != NULL) {
const char *name;
char *xml;
bool printXML = vshCommandOptBool(cmd, "print-xml");
+ virshControlPtr priv = ctl->privData;
- if (!vshBuildPoolXML(ctl, cmd, &name, &xml))
+ if (!virshBuildPoolXML(ctl, cmd, &name, &xml))
return false;
if (printXML) {
vshPrint(ctl, "%s", xml);
VIR_FREE(xml);
} else {
- pool = virStoragePoolDefineXML(ctl->conn, xml, 0);
+ pool = virStoragePoolDefineXML(priv->conn, xml, 0);
VIR_FREE(xml);
if (pool != NULL) {
const char *name;
unsigned int flags = 0;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name)))
return false;
if (vshCommandOptBool(cmd, "no-overwrite"))
bool ret = true;
const char *name;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name)))
return false;
if (virStoragePoolDestroy(pool) == 0) {
bool ret = true;
const char *name;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name)))
return false;
if (virStoragePoolDelete(pool, 0) == 0) {
bool ret = true;
const char *name;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name)))
return false;
if (virStoragePoolRefresh(pool, 0) == 0) {
if (inactive)
flags |= VIR_STORAGE_XML_INACTIVE;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL)))
return false;
dump = virStoragePoolGetXMLDesc(pool, flags);
}
static int
-vshStoragePoolSorter(const void *a, const void *b)
+virshStoragePoolSorter(const void *a, const void *b)
{
virStoragePoolPtr *pa = (virStoragePoolPtr *) a;
virStoragePoolPtr *pb = (virStoragePoolPtr *) b;
virStoragePoolGetName(*pb));
}
-struct vshStoragePoolList {
+struct virshStoragePoolList {
virStoragePoolPtr *pools;
size_t npools;
};
-typedef struct vshStoragePoolList *vshStoragePoolListPtr;
+typedef struct virshStoragePoolList *virshStoragePoolListPtr;
static void
-vshStoragePoolListFree(vshStoragePoolListPtr list)
+virshStoragePoolListFree(virshStoragePoolListPtr list)
{
size_t i;
VIR_FREE(list);
}
-static vshStoragePoolListPtr
-vshStoragePoolListCollect(vshControl *ctl,
- unsigned int flags)
+static virshStoragePoolListPtr
+virshStoragePoolListCollect(vshControl *ctl,
+ unsigned int flags)
{
- vshStoragePoolListPtr list = vshMalloc(ctl, sizeof(*list));
+ virshStoragePoolListPtr list = vshMalloc(ctl, sizeof(*list));
size_t i;
int ret;
char **names = NULL;
int nActivePools = 0;
int nInactivePools = 0;
int nAllPools = 0;
+ virshControlPtr priv = ctl->privData;
/* try the list with flags support (0.10.2 and later) */
- if ((ret = virConnectListAllStoragePools(ctl->conn,
+ if ((ret = virConnectListAllStoragePools(priv->conn,
&list->pools,
flags)) >= 0) {
list->npools = ret;
unsigned int newflags = flags & (VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE |
VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE);
vshResetLibvirtError();
- if ((ret = virConnectListAllStoragePools(ctl->conn, &list->pools,
+ if ((ret = virConnectListAllStoragePools(priv->conn, &list->pools,
newflags)) >= 0) {
list->npools = ret;
goto filter;
/* Get the number of active pools */
if (!VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE)) {
- if ((nActivePools = virConnectNumOfStoragePools(ctl->conn)) < 0) {
+ if ((nActivePools = virConnectNumOfStoragePools(priv->conn)) < 0) {
vshError(ctl, "%s", _("Failed to get the number of active pools "));
goto cleanup;
}
/* Get the number of inactive pools */
if (!VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE)) {
- if ((nInactivePools = virConnectNumOfDefinedStoragePools(ctl->conn)) < 0) {
+ if ((nInactivePools = virConnectNumOfDefinedStoragePools(priv->conn)) < 0) {
vshError(ctl, "%s", _("Failed to get the number of inactive pools"));
goto cleanup;
}
/* Retrieve a list of active storage pool names */
if (!VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE)) {
- if (virConnectListStoragePools(ctl->conn,
+ if (virConnectListStoragePools(priv->conn,
names, nActivePools) < 0) {
vshError(ctl, "%s", _("Failed to list active pools"));
goto cleanup;
/* Add the inactive storage pools to the end of the name list */
if (!VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) ||
VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE)) {
- if (virConnectListDefinedStoragePools(ctl->conn,
+ if (virConnectListDefinedStoragePools(priv->conn,
&names[nActivePools],
nInactivePools) < 0) {
vshError(ctl, "%s", _("Failed to list inactive pools"));
/* get active pools */
for (i = 0; i < nActivePools; i++) {
- if (!(pool = virStoragePoolLookupByName(ctl->conn, names[i])))
+ if (!(pool = virStoragePoolLookupByName(priv->conn, names[i])))
continue;
list->pools[list->npools++] = pool;
}
/* get inactive pools */
for (i = 0; i < nInactivePools; i++) {
- if (!(pool = virStoragePoolLookupByName(ctl->conn, names[i])))
+ if (!(pool = virStoragePoolLookupByName(priv->conn, names[i])))
continue;
list->pools[list->npools++] = pool;
}
/* sort the list */
if (list->pools && list->npools)
qsort(list->pools, list->npools,
- sizeof(*list->pools), vshStoragePoolSorter);
+ sizeof(*list->pools), virshStoragePoolSorter);
/* truncate the list if filter simulation deleted entries */
if (deleted)
VIR_FREE(names[i]);
if (!success) {
- vshStoragePoolListFree(list);
+ virshStoragePoolListFree(list);
list = NULL;
}
}
-VIR_ENUM_DECL(vshStoragePoolState)
-VIR_ENUM_IMPL(vshStoragePoolState,
+VIR_ENUM_DECL(virshStoragePoolState)
+VIR_ENUM_IMPL(virshStoragePoolState,
VIR_STORAGE_POOL_STATE_LAST,
N_("inactive"),
N_("building"),
N_("inaccessible"))
static const char *
-vshStoragePoolStateToString(int state)
+virshStoragePoolStateToString(int state)
{
- const char *str = vshStoragePoolStateTypeToString(state);
+ const char *str = virshStoragePoolStateTypeToString(state);
return str ? _(str) : _("unknown");
}
};
struct poolInfoText *poolInfoTexts = NULL;
unsigned int flags = VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE;
- vshStoragePoolListPtr list = NULL;
+ virshStoragePoolListPtr list = NULL;
const char *type = NULL;
bool details = vshCommandOptBool(cmd, "details");
bool inactive, all;
virStringFreeList(poolTypes);
}
- if (!(list = vshStoragePoolListCollect(ctl, flags)))
+ if (!(list = virshStoragePoolListCollect(ctl, flags)))
goto cleanup;
poolInfoTexts = vshCalloc(ctl, list->npools, sizeof(*poolInfoTexts));
} else {
/* Decide which state string to display */
if (details) {
- const char *state = vshStoragePoolStateToString(info.state);
+ const char *state = virshStoragePoolStateToString(info.state);
poolInfoTexts[i].state = vshStrdup(ctl, state);
}
VIR_FREE(poolInfoTexts);
- vshStoragePoolListFree(list);
+ virshStoragePoolListFree(list);
return ret;
}
char *srcSpec = NULL;
char *srcList;
const char *initiator = NULL;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "type", &type) < 0 ||
vshCommandOptStringReq(ctl, cmd, "host", &host) < 0 ||
srcSpec = virBufferContentAndReset(&buf);
}
- srcList = virConnectFindStoragePoolSources(ctl->conn, type, srcSpec, 0);
+ srcList = virConnectFindStoragePoolSources(priv->conn, type, srcSpec, 0);
VIR_FREE(srcSpec);
if (srcList == NULL) {
vshError(ctl, _("Failed to find any %s pool sources"), type);
{
const char *type = NULL, *srcSpecFile = NULL;
char *srcSpec = NULL, *srcList;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "type", &type) < 0)
return false;
&srcSpec) < 0)
return false;
- srcList = virConnectFindStoragePoolSources(ctl->conn, type, srcSpec, 0);
+ srcList = virConnectFindStoragePoolSources(priv->conn, type, srcSpec, 0);
VIR_FREE(srcSpec);
if (srcList == NULL) {
vshError(ctl, _("Failed to find any %s pool sources"), type);
bool ret = true;
char uuid[VIR_UUID_STRING_BUFLEN];
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL)))
return false;
vshPrint(ctl, "%-15s %s\n", _("Name:"), virStoragePoolGetName(pool));
double val;
const char *unit;
vshPrint(ctl, "%-15s %s\n", _("State:"),
- vshStoragePoolStateToString(info.state));
+ virshStoragePoolStateToString(info.state));
/* Check and display whether the pool is persistent or not */
persistent = virStoragePoolIsPersistent(pool);
{
virStoragePoolPtr pool;
- if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
- VSH_BYUUID)))
+ if (!(pool = virshCommandOptPoolBy(ctl, cmd, "pool", NULL, VIRSH_BYUUID)))
return false;
vshPrint(ctl, "%s\n", virStoragePoolGetName(pool));
bool ret = true;
const char *name = NULL;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name)))
return false;
if (virStoragePoolCreate(pool, 0) == 0) {
bool ret = true;
const char *name;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name)))
return false;
if (virStoragePoolUndefine(pool) == 0) {
virStoragePoolPtr pool;
char uuid[VIR_UUID_STRING_BUFLEN];
- if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
- VSH_BYNAME)))
+ if (!(pool = virshCommandOptPoolBy(ctl, cmd, "pool", NULL, VIRSH_BYNAME)))
return false;
if (virStoragePoolGetUUIDString(pool, uuid) != -1)
virStoragePoolPtr pool_edited = NULL;
unsigned int flags = VIR_STORAGE_XML_INACTIVE;
char *tmp_desc = NULL;
+ virshControlPtr priv = ctl->privData;
- pool = vshCommandOptPool(ctl, cmd, "pool", NULL);
+ pool = virshCommandOptPool(ctl, cmd, "pool", NULL);
if (pool == NULL)
goto cleanup;
goto edit_cleanup; \
} while (0)
#define EDIT_DEFINE \
- (pool_edited = virStoragePoolDefineXML(ctl->conn, doc_edited, 0))
+ (pool_edited = virStoragePoolDefineXML(priv->conn, doc_edited, 0))
#include "virsh-edit.c"
vshPrint(ctl, _("Pool %s XML configuration edited.\n"),
# include "virsh.h"
virStoragePoolPtr
-vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname,
- const char **name, unsigned int flags);
+virshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname,
+ const char **name, unsigned int flags);
/* default is lookup by Name and UUID */
-# define vshCommandOptPool(_ctl, _cmd, _optname, _name) \
- vshCommandOptPoolBy(_ctl, _cmd, _optname, _name, \
- VSH_BYUUID|VSH_BYNAME)
+# define virshCommandOptPool(_ctl, _cmd, _optname, _name) \
+ virshCommandOptPoolBy(_ctl, _cmd, _optname, _name, \
+ VIRSH_BYUUID | VIRSH_BYNAME)
extern const vshCmdDef storagePoolCmds[];
#include "conf/secret_conf.h"
static virSecretPtr
-vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name)
+virshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name)
{
virSecretPtr secret = NULL;
const char *n = NULL;
const char *optname = "secret";
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
return NULL;
if (name != NULL)
*name = n;
- secret = virSecretLookupByUUIDString(ctl->conn, n);
+ secret = virSecretLookupByUUIDString(priv->conn, n);
if (secret == NULL)
vshError(ctl, _("failed to get secret '%s'"), n);
virSecretPtr res;
char uuid[VIR_UUID_STRING_BUFLEN];
bool ret = false;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
return false;
- if (!(res = virSecretDefineXML(ctl->conn, buffer, 0))) {
+ if (!(res = virSecretDefineXML(priv->conn, buffer, 0))) {
vshError(ctl, _("Failed to set attributes from %s"), from);
goto cleanup;
}
bool ret = false;
char *xml;
- secret = vshCommandOptSecret(ctl, cmd, NULL);
+ secret = virshCommandOptSecret(ctl, cmd, NULL);
if (secret == NULL)
return false;
int res;
bool ret = false;
- if (!(secret = vshCommandOptSecret(ctl, cmd, NULL)))
+ if (!(secret = virshCommandOptSecret(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "base64", &base64) < 0)
size_t value_size;
bool ret = false;
- secret = vshCommandOptSecret(ctl, cmd, NULL);
+ secret = virshCommandOptSecret(ctl, cmd, NULL);
if (secret == NULL)
return false;
bool ret = false;
const char *uuid;
- secret = vshCommandOptSecret(ctl, cmd, &uuid);
+ secret = virshCommandOptSecret(ctl, cmd, &uuid);
if (secret == NULL)
return false;
}
static int
-vshSecretSorter(const void *a, const void *b)
+virshSecretSorter(const void *a, const void *b)
{
virSecretPtr *sa = (virSecretPtr *) a;
virSecretPtr *sb = (virSecretPtr *) b;
return vshStrcasecmp(uuid_sa, uuid_sb);
}
-struct vshSecretList {
+struct virshSecretList {
virSecretPtr *secrets;
size_t nsecrets;
};
-typedef struct vshSecretList *vshSecretListPtr;
+typedef struct virshSecretList *virshSecretListPtr;
static void
-vshSecretListFree(vshSecretListPtr list)
+virshSecretListFree(virshSecretListPtr list)
{
size_t i;
VIR_FREE(list);
}
-static vshSecretListPtr
-vshSecretListCollect(vshControl *ctl,
- unsigned int flags)
+static virshSecretListPtr
+virshSecretListCollect(vshControl *ctl,
+ unsigned int flags)
{
- vshSecretListPtr list = vshMalloc(ctl, sizeof(*list));
+ virshSecretListPtr list = vshMalloc(ctl, sizeof(*list));
size_t i;
int ret;
virSecretPtr secret;
size_t deleted = 0;
int nsecrets = 0;
char **uuids = NULL;
+ virshControlPtr priv = ctl->privData;
/* try the list with flags support (0.10.2 and later) */
- if ((ret = virConnectListAllSecrets(ctl->conn,
+ if ((ret = virConnectListAllSecrets(priv->conn,
&list->secrets,
flags)) >= 0) {
list->nsecrets = ret;
goto cleanup;
}
- nsecrets = virConnectNumOfSecrets(ctl->conn);
+ nsecrets = virConnectNumOfSecrets(priv->conn);
if (nsecrets < 0) {
vshError(ctl, "%s", _("Failed to count secrets"));
goto cleanup;
uuids = vshMalloc(ctl, sizeof(char *) * nsecrets);
- nsecrets = virConnectListSecrets(ctl->conn, uuids, nsecrets);
+ nsecrets = virConnectListSecrets(priv->conn, uuids, nsecrets);
if (nsecrets < 0) {
vshError(ctl, "%s", _("Failed to list secrets"));
goto cleanup;
/* get the secrets */
for (i = 0; i < nsecrets; i++) {
- if (!(secret = virSecretLookupByUUIDString(ctl->conn, uuids[i])))
+ if (!(secret = virSecretLookupByUUIDString(priv->conn, uuids[i])))
continue;
list->secrets[list->nsecrets++] = secret;
}
/* sort the list */
if (list->secrets && list->nsecrets)
qsort(list->secrets, list->nsecrets,
- sizeof(*list->secrets), vshSecretSorter);
+ sizeof(*list->secrets), virshSecretSorter);
/* truncate the list for not found secret objects */
if (deleted)
}
if (!success) {
- vshSecretListFree(list);
+ virshSecretListFree(list);
list = NULL;
}
cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
size_t i;
- vshSecretListPtr list = NULL;
+ virshSecretListPtr list = NULL;
bool ret = false;
unsigned int flags = 0;
if (vshCommandOptBool(cmd, "no-private"))
flags |= VIR_CONNECT_LIST_SECRETS_NO_PRIVATE;
- if (!(list = vshSecretListCollect(ctl, flags)))
+ if (!(list = virshSecretListCollect(ctl, flags)))
return false;
vshPrintExtra(ctl, " %-36s %s\n", _("UUID"), _("Usage"));
ret = true;
cleanup:
- vshSecretListFree(list);
+ virshSecretListFree(list);
return ret;
}
/* Helper for snapshot-create and snapshot-create-as */
static bool
-vshSnapshotCreate(vshControl *ctl, virDomainPtr dom, const char *buffer,
- unsigned int flags, const char *from)
+virshSnapshotCreate(vshControl *ctl, virDomainPtr dom, const char *buffer,
+ unsigned int flags, const char *from)
{
bool ret = false;
virDomainSnapshotPtr snapshot;
if (vshCommandOptBool(cmd, "live"))
flags |= VIR_DOMAIN_SNAPSHOT_CREATE_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
goto cleanup;
if (vshCommandOptStringReq(ctl, cmd, "xmlfile", &from) < 0)
}
}
- ret = vshSnapshotCreate(ctl, dom, buffer, flags, from);
+ ret = virshSnapshotCreate(ctl, dom, buffer, flags, from);
cleanup:
VIR_FREE(buffer);
* "snapshot-create-as" command
*/
static int
-vshParseSnapshotMemspec(vshControl *ctl, virBufferPtr buf, const char *str)
+virshParseSnapshotMemspec(vshControl *ctl, virBufferPtr buf, const char *str)
{
int ret = -1;
const char *snapshot = NULL;
}
static int
-vshParseSnapshotDiskspec(vshControl *ctl, virBufferPtr buf, const char *str)
+virshParseSnapshotDiskspec(vshControl *ctl, virBufferPtr buf, const char *str)
{
int ret = -1;
const char *name = NULL;
if (vshCommandOptBool(cmd, "live"))
flags |= VIR_DOMAIN_SNAPSHOT_CREATE_LIVE;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0 ||
if (vshCommandOptStringReq(ctl, cmd, "memspec", &memspec) < 0)
goto cleanup;
- if (memspec && vshParseSnapshotMemspec(ctl, &buf, memspec) < 0)
+ if (memspec && virshParseSnapshotMemspec(ctl, &buf, memspec) < 0)
goto cleanup;
if (vshCommandOptBool(cmd, "diskspec")) {
virBufferAddLit(&buf, "<disks>\n");
virBufferAdjustIndent(&buf, 2);
while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
- if (vshParseSnapshotDiskspec(ctl, &buf, opt->data) < 0)
+ if (virshParseSnapshotDiskspec(ctl, &buf, opt->data) < 0)
goto cleanup;
}
virBufferAdjustIndent(&buf, -2);
goto cleanup;
}
- ret = vshSnapshotCreate(ctl, dom, buffer, flags, NULL);
+ ret = virshSnapshotCreate(ctl, dom, buffer, flags, NULL);
cleanup:
virBufferFreeAndReset(&buf);
* present. On success, populate *SNAP and *NAME, before returning 0.
* On failure, return -1 after issuing an error message. */
static int
-vshLookupSnapshot(vshControl *ctl, const vshCmd *cmd,
- const char *arg, bool exclusive, virDomainPtr dom,
- virDomainSnapshotPtr *snap, const char **name)
+virshLookupSnapshot(vshControl *ctl, const vshCmd *cmd,
+ const char *arg, bool exclusive, virDomainPtr dom,
+ virDomainSnapshotPtr *snap, const char **name)
{
bool current = vshCommandOptBool(cmd, "current");
const char *snapname = NULL;
vshCommandOptBool(cmd, "snapshotname"))
define_flags |= VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
- if (vshLookupSnapshot(ctl, cmd, "snapshotname", false, dom,
- &snapshot, &name) < 0)
+ if (virshLookupSnapshot(ctl, cmd, "snapshotname", false, dom,
+ &snapshot, &name) < 0)
goto cleanup;
#define EDIT_GET_XML \
VSH_EXCLUSIVE_OPTIONS("name", "snapshotname");
- if (!(dom = vshCommandOptDomain(ctl, cmd, &domname)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, &domname)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "snapshotname", &snapshotname) < 0)
* proven no parent exists), and -1 on failure with error reported
* (such as no snapshot support or domain deleted in meantime). */
static int
-vshGetSnapshotParent(vshControl *ctl, virDomainSnapshotPtr snapshot,
- char **parent_name)
+virshGetSnapshotParent(vshControl *ctl, virDomainSnapshotPtr snapshot,
+ char **parent_name)
{
virDomainSnapshotPtr parent = NULL;
char *xml = NULL;
xmlDocPtr xmldoc = NULL;
xmlXPathContextPtr ctxt = NULL;
int ret = -1;
+ virshControlPtr priv = ctl->privData;
*parent_name = NULL;
/* Try new API, since it is faster. */
- if (!ctl->useSnapshotOld) {
+ if (!priv->useSnapshotOld) {
parent = virDomainSnapshotGetParent(snapshot, 0);
if (parent) {
/* API works, and virDomainSnapshotGetName will succeed */
goto cleanup;
}
/* API didn't work, fall back to XML scraping. */
- ctl->useSnapshotOld = true;
+ priv->useSnapshotOld = true;
}
xml = virDomainSnapshotGetXMLDesc(snapshot, 0);
* 1 if snapshot is okay (or if snapshot is already NULL), and -1 on
* failure, with error already reported. */
static int
-vshSnapshotFilter(vshControl *ctl, virDomainSnapshotPtr snapshot,
- unsigned int flags)
+virshSnapshotFilter(vshControl *ctl, virDomainSnapshotPtr snapshot,
+ unsigned int flags)
{
char *xml = NULL;
xmlDocPtr xmldoc = NULL;
unsigned int flags;
int current;
int metadata;
+ virshControlPtr priv = ctl->privData;
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
return false;
- if (vshLookupSnapshot(ctl, cmd, "snapshotname", true, dom,
- &snapshot, &name) < 0)
+ if (virshLookupSnapshot(ctl, cmd, "snapshotname", true, dom,
+ &snapshot, &name) < 0)
goto cleanup;
vshPrint(ctl, "%-15s %s\n", _("Name:"), name);
/* Children, Descendants. After this point, the fallback to
* compute children is too expensive, so we gracefully quit if the
* APIs don't exist. */
- if (ctl->useSnapshotOld) {
+ if (priv->useSnapshotOld) {
ret = true;
goto cleanup;
}
}
/* Helpers for collecting a list of snapshots. */
-struct vshSnap {
+struct virshSnap {
virDomainSnapshotPtr snap;
char *parent;
};
-struct vshSnapshotList {
- struct vshSnap *snaps;
+struct virshSnapshotList {
+ struct virshSnap *snaps;
int nsnaps;
};
-typedef struct vshSnapshotList *vshSnapshotListPtr;
+typedef struct virshSnapshotList *virshSnapshotListPtr;
static void
-vshSnapshotListFree(vshSnapshotListPtr snaplist)
+virshSnapshotListFree(virshSnapshotListPtr snaplist)
{
size_t i;
}
static int
-vshSnapSorter(const void *a, const void *b)
+virshSnapSorter(const void *a, const void *b)
{
- const struct vshSnap *sa = a;
- const struct vshSnap *sb = b;
+ const struct virshSnap *sa = a;
+ const struct virshSnap *sb = b;
if (sa->snap && !sb->snap)
return -1;
* list is limited to descendants of the given snapshot. If FLAGS is
* given, the list is filtered. If TREE is specified, then all but
* FROM or the roots will also have parent information. */
-static vshSnapshotListPtr
-vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom,
- virDomainSnapshotPtr from,
- unsigned int orig_flags, bool tree)
+static virshSnapshotListPtr
+virshSnapshotListCollect(vshControl *ctl, virDomainPtr dom,
+ virDomainSnapshotPtr from,
+ unsigned int orig_flags, bool tree)
{
size_t i;
char **names = NULL;
bool descendants = false;
bool roots = false;
virDomainSnapshotPtr *snaps;
- vshSnapshotListPtr snaplist = vshMalloc(ctl, sizeof(*snaplist));
- vshSnapshotListPtr ret = NULL;
+ virshSnapshotListPtr snaplist = vshMalloc(ctl, sizeof(*snaplist));
+ virshSnapshotListPtr ret = NULL;
const char *fromname = NULL;
int start_index = -1;
int deleted = 0;
bool filter_fallback = false;
unsigned int flags = orig_flags;
+ virshControlPtr priv = ctl->privData;
/* Try the interface available in 0.9.13 and newer. */
- if (!ctl->useSnapshotOld) {
+ if (!priv->useSnapshotOld) {
if (from)
count = virDomainSnapshotListAllChildren(from, &snaps, flags);
else
VIR_FREE(snaps);
if (tree) {
for (i = 0; i < count; i++) {
- if (vshGetSnapshotParent(ctl, snaplist->snaps[i].snap,
- &snaplist->snaps[i].parent) < 0)
+ if (virshGetSnapshotParent(ctl, snaplist->snaps[i].snap,
+ &snaplist->snaps[i].parent) < 0)
goto cleanup;
}
if (from) {
flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
/* Determine if we can use the new child listing API. */
- if (ctl->useSnapshotOld ||
+ if (priv->useSnapshotOld ||
((count = virDomainSnapshotNumChildren(from, flags)) < 0 &&
last_error->code == VIR_ERR_NO_SUPPORT)) {
/* We can emulate --from. */
/* XXX can we also emulate --leaves? */
vshResetLibvirtError();
- ctl->useSnapshotOld = true;
+ priv->useSnapshotOld = true;
flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
goto global;
}
names = vshCalloc(ctl, sizeof(*names), count);
/* Now that we have a count, collect the list. */
- if (from && !ctl->useSnapshotOld) {
+ if (from && !priv->useSnapshotOld) {
if (tree) {
if (count)
count = virDomainSnapshotListChildrenNames(from, names + 1,
* --from together put from as the first element without a parent;
* with the old API we still need to do a post-process filtering
* based on all parent information. */
- if (tree || (from && ctl->useSnapshotOld) || roots) {
- for (i = (from && !ctl->useSnapshotOld); i < count; i++) {
- if (from && ctl->useSnapshotOld && STREQ(names[i], fromname)) {
+ if (tree || (from && priv->useSnapshotOld) || roots) {
+ for (i = (from && !priv->useSnapshotOld); i < count; i++) {
+ if (from && priv->useSnapshotOld && STREQ(names[i], fromname)) {
start_index = i;
if (tree)
continue;
}
- if (vshGetSnapshotParent(ctl, snaplist->snaps[i].snap,
- &snaplist->snaps[i].parent) < 0)
+ if (virshGetSnapshotParent(ctl, snaplist->snaps[i].snap,
+ &snaplist->snaps[i].parent) < 0)
goto cleanup;
if ((from && ((tree && !snaplist->snaps[i].parent) ||
(!descendants &&
if (tree)
goto success;
- if (ctl->useSnapshotOld && descendants) {
+ if (priv->useSnapshotOld && descendants) {
bool changed = false;
bool remaining = false;
if (!(orig_flags & VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION))
orig_flags |= VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION;
for (i = 0; i < snaplist->nsnaps; i++) {
- switch (vshSnapshotFilter(ctl, snaplist->snaps[i].snap,
- orig_flags)) {
+ switch (virshSnapshotFilter(ctl, snaplist->snaps[i].snap,
+ orig_flags)) {
case 1:
break;
case 0:
}
}
qsort(snaplist->snaps, snaplist->nsnaps, sizeof(*snaplist->snaps),
- vshSnapSorter);
+ virshSnapSorter);
snaplist->nsnaps -= deleted;
ret = snaplist;
snaplist = NULL;
cleanup:
- vshSnapshotListFree(snaplist);
+ virshSnapshotListFree(snaplist);
if (names && count > 0)
for (i = 0; i < count; i++)
VIR_FREE(names[i]);
}
static const char *
-vshSnapshotListLookup(int id, bool parent, void *opaque)
+virshSnapshotListLookup(int id, bool parent, void *opaque)
{
- vshSnapshotListPtr snaplist = opaque;
+ virshSnapshotListPtr snaplist = opaque;
if (parent)
return snaplist->snaps[id].parent;
return virDomainSnapshotGetName(snaplist->snaps[id].snap);
const char *from_snap = NULL;
char *parent_snap = NULL;
virDomainSnapshotPtr start = NULL;
- vshSnapshotListPtr snaplist = NULL;
+ virshSnapshotListPtr snaplist = NULL;
VSH_EXCLUSIVE_OPTIONS_VAR(tree, name);
VSH_EXCLUSIVE_OPTIONS_VAR(parent, roots);
flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
}
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if ((from || current) &&
- vshLookupSnapshot(ctl, cmd, "from", true, dom, &start, &from_snap) < 0)
+ virshLookupSnapshot(ctl, cmd, "from", true, dom, &start, &from_snap) < 0)
goto cleanup;
- if (!(snaplist = vshSnapshotListCollect(ctl, dom, start, flags, tree)))
+ if (!(snaplist = virshSnapshotListCollect(ctl, dom, start, flags, tree)))
goto cleanup;
if (!tree && !name) {
if (tree) {
for (i = 0; i < snaplist->nsnaps; i++) {
if (!snaplist->snaps[i].parent &&
- vshTreePrint(ctl, vshSnapshotListLookup, snaplist,
+ vshTreePrint(ctl, virshSnapshotListLookup, snaplist,
snaplist->nsnaps, i) < 0)
goto cleanup;
}
cleanup:
/* this frees up memory from the last iteration of the loop */
- vshSnapshotListFree(snaplist);
+ virshSnapshotListFree(snaplist);
VIR_FREE(parent_snap);
VIR_FREE(state);
if (start)
if (vshCommandOptStringReq(ctl, cmd, "snapshotname", &name) < 0)
return false;
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
if (!(snapshot = virDomainSnapshotLookupByName(dom, name, 0)))
virDomainSnapshotPtr snapshot = NULL;
char *parent = NULL;
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
- if (vshLookupSnapshot(ctl, cmd, "snapshotname", true, dom,
- &snapshot, &name) < 0)
+ if (virshLookupSnapshot(ctl, cmd, "snapshotname", true, dom,
+ &snapshot, &name) < 0)
goto cleanup;
- if (vshGetSnapshotParent(ctl, snapshot, &parent) < 0)
+ if (virshGetSnapshotParent(ctl, snapshot, &parent) < 0)
goto cleanup;
if (!parent) {
vshError(ctl, _("snapshot '%s' has no parent"), name);
if (vshCommandOptBool(cmd, "force"))
force = true;
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
- if (vshLookupSnapshot(ctl, cmd, "snapshotname", true, dom,
- &snapshot, &name) < 0)
+ if (virshLookupSnapshot(ctl, cmd, "snapshotname", true, dom,
+ &snapshot, &name) < 0)
goto cleanup;
result = virDomainRevertToSnapshot(snapshot, flags);
virDomainSnapshotPtr snapshot = NULL;
unsigned int flags = 0;
- dom = vshCommandOptDomain(ctl, cmd, NULL);
+ dom = virshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
- if (vshLookupSnapshot(ctl, cmd, "snapshotname", true, dom,
- &snapshot, &name) < 0)
+ if (virshLookupSnapshot(ctl, cmd, "snapshotname", true, dom,
+ &snapshot, &name) < 0)
goto cleanup;
if (vshCommandOptBool(cmd, "children"))
#include "virstring.h"
virStorageVolPtr
-vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
- const char *optname,
- const char *pooloptname,
- const char **name, unsigned int flags)
+virshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
+ const char *optname,
+ const char *pooloptname,
+ const char **name, unsigned int flags)
{
virStorageVolPtr vol = NULL;
virStoragePoolPtr pool = NULL;
const char *n = NULL, *p = NULL;
- virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL);
+ virshControlPtr priv = ctl->privData;
+
+ virCheckFlags(VIRSH_BYUUID | VIRSH_BYNAME, NULL);
if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
return NULL;
return NULL;
if (p) {
- if (!(pool = vshCommandOptPoolBy(ctl, cmd, pooloptname, name, flags)))
+ if (!(pool = virshCommandOptPoolBy(ctl, cmd, pooloptname, name, flags)))
return NULL;
if (virStoragePoolIsActive(pool) != 1) {
*name = n;
/* try it by name */
- if (pool && (flags & VSH_BYNAME)) {
+ if (pool && (flags & VIRSH_BYNAME)) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol name\n",
cmd->def->name, optname);
vol = virStorageVolLookupByName(pool, n);
}
/* try it by key */
- if (!vol && (flags & VSH_BYUUID)) {
+ if (!vol && (flags & VIRSH_BYUUID)) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol key\n",
cmd->def->name, optname);
- vol = virStorageVolLookupByKey(ctl->conn, n);
+ vol = virStorageVolLookupByKey(priv->conn, n);
}
/* try it by path */
- if (!vol && (flags & VSH_BYUUID)) {
+ if (!vol && (flags & VIRSH_BYUUID)) {
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol path\n",
cmd->def->name, optname);
- vol = virStorageVolLookupByPath(ctl->conn, n);
+ vol = virStorageVolLookupByPath(priv->conn, n);
}
if (!vol) {
};
static int
-vshVolSize(const char *data, unsigned long long *val)
+virshVolSize(const char *data, unsigned long long *val)
{
char *end;
if (virStrToLong_ull(data, &end, 10, val) < 0)
unsigned long long capacity, allocation = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
unsigned long flags = 0;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptBool(cmd, "prealloc-metadata"))
flags |= VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0)
if (vshCommandOptStringReq(ctl, cmd, "capacity", &capacityStr) < 0)
goto cleanup;
- if (vshVolSize(capacityStr, &capacity) < 0) {
+ if (virshVolSize(capacityStr, &capacity) < 0) {
vshError(ctl, _("Malformed size %s"), capacityStr);
goto cleanup;
}
if (vshCommandOptString(ctl, cmd, "allocation", &allocationStr) > 0 &&
- vshVolSize(allocationStr, &allocation) < 0) {
+ virshVolSize(allocationStr, &allocation) < 0) {
vshError(ctl, _("Malformed size %s"), allocationStr);
goto cleanup;
}
vshDebug(ctl, VSH_ERR_DEBUG,
"%s: Look up backing store volume '%s' as key\n",
cmd->def->name, snapshotStrVol);
- snapVol = virStorageVolLookupByKey(ctl->conn, snapshotStrVol);
+ snapVol = virStorageVolLookupByKey(priv->conn, snapshotStrVol);
if (snapVol)
vshDebug(ctl, VSH_ERR_DEBUG,
"%s: Backing store volume found using '%s' as key\n",
vshDebug(ctl, VSH_ERR_DEBUG,
"%s: Look up backing store volume '%s' as path\n",
cmd->def->name, snapshotStrVol);
- snapVol = virStorageVolLookupByPath(ctl->conn, snapshotStrVol);
+ snapVol = virStorageVolLookupByPath(priv->conn, snapshotStrVol);
if (snapVol)
vshDebug(ctl, VSH_ERR_DEBUG,
"%s: Backing store volume found using '%s' as path\n",
if (vshCommandOptBool(cmd, "prealloc-metadata"))
flags |= VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
char *buffer = NULL;
unsigned int flags = 0;
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL)))
goto cleanup;
if (vshCommandOptBool(cmd, "prealloc-metadata"))
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
goto cleanup;
- if (!(inputvol = vshCommandOptVol(ctl, cmd, "vol", "inputpool", NULL)))
+ if (!(inputvol = virshCommandOptVol(ctl, cmd, "vol", "inputpool", NULL)))
goto cleanup;
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) {
}
static xmlChar *
-vshMakeCloneXML(const char *origxml, const char *newname)
+virshMakeCloneXML(const char *origxml, const char *newname)
{
xmlDocPtr doc = NULL;
bool ret = false;
unsigned int flags = 0;
- if (!(origvol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+ if (!(origvol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
goto cleanup;
if (vshCommandOptBool(cmd, "prealloc-metadata"))
if (!origxml)
goto cleanup;
- newxml = vshMakeCloneXML(origxml, name);
+ newxml = virshMakeCloneXML(origxml, name);
if (!newxml) {
vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
goto cleanup;
virStreamPtr st = NULL;
const char *name = NULL;
unsigned long long offset = 0, length = 0;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptULongLong(ctl, cmd, "offset", &offset) < 0)
return false;
if (vshCommandOptULongLongWrap(ctl, cmd, "length", &length) < 0)
return false;
- if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
+ if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0)
goto cleanup;
}
- if (!(st = virStreamNew(ctl->conn, 0))) {
+ if (!(st = virStreamNew(priv->conn, 0))) {
vshError(ctl, _("cannot create a new stream"));
goto cleanup;
}
const char *name = NULL;
unsigned long long offset = 0, length = 0;
bool created = false;
+ virshControlPtr priv = ctl->privData;
if (vshCommandOptULongLong(ctl, cmd, "offset", &offset) < 0)
return false;
if (vshCommandOptULongLongWrap(ctl, cmd, "length", &length) < 0)
return false;
- if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
+ if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0)
created = true;
}
- if (!(st = virStreamNew(ctl->conn, 0))) {
+ if (!(st = virStreamNew(priv->conn, 0))) {
vshError(ctl, _("cannot create a new stream"));
goto cleanup;
}
goto cleanup;
}
- if (virStreamRecvAll(st, vshStreamSink, &fd) < 0) {
+ if (virStreamRecvAll(st, virshStreamSink, &fd) < 0) {
vshError(ctl, _("cannot receive data from volume %s"), name);
goto cleanup;
}
bool ret = true;
const char *name;
- if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
+ if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
return false;
if (virStorageVolDelete(vol, 0) == 0) {
int algorithm = VIR_STORAGE_VOL_WIPE_ALG_ZERO;
int funcRet;
- if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
+ if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "algorithm", &algorithm_str) < 0)
}
-VIR_ENUM_DECL(vshStorageVol)
-VIR_ENUM_IMPL(vshStorageVol,
+VIR_ENUM_DECL(virshStorageVol)
+VIR_ENUM_IMPL(virshStorageVol,
VIR_STORAGE_VOL_LAST,
N_("file"),
N_("block"),
N_("netdir"))
static const char *
-vshVolumeTypeToString(int type)
+virshVolumeTypeToString(int type)
{
- const char *str = vshStorageVolTypeToString(type);
+ const char *str = virshStorageVolTypeToString(type);
return str ? _(str) : _("unknown");
}
virStorageVolPtr vol;
bool ret = true;
- if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+ if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
return false;
vshPrint(ctl, "%-15s %s\n", _("Name:"), virStorageVolGetName(vol));
const char *unit;
vshPrint(ctl, "%-15s %s\n", _("Type:"),
- vshVolumeTypeToString(info.type));
+ virshVolumeTypeToString(info.type));
val = vshPrettyCapacity(info.capacity, &unit);
vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
if (vshCommandOptBool(cmd, "shrink"))
flags |= VIR_STORAGE_VOL_RESIZE_SHRINK;
- if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+ if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
return false;
if (vshCommandOptStringReq(ctl, cmd, "capacity", &capacityStr) < 0)
if (delta)
flags |= VIR_STORAGE_VOL_RESIZE_DELTA;
- if (vshVolSize(capacityStr, &capacity) < 0) {
+ if (virshVolSize(capacityStr, &capacity) < 0) {
vshError(ctl, _("Malformed size %s"), capacityStr);
goto cleanup;
}
bool ret = true;
char *dump;
- if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+ if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
return false;
dump = virStorageVolGetXMLDesc(vol, 0);
}
static int
-vshStorageVolSorter(const void *a, const void *b)
+virshStorageVolSorter(const void *a, const void *b)
{
virStorageVolPtr *va = (virStorageVolPtr *) a;
virStorageVolPtr *vb = (virStorageVolPtr *) b;
virStorageVolGetName(*vb));
}
-struct vshStorageVolList {
+struct virshStorageVolList {
virStorageVolPtr *vols;
size_t nvols;
};
-typedef struct vshStorageVolList *vshStorageVolListPtr;
+typedef struct virshStorageVolList *virshStorageVolListPtr;
static void
-vshStorageVolListFree(vshStorageVolListPtr list)
+virshStorageVolListFree(virshStorageVolListPtr list)
{
size_t i;
VIR_FREE(list);
}
-static vshStorageVolListPtr
-vshStorageVolListCollect(vshControl *ctl,
- virStoragePoolPtr pool,
- unsigned int flags)
+static virshStorageVolListPtr
+virshStorageVolListCollect(vshControl *ctl,
+ virStoragePoolPtr pool,
+ unsigned int flags)
{
- vshStorageVolListPtr list = vshMalloc(ctl, sizeof(*list));
+ virshStorageVolListPtr list = vshMalloc(ctl, sizeof(*list));
size_t i;
char **names = NULL;
virStorageVolPtr vol = NULL;
finished:
/* sort the list */
if (list->vols && list->nvols)
- qsort(list->vols, list->nvols, sizeof(*list->vols), vshStorageVolSorter);
+ qsort(list->vols, list->nvols, sizeof(*list->vols), virshStorageVolSorter);
if (deleted)
VIR_SHRINK_N(list->vols, list->nvols, deleted);
VIR_FREE(names);
if (!success) {
- vshStorageVolListFree(list);
+ virshStorageVolListFree(list);
list = NULL;
}
char *type;
};
struct volInfoText *volInfoTexts = NULL;
- vshStorageVolListPtr list = NULL;
+ virshStorageVolListPtr list = NULL;
/* Look up the pool information given to us by the user */
- if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+ if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL)))
return false;
- if (!(list = vshStorageVolListCollect(ctl, pool, 0)))
+ if (!(list = virshStorageVolListCollect(ctl, pool, 0)))
goto cleanup;
if (list->nvols > 0)
/* Volume type */
volInfoTexts[i].type = vshStrdup(ctl,
- vshVolumeTypeToString(volumeInfo.type));
+ virshVolumeTypeToString(volumeInfo.type));
val = vshPrettyCapacity(volumeInfo.capacity, &unit);
if (virAsprintf(&volInfoTexts[i].capacity,
VIR_FREE(outputStr);
VIR_FREE(volInfoTexts);
virStoragePoolFree(pool);
- vshStorageVolListFree(list);
+ virshStorageVolListFree(list);
/* Return the desired value */
return ret;
{
virStorageVolPtr vol;
- if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
- VSH_BYUUID)))
+ if (!(vol = virshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
+ VIRSH_BYUUID)))
return false;
vshPrint(ctl, "%s\n", virStorageVolGetName(vol));
char uuid[VIR_UUID_STRING_BUFLEN];
/* Use the supplied string to locate the volume */
- if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
- VSH_BYUUID))) {
+ if (!(vol = virshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
+ VIRSH_BYUUID))) {
return false;
}
{
virStorageVolPtr vol;
- if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+ if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
return false;
vshPrint(ctl, "%s\n", virStorageVolGetKey(vol));
virStorageVolPtr vol;
char * StorageVolPath;
- if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+ if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
return false;
if ((StorageVolPath = virStorageVolGetPath(vol)) == NULL) {
# include "virsh.h"
-virStorageVolPtr vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
- const char *optname,
- const char *pooloptname,
- const char **name, unsigned int flags);
+virStorageVolPtr virshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
+ const char *optname,
+ const char *pooloptname,
+ const char **name, unsigned int flags);
/* default is lookup by Name and UUID */
-# define vshCommandOptVol(_ctl, _cmd, _optname, _pooloptname, _name) \
- vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \
- VSH_BYUUID|VSH_BYNAME)
+# define virshCommandOptVol(_ctl, _cmd, _optname, _pooloptname, _name) \
+ virshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \
+ VIRSH_BYUUID | VIRSH_BYNAME)
extern const vshCmdDef storageVolCmds[];
#include <config.h>
#include "virsh.h"
-#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <sys/time.h>
-#include "c-ctype.h"
#include <fcntl.h>
#include <locale.h>
#include <time.h>
#include <limits.h>
#include <sys/stat.h>
#include <inttypes.h>
-#include <strings.h>
#include <signal.h>
#if WITH_READLINE
static char *progname;
static const vshCmdGrp cmdGroups[];
-
-/* Bypass header poison */
-#undef strdup
-
-void *
-_vshMalloc(vshControl *ctl, size_t size, const char *filename, int line)
-{
- char *x;
-
- if (VIR_ALLOC_N(x, size) == 0)
- return x;
- vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
- filename, line, (int) size);
- exit(EXIT_FAILURE);
-}
-
-void *
-_vshCalloc(vshControl *ctl, size_t nmemb, size_t size, const char *filename,
- int line)
-{
- char *x;
-
- if (!xalloc_oversized(nmemb, size) &&
- VIR_ALLOC_N(x, nmemb * size) == 0)
- return x;
- vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
- filename, line, (int) (size*nmemb));
- exit(EXIT_FAILURE);
-}
-
-char *
-_vshStrdup(vshControl *ctl, const char *s, const char *filename, int line)
-{
- char *x;
-
- if (VIR_STRDUP(x, s) >= 0)
- return x;
- vshError(ctl, _("%s: %d: failed to allocate %lu bytes"),
- filename, line, (unsigned long)strlen(s));
- exit(EXIT_FAILURE);
-}
-
-/* Poison the raw allocating identifiers in favor of our vsh variants. */
-#define strdup use_vshStrdup_instead_of_strdup
-
-int
-vshNameSorter(const void *a, const void *b)
-{
- const char **sa = (const char**)a;
- const char **sb = (const char**)b;
-
- return vshStrcasecmp(*sa, *sb);
-}
-
-double
-vshPrettyCapacity(unsigned long long val, const char **unit)
-{
- double limit = 1024;
-
- if (val < limit) {
- *unit = "B";
- return val;
- }
- limit *= 1024;
- if (val < limit) {
- *unit = "KiB";
- return val / (limit / 1024);
- }
- limit *= 1024;
- if (val < limit) {
- *unit = "MiB";
- return val / (limit / 1024);
- }
- limit *= 1024;
- if (val < limit) {
- *unit = "GiB";
- return val / (limit / 1024);
- }
- limit *= 1024;
- if (val < limit) {
- *unit = "TiB";
- return val / (limit / 1024);
- }
- limit *= 1024;
- if (val < limit) {
- *unit = "PiB";
- return val / (limit / 1024);
- }
- limit *= 1024;
- *unit = "EiB";
- return val / (limit / 1024);
-}
-
-/*
- * Convert the strings separated by ',' into array. The returned
- * array is a NULL terminated string list. The caller has to free
- * the array using virStringFreeList or a similar method.
- *
- * Returns the length of the filled array on success, or -1
- * on error.
- */
-int
-vshStringToArray(const char *str,
- char ***array)
-{
- char *str_copied = vshStrdup(NULL, str);
- char *str_tok = NULL;
- char *tmp;
- unsigned int nstr_tokens = 0;
- char **arr = NULL;
- size_t len = strlen(str_copied);
-
- /* tokenize the string from user and save its parts into an array */
- nstr_tokens = 1;
-
- /* count the delimiters, recognizing ,, as an escape for a
- * literal comma */
- str_tok = str_copied;
- while ((str_tok = strchr(str_tok, ','))) {
- if (str_tok[1] == ',')
- str_tok++;
- else
- nstr_tokens++;
- str_tok++;
- }
-
- /* reserve the NULL element at the end */
- if (VIR_ALLOC_N(arr, nstr_tokens + 1) < 0) {
- VIR_FREE(str_copied);
- return -1;
- }
-
- /* tokenize the input string, while treating ,, as a literal comma */
- nstr_tokens = 0;
- tmp = str_tok = str_copied;
- while ((tmp = strchr(tmp, ','))) {
- if (tmp[1] == ',') {
- memmove(&tmp[1], &tmp[2], len - (tmp - str_copied) - 2 + 1);
- len--;
- tmp++;
- continue;
- }
- *tmp++ = '\0';
- arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
- str_tok = tmp;
- }
- arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
-
- *array = arr;
- VIR_FREE(str_copied);
- return nstr_tokens;
-}
-
-virErrorPtr last_error;
-
-/*
- * Quieten libvirt until we're done with the command.
- */
-static void
-virshErrorHandler(void *unused ATTRIBUTE_UNUSED, virErrorPtr error)
-{
- virFreeError(last_error);
- last_error = virSaveLastError();
- if (virGetEnvAllowSUID("VIRSH_DEBUG") != NULL)
- virDefaultErrorFunc(error);
-}
-
-/* Store a libvirt error that is from a helper API that doesn't raise errors
- * so it doesn't get overwritten */
-void
-vshSaveLibvirtError(void)
-{
- virFreeError(last_error);
- last_error = virSaveLastError();
-}
-
-/*
- * Reset libvirt error on graceful fallback paths
- */
-void
-vshResetLibvirtError(void)
-{
- virFreeError(last_error);
- last_error = NULL;
-}
-
-/*
- * Report an error when a command finishes. This is better than before
- * (when correct operation would report errors), but it has some
- * problems: we lose the smarter formatting of virDefaultErrorFunc(),
- * and it can become harder to debug problems, if errors get reported
- * twice during one command. This case shouldn't really happen anyway,
- * and it's IMHO a bug that libvirt does that sometimes.
- */
-void
-vshReportError(vshControl *ctl)
-{
- if (last_error == NULL) {
- /* Calling directly into libvirt util functions won't trigger the
- * error callback (which sets last_error), so check it ourselves.
- *
- * If the returned error has CODE_OK, this most likely means that
- * no error was ever raised, so just ignore */
- last_error = virSaveLastError();
- if (!last_error || last_error->code == VIR_ERR_OK)
- goto out;
- }
-
- if (last_error->code == VIR_ERR_OK) {
- vshError(ctl, "%s", _("unknown error"));
- goto out;
- }
-
- vshError(ctl, "%s", last_error->message);
-
- out:
- vshResetLibvirtError();
-}
+static const vshClientHooks hooks;
/*
* Detection of disconnections and automatic reconnection support
static int disconnected; /* we may have been disconnected */
/*
- * vshCatchDisconnect:
+ * virshCatchDisconnect:
*
* We get here when the connection was closed. We can't do much in the
* handler, just save the fact it was raised.
*/
static void
-vshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED,
- int reason,
- void *opaque ATTRIBUTE_UNUSED)
+virshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED,
+ int reason,
+ void *opaque ATTRIBUTE_UNUSED)
{
if (reason != VIR_CONNECT_CLOSE_REASON_CLIENT)
disconnected++;
/* Main Function which should be used for connecting.
* This function properly handles keepalive settings. */
virConnectPtr
-vshConnect(vshControl *ctl, const char *uri, bool readonly)
+virshConnect(vshControl *ctl, const char *uri, bool readonly)
{
virConnectPtr c = NULL;
int interval = 5; /* Default */
}
/*
- * vshReconnect:
+ * virshReconnect:
*
* Reconnect after a disconnect from libvirtd
*
*/
static void
-vshReconnect(vshControl *ctl)
+virshReconnect(vshControl *ctl)
{
bool connected = false;
+ virshControlPtr priv = ctl->privData;
- if (ctl->conn) {
+ if (priv->conn) {
int ret;
-
connected = true;
- virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect);
- ret = virConnectClose(ctl->conn);
+ virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect);
+ ret = virConnectClose(priv->conn);
if (ret < 0)
vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
else if (ret > 0)
"disconnect from the hypervisor"));
}
- ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly);
+ priv->conn = virshConnect(ctl, ctl->connname, priv->readonly);
- if (!ctl->conn) {
+ if (!priv->conn) {
if (disconnected)
vshError(ctl, "%s", _("Failed to reconnect to the hypervisor"));
else
vshError(ctl, "%s", _("failed to connect to the hypervisor"));
} else {
- if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect,
+ if (virConnectRegisterCloseCallback(priv->conn, virshCatchDisconnect,
NULL, NULL) < 0)
vshError(ctl, "%s", _("Unable to register disconnect callback"));
if (connected)
vshError(ctl, "%s", _("Reconnected to the hypervisor"));
}
disconnected = 0;
- ctl->useGetInfo = false;
- ctl->useSnapshotOld = false;
- ctl->blockJobNoBytes = false;
+ priv->useGetInfo = false;
+ priv->useSnapshotOld = false;
+ priv->blockJobNoBytes = false;
}
+int virshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED,
+ const char *bytes, size_t nbytes, void *opaque)
+{
+ int *fd = opaque;
+
+ return safewrite(*fd, bytes, nbytes);
+}
-/*
- * "connect" command
+/* ---------------
+ * Command Connect
+ * ---------------
*/
-static const vshCmdInfo info_connect[] = {
- {.name = "help",
- .data = N_("(re)connect to hypervisor")
- },
- {.name = "desc",
- .data = N_("Connect to local hypervisor. This is built-in "
- "command after shell start up.")
- },
- {.name = NULL}
-};
static const vshCmdOptDef opts_connect[] = {
{.name = "name",
{.name = NULL}
};
-static bool
-cmdConnect(vshControl *ctl, const vshCmd *cmd)
-{
- bool ro = vshCommandOptBool(cmd, "readonly");
- const char *name = NULL;
-
- if (ctl->conn) {
- int ret;
-
- virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect);
- ret = virConnectClose(ctl->conn);
- if (ret < 0)
- vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
- else if (ret > 0)
- vshError(ctl, "%s", _("One or more references were leaked after "
- "disconnect from the hypervisor"));
- ctl->conn = NULL;
- }
-
- VIR_FREE(ctl->name);
- if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0)
- return false;
-
- ctl->name = vshStrdup(ctl, name);
-
- ctl->useGetInfo = false;
- ctl->useSnapshotOld = false;
- ctl->blockJobNoBytes = false;
- ctl->readonly = ro;
-
- ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly);
-
- if (!ctl->conn) {
- vshError(ctl, "%s", _("Failed to connect to the hypervisor"));
- return false;
- }
-
- if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect,
- NULL, NULL) < 0)
- vshError(ctl, "%s", _("Unable to register disconnect callback"));
-
- return true;
-}
-
-
-#ifndef WIN32
-static void
-vshPrintRaw(vshControl *ctl, ...)
-{
- va_list ap;
- char *key;
-
- va_start(ap, ctl);
- while ((key = va_arg(ap, char *)) != NULL)
- vshPrint(ctl, "%s\r\n", key);
- va_end(ap);
-}
-
-/**
- * vshAskReedit:
- * @msg: Question to ask user
- *
- * Ask user if he wants to return to previously
- * edited file.
- *
- * Returns 'y' if he wants to
- * 'n' if he doesn't want to
- * 'i' if he wants to try defining it again while ignoring validation
- * 'f' if he forcibly wants to
- * -1 on error
- * 0 otherwise
- */
-int
-vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail)
-{
- int c = -1;
-
- if (!isatty(STDIN_FILENO))
- return -1;
-
- vshReportError(ctl);
-
- if (vshTTYMakeRaw(ctl, false) < 0)
- return -1;
-
- while (true) {
- vshPrint(ctl, "\r%s %s %s: ", msg, _("Try again?"),
- relax_avail ? "[y,n,i,f,?]" : "[y,n,f,?]");
- c = c_tolower(getchar());
-
- if (c == '?') {
- vshPrintRaw(ctl,
- "",
- _("y - yes, start editor again"),
- _("n - no, throw away my changes"),
- NULL);
-
- if (relax_avail) {
- vshPrintRaw(ctl,
- _("i - turn off validation and try to redefine again"),
- NULL);
- }
-
- vshPrintRaw(ctl,
- _("f - force, try to redefine again"),
- _("? - print this help"),
- NULL);
- continue;
- } else if (c == 'y' || c == 'n' || c == 'f' ||
- (relax_avail && c == 'i')) {
- break;
- }
- }
-
- vshTTYRestore(ctl);
-
- vshPrint(ctl, "\r\n");
- return c;
-}
-#else /* WIN32 */
-int
-vshAskReedit(vshControl *ctl,
- const char *msg ATTRIBUTE_UNUSED,
- bool relax_avail ATTRIBUTE_UNUSED)
-{
- vshDebug(ctl, VSH_ERR_WARNING, "%s", _("This function is not "
- "supported on WIN32 platform"));
- return 0;
-}
-#endif /* WIN32 */
-
-int vshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED,
- const char *bytes, size_t nbytes, void *opaque)
-{
- int *fd = opaque;
-
- return safewrite(*fd, bytes, nbytes);
-}
-
-/* ---------------
- * Commands
- * ---------------
- */
-
-/*
- * "help" command
- */
-static const vshCmdInfo info_help[] = {
- {.name = "help",
- .data = N_("print help")
- },
- {.name = "desc",
- .data = N_("Prints global help, command specific help, or help for a\n"
- " group of related commands")
- },
- {.name = NULL}
-};
-
-static const vshCmdOptDef opts_help[] = {
- {.name = "command",
- .type = VSH_OT_STRING,
- .help = N_("Prints global help, command specific help, or help for a group of related commands")
- },
- {.name = NULL}
-};
-
-static bool
-cmdHelp(vshControl *ctl, const vshCmd *cmd)
- {
- const char *name = NULL;
-
- if (vshCommandOptString(ctl, cmd, "command", &name) <= 0) {
- const vshCmdGrp *grp;
- const vshCmdDef *def;
-
- vshPrint(ctl, "%s", _("Grouped commands:\n\n"));
-
- for (grp = cmdGroups; grp->name; grp++) {
- vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
- grp->keyword);
-
- for (def = grp->commands; def->name; def++) {
- if (def->flags & VSH_CMD_FLAG_ALIAS)
- continue;
- vshPrint(ctl, " %-30s %s\n", def->name,
- _(vshCmddefGetInfo(def, "help")));
- }
-
- vshPrint(ctl, "\n");
- }
-
- return true;
- }
-
- if (vshCmddefSearch(name)) {
- return vshCmddefHelp(ctl, name);
- } else if (vshCmdGrpSearch(name)) {
- return vshCmdGrpHelp(ctl, name);
- } else {
- vshError(ctl, _("command or command group '%s' doesn't exist"), name);
- return false;
- }
-}
-
-/* Tree listing helpers. */
-
-static int
-vshTreePrintInternal(vshControl *ctl,
- vshTreeLookup lookup,
- void *opaque,
- int num_devices,
- int devid,
- int lastdev,
- bool root,
- virBufferPtr indent)
-{
- size_t i;
- int nextlastdev = -1;
- int ret = -1;
- const char *dev = (lookup)(devid, false, opaque);
-
- if (virBufferError(indent))
- goto cleanup;
-
- /* Print this device, with indent if not at root */
- vshPrint(ctl, "%s%s%s\n", virBufferCurrentContent(indent),
- root ? "" : "+- ", dev);
-
- /* Update indent to show '|' or ' ' for child devices */
- if (!root) {
- virBufferAddChar(indent, devid == lastdev ? ' ' : '|');
- virBufferAddChar(indent, ' ');
- if (virBufferError(indent))
- goto cleanup;
- }
-
- /* Determine the index of the last child device */
- for (i = 0; i < num_devices; i++) {
- const char *parent = (lookup)(i, true, opaque);
-
- if (parent && STREQ(parent, dev))
- nextlastdev = i;
- }
-
- /* If there is a child device, then print another blank line */
- if (nextlastdev != -1)
- vshPrint(ctl, "%s |\n", virBufferCurrentContent(indent));
-
- /* Finally print all children */
- virBufferAddLit(indent, " ");
- if (virBufferError(indent))
- goto cleanup;
- for (i = 0; i < num_devices; i++) {
- const char *parent = (lookup)(i, true, opaque);
-
- if (parent && STREQ(parent, dev) &&
- vshTreePrintInternal(ctl, lookup, opaque,
- num_devices, i, nextlastdev,
- false, indent) < 0)
- goto cleanup;
- }
- virBufferTrim(indent, " ", -1);
-
- /* If there was no child device, and we're the last in
- * a list of devices, then print another blank line */
- if (nextlastdev == -1 && devid == lastdev)
- vshPrint(ctl, "%s\n", virBufferCurrentContent(indent));
-
- if (!root)
- virBufferTrim(indent, NULL, 2);
- ret = 0;
- cleanup:
- return ret;
-}
-
-int
-vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
- int num_devices, int devid)
-{
- int ret;
- virBuffer indent = VIR_BUFFER_INITIALIZER;
-
- ret = vshTreePrintInternal(ctl, lookup, opaque, num_devices,
- devid, devid, true, &indent);
- if (ret < 0)
- vshError(ctl, "%s", _("Failed to complete tree listing"));
- virBufferFreeAndReset(&indent);
- return ret;
-}
-
-/* Common code for the edit / net-edit / pool-edit functions which follow. */
-char *
-vshEditWriteToTempFile(vshControl *ctl, const char *doc)
-{
- char *ret;
- const char *tmpdir;
- int fd;
- char ebuf[1024];
-
- tmpdir = virGetEnvBlockSUID("TMPDIR");
- if (!tmpdir) tmpdir = "/tmp";
- if (virAsprintf(&ret, "%s/virshXXXXXX.xml", tmpdir) < 0) {
- vshError(ctl, "%s", _("out of memory"));
- return NULL;
- }
- fd = mkostemps(ret, 4, O_CLOEXEC);
- if (fd == -1) {
- vshError(ctl, _("mkostemps: failed to create temporary file: %s"),
- virStrerror(errno, ebuf, sizeof(ebuf)));
- VIR_FREE(ret);
- return NULL;
- }
-
- if (safewrite(fd, doc, strlen(doc)) == -1) {
- vshError(ctl, _("write: %s: failed to write to temporary file: %s"),
- ret, virStrerror(errno, ebuf, sizeof(ebuf)));
- VIR_FORCE_CLOSE(fd);
- unlink(ret);
- VIR_FREE(ret);
- return NULL;
- }
- if (VIR_CLOSE(fd) < 0) {
- vshError(ctl, _("close: %s: failed to write or close temporary file: %s"),
- ret, virStrerror(errno, ebuf, sizeof(ebuf)));
- unlink(ret);
- VIR_FREE(ret);
- return NULL;
- }
-
- /* Temporary filename: caller frees. */
- return ret;
-}
-
-/* Characters permitted in $EDITOR environment variable and temp filename. */
-#define ACCEPTED_CHARS \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@"
-
-int
-vshEditFile(vshControl *ctl, const char *filename)
-{
- const char *editor;
- virCommandPtr cmd;
- int ret = -1;
- int outfd = STDOUT_FILENO;
- int errfd = STDERR_FILENO;
-
- editor = virGetEnvBlockSUID("VISUAL");
- if (!editor)
- editor = virGetEnvBlockSUID("EDITOR");
- if (!editor)
- editor = DEFAULT_EDITOR;
-
- /* Check that filename doesn't contain shell meta-characters, and
- * if it does, refuse to run. Follow the Unix conventions for
- * EDITOR: the user can intentionally specify command options, so
- * we don't protect any shell metacharacters there. Lots more
- * than virsh will misbehave if EDITOR has bogus contents (which
- * is why sudo scrubs it by default). Conversely, if the editor
- * is safe, we can run it directly rather than wasting a shell.
- */
- if (strspn(editor, ACCEPTED_CHARS) != strlen(editor)) {
- if (strspn(filename, ACCEPTED_CHARS) != strlen(filename)) {
- vshError(ctl,
- _("%s: temporary filename contains shell meta or other "
- "unacceptable characters (is $TMPDIR wrong?)"),
- filename);
- return -1;
- }
- cmd = virCommandNewArgList("sh", "-c", NULL);
- virCommandAddArgFormat(cmd, "%s %s", editor, filename);
- } else {
- cmd = virCommandNewArgList(editor, filename, NULL);
- }
-
- virCommandSetInputFD(cmd, STDIN_FILENO);
- virCommandSetOutputFD(cmd, &outfd);
- virCommandSetErrorFD(cmd, &errfd);
- if (virCommandRunAsync(cmd, NULL) < 0 ||
- virCommandWait(cmd, NULL) < 0) {
- vshReportError(ctl);
- goto cleanup;
- }
- ret = 0;
-
- cleanup:
- virCommandFree(cmd);
- return ret;
-}
-
-char *
-vshEditReadBackFile(vshControl *ctl, const char *filename)
-{
- char *ret;
- char ebuf[1024];
-
- if (virFileReadAll(filename, VSH_MAX_XML_FILE, &ret) == -1) {
- vshError(ctl,
- _("%s: failed to read temporary file: %s"),
- filename, virStrerror(errno, ebuf, sizeof(ebuf)));
- return NULL;
- }
- return ret;
-}
-
-
-/*
- * "cd" command
- */
-static const vshCmdInfo info_cd[] = {
+static const vshCmdInfo info_connect[] = {
{.name = "help",
- .data = N_("change the current directory")
+ .data = N_("(re)connect to hypervisor")
},
{.name = "desc",
- .data = N_("Change the current directory.")
- },
- {.name = NULL}
-};
-
-static const vshCmdOptDef opts_cd[] = {
- {.name = "dir",
- .type = VSH_OT_STRING,
- .help = N_("directory to switch to (default: home or else root)")
+ .data = N_("Connect to local hypervisor. This is built-in "
+ "command after shell start up.")
},
{.name = NULL}
};
static bool
-cmdCd(vshControl *ctl, const vshCmd *cmd)
+cmdConnect(vshControl *ctl, const vshCmd *cmd)
{
- const char *dir = NULL;
- char *dir_malloced = NULL;
- bool ret = true;
- char ebuf[1024];
+ bool ro = vshCommandOptBool(cmd, "readonly");
+ const char *name = NULL;
+ virshControlPtr priv = ctl->privData;
- if (!ctl->imode) {
- vshError(ctl, "%s", _("cd: command valid only in interactive mode"));
- return false;
- }
-
- if (vshCommandOptString(ctl, cmd, "dir", &dir) <= 0)
- dir = dir_malloced = virGetUserDirectory();
- if (!dir)
- dir = "/";
-
- if (chdir(dir) == -1) {
- vshError(ctl, _("cd: %s: %s"),
- virStrerror(errno, ebuf, sizeof(ebuf)), dir);
- ret = false;
- }
-
- VIR_FREE(dir_malloced);
- return ret;
-}
-
-/*
- * "pwd" command
- */
-static const vshCmdInfo info_pwd[] = {
- {.name = "help",
- .data = N_("print the current directory")
- },
- {.name = "desc",
- .data = N_("Print the current directory.")
- },
- {.name = NULL}
-};
-
-static bool
-cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
-{
- char *cwd;
- bool ret = true;
- char ebuf[1024];
-
- cwd = getcwd(NULL, 0);
- if (!cwd) {
- vshError(ctl, _("pwd: cannot get current directory: %s"),
- virStrerror(errno, ebuf, sizeof(ebuf)));
- ret = false;
- } else {
- vshPrint(ctl, _("%s\n"), cwd);
- VIR_FREE(cwd);
- }
-
- return ret;
-}
-
-/*
- * "echo" command
- */
-static const vshCmdInfo info_echo[] = {
- {.name = "help",
- .data = N_("echo arguments")
- },
- {.name = "desc",
- .data = N_("Echo back arguments, possibly with quoting.")
- },
- {.name = NULL}
-};
-
-static const vshCmdOptDef opts_echo[] = {
- {.name = "shell",
- .type = VSH_OT_BOOL,
- .help = N_("escape for shell use")
- },
- {.name = "xml",
- .type = VSH_OT_BOOL,
- .help = N_("escape for XML use")
- },
- {.name = "str",
- .type = VSH_OT_ALIAS,
- .help = "string"
- },
- {.name = "hi",
- .type = VSH_OT_ALIAS,
- .help = "string=hello"
- },
- {.name = "string",
- .type = VSH_OT_ARGV,
- .help = N_("arguments to echo")
- },
- {.name = NULL}
-};
-
-/* Exists mainly for debugging virsh, but also handy for adding back
- * quotes for later evaluation.
- */
-static bool
-cmdEcho(vshControl *ctl, const vshCmd *cmd)
-{
- bool shell = false;
- bool xml = false;
- int count = 0;
- const vshCmdOpt *opt = NULL;
- char *arg;
- virBuffer buf = VIR_BUFFER_INITIALIZER;
-
- if (vshCommandOptBool(cmd, "shell"))
- shell = true;
- if (vshCommandOptBool(cmd, "xml"))
- xml = true;
-
- while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
- char *str;
- virBuffer xmlbuf = VIR_BUFFER_INITIALIZER;
-
- arg = opt->data;
-
- if (count)
- virBufferAddChar(&buf, ' ');
-
- if (xml) {
- virBufferEscapeString(&xmlbuf, "%s", arg);
- if (virBufferError(&xmlbuf)) {
- vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
- return false;
- }
- str = virBufferContentAndReset(&xmlbuf);
- } else {
- str = vshStrdup(ctl, arg);
- }
-
- if (shell)
- virBufferEscapeShell(&buf, str);
- else
- virBufferAdd(&buf, str, -1);
- count++;
- VIR_FREE(str);
- }
-
- if (virBufferError(&buf)) {
- vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
- return false;
- }
- arg = virBufferContentAndReset(&buf);
- if (arg)
- vshPrint(ctl, "%s", arg);
- VIR_FREE(arg);
- return true;
-}
-
-/*
- * "quit" command
- */
-static const vshCmdInfo info_quit[] = {
- {.name = "help",
- .data = N_("quit this interactive terminal")
- },
- {.name = "desc",
- .data = ""
- },
- {.name = NULL}
-};
-
-static bool
-cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
-{
- ctl->imode = false;
- return true;
-}
-
-/* ---------------
- * Utils for work with command definition
- * ---------------
- */
-const char *
-vshCmddefGetInfo(const vshCmdDef * cmd, const char *name)
-{
- const vshCmdInfo *info;
-
- for (info = cmd->info; info && info->name; info++) {
- if (STREQ(info->name, name))
- return info->data;
- }
- return NULL;
-}
-
-/* Validate that the options associated with cmd can be parsed. */
-static int
-vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg,
- uint32_t *opts_required)
-{
- size_t i;
- bool optional = false;
-
- *opts_need_arg = 0;
- *opts_required = 0;
-
- if (!cmd->opts)
- return 0;
-
- for (i = 0; cmd->opts[i].name; i++) {
- const vshCmdOptDef *opt = &cmd->opts[i];
-
- if (i > 31)
- return -1; /* too many options */
- if (opt->type == VSH_OT_BOOL) {
- optional = true;
- if (opt->flags & VSH_OFLAG_REQ)
- return -1; /* bool options can't be mandatory */
- continue;
- }
- if (opt->type == VSH_OT_ALIAS) {
- size_t j;
- char *name = (char *)opt->help; /* cast away const */
- char *p;
-
- if (opt->flags || !opt->help)
- return -1; /* alias options are tracked by the original name */
- if ((p = strchr(name, '=')) &&
- VIR_STRNDUP(name, name, p - name) < 0)
- return -1;
- for (j = i + 1; cmd->opts[j].name; j++) {
- if (STREQ(name, cmd->opts[j].name) &&
- cmd->opts[j].type != VSH_OT_ALIAS)
- break;
- }
- if (name != opt->help) {
- VIR_FREE(name);
- /* If alias comes with value, replacement must not be bool */
- if (cmd->opts[j].type == VSH_OT_BOOL)
- return -1;
- }
- if (!cmd->opts[j].name)
- return -1; /* alias option must map to a later option name */
- continue;
- }
- if (opt->flags & VSH_OFLAG_REQ_OPT) {
- if (opt->flags & VSH_OFLAG_REQ)
- *opts_required |= 1 << i;
- else
- optional = true;
- continue;
- }
-
- *opts_need_arg |= 1 << i;
- if (opt->flags & VSH_OFLAG_REQ) {
- if (optional && opt->type != VSH_OT_ARGV)
- return -1; /* mandatory options must be listed first */
- *opts_required |= 1 << i;
- } else {
- optional = true;
- }
-
- if (opt->type == VSH_OT_ARGV && cmd->opts[i + 1].name)
- return -1; /* argv option must be listed last */
- }
- return 0;
-}
-
-static vshCmdOptDef helpopt = {
- .name = "help",
- .type = VSH_OT_BOOL,
- .help = N_("print help for this function")
-};
-static const vshCmdOptDef *
-vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
- uint32_t *opts_seen, int *opt_index, char **optstr)
-{
- size_t i;
- const vshCmdOptDef *ret = NULL;
- char *alias = NULL;
-
- if (STREQ(name, helpopt.name))
- return &helpopt;
-
- for (i = 0; cmd->opts && cmd->opts[i].name; i++) {
- const vshCmdOptDef *opt = &cmd->opts[i];
-
- if (STREQ(opt->name, name)) {
- if (opt->type == VSH_OT_ALIAS) {
- char *value;
-
- /* Two types of replacements:
- opt->help = "string": straight replacement of name
- opt->help = "string=value": treat boolean flag as
- alias of option and its default value */
- sa_assert(!alias);
- if (VIR_STRDUP(alias, opt->help) < 0)
- goto cleanup;
- name = alias;
- if ((value = strchr(name, '='))) {
- *value = '\0';
- if (*optstr) {
- vshError(ctl, _("invalid '=' after option --%s"),
- opt->name);
- goto cleanup;
- }
- if (VIR_STRDUP(*optstr, value + 1) < 0)
- goto cleanup;
- }
- continue;
- }
- if ((*opts_seen & (1 << i)) && opt->type != VSH_OT_ARGV) {
- vshError(ctl, _("option --%s already seen"), name);
- goto cleanup;
- }
- *opts_seen |= 1 << i;
- *opt_index = i;
- ret = opt;
- goto cleanup;
- }
- }
-
- if (STRNEQ(cmd->name, "help")) {
- vshError(ctl, _("command '%s' doesn't support option --%s"),
- cmd->name, name);
- }
- cleanup:
- VIR_FREE(alias);
- return ret;
-}
-
-static const vshCmdOptDef *
-vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg,
- uint32_t *opts_seen)
-{
- size_t i;
- const vshCmdOptDef *opt;
-
- if (!*opts_need_arg)
- return NULL;
-
- /* Grab least-significant set bit */
- i = ffs(*opts_need_arg) - 1;
- opt = &cmd->opts[i];
- if (opt->type != VSH_OT_ARGV)
- *opts_need_arg &= ~(1 << i);
- *opts_seen |= 1 << i;
- return opt;
-}
-
-/*
- * Checks for required options
- */
-static int
-vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required,
- uint32_t opts_seen)
-{
- const vshCmdDef *def = cmd->def;
- size_t i;
-
- opts_required &= ~opts_seen;
- if (!opts_required)
- return 0;
-
- for (i = 0; def->opts[i].name; i++) {
- if (opts_required & (1 << i)) {
- const vshCmdOptDef *opt = &def->opts[i];
-
- vshError(ctl,
- opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV ?
- _("command '%s' requires <%s> option") :
- _("command '%s' requires --%s option"),
- def->name, opt->name);
- }
- }
- return -1;
-}
-
-const vshCmdDef *
-vshCmddefSearch(const char *cmdname)
-{
- const vshCmdGrp *g;
- const vshCmdDef *c;
-
- for (g = cmdGroups; g->name; g++) {
- for (c = g->commands; c->name; c++) {
- if (STREQ(c->name, cmdname))
- return c;
- }
- }
-
- return NULL;
-}
-
-const vshCmdGrp *
-vshCmdGrpSearch(const char *grpname)
-{
- const vshCmdGrp *g;
-
- for (g = cmdGroups; g->name; g++) {
- if (STREQ(g->name, grpname) || STREQ(g->keyword, grpname))
- return g;
- }
-
- return NULL;
-}
-
-bool
-vshCmdGrpHelp(vshControl *ctl, const char *grpname)
-{
- const vshCmdGrp *grp = vshCmdGrpSearch(grpname);
- const vshCmdDef *cmd = NULL;
-
- if (!grp) {
- vshError(ctl, _("command group '%s' doesn't exist"), grpname);
- return false;
- } else {
- vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
- grp->keyword);
-
- for (cmd = grp->commands; cmd->name; cmd++) {
- if (cmd->flags & VSH_CMD_FLAG_ALIAS)
- continue;
- vshPrint(ctl, " %-30s %s\n", cmd->name,
- _(vshCmddefGetInfo(cmd, "help")));
- }
- }
-
- return true;
-}
-
-bool
-vshCmddefHelp(vshControl *ctl, const char *cmdname)
-{
- const vshCmdDef *def = vshCmddefSearch(cmdname);
-
- if (!def) {
- vshError(ctl, _("command '%s' doesn't exist"), cmdname);
- return false;
- } else {
- /* Don't translate desc if it is "". */
- const char *desc = vshCmddefGetInfo(def, "desc");
- const char *help = _(vshCmddefGetInfo(def, "help"));
- char buf[256];
- uint32_t opts_need_arg;
- uint32_t opts_required;
- bool shortopt = false; /* true if 'arg' works instead of '--opt arg' */
-
- if (vshCmddefOptParse(def, &opts_need_arg, &opts_required)) {
- vshError(ctl, _("internal error: bad options in command: '%s'"),
- def->name);
- return false;
- }
-
- fputs(_(" NAME\n"), stdout);
- fprintf(stdout, " %s - %s\n", def->name, help);
-
- fputs(_("\n SYNOPSIS\n"), stdout);
- fprintf(stdout, " %s", def->name);
- if (def->opts) {
- const vshCmdOptDef *opt;
- for (opt = def->opts; opt->name; opt++) {
- const char *fmt = "%s";
- switch (opt->type) {
- case VSH_OT_BOOL:
- fmt = "[--%s]";
- break;
- case VSH_OT_INT:
- /* xgettext:c-format */
- fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>"
- : _("[--%s <number>]"));
- if (!(opt->flags & VSH_OFLAG_REQ_OPT))
- shortopt = true;
- break;
- case VSH_OT_STRING:
- /* xgettext:c-format */
- fmt = _("[--%s <string>]");
- if (!(opt->flags & VSH_OFLAG_REQ_OPT))
- shortopt = true;
- break;
- case VSH_OT_DATA:
- fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>" : "[<%s>]");
- if (!(opt->flags & VSH_OFLAG_REQ_OPT))
- shortopt = true;
- break;
- case VSH_OT_ARGV:
- /* xgettext:c-format */
- if (shortopt) {
- fmt = (opt->flags & VSH_OFLAG_REQ)
- ? _("{[--%s] <string>}...")
- : _("[[--%s] <string>]...");
- } else {
- fmt = (opt->flags & VSH_OFLAG_REQ) ? _("<%s>...")
- : _("[<%s>]...");
- }
- break;
- case VSH_OT_ALIAS:
- /* aliases are intentionally undocumented */
- continue;
- }
- fputc(' ', stdout);
- fprintf(stdout, fmt, opt->name);
- }
- }
- fputc('\n', stdout);
-
- if (desc[0]) {
- /* Print the description only if it's not empty. */
- fputs(_("\n DESCRIPTION\n"), stdout);
- fprintf(stdout, " %s\n", _(desc));
- }
-
- if (def->opts && def->opts->name) {
- const vshCmdOptDef *opt;
- fputs(_("\n OPTIONS\n"), stdout);
- for (opt = def->opts; opt->name; opt++) {
- switch (opt->type) {
- case VSH_OT_BOOL:
- snprintf(buf, sizeof(buf), "--%s", opt->name);
- break;
- case VSH_OT_INT:
- snprintf(buf, sizeof(buf),
- (opt->flags & VSH_OFLAG_REQ) ? _("[--%s] <number>")
- : _("--%s <number>"), opt->name);
- break;
- case VSH_OT_STRING:
- /* OT_STRING should never be VSH_OFLAG_REQ */
- if (opt->flags & VSH_OFLAG_REQ) {
- vshError(ctl,
- _("internal error: bad options in command: '%s'"),
- def->name);
- return false;
- }
- snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name);
- break;
- case VSH_OT_DATA:
- /* OT_DATA should always be VSH_OFLAG_REQ */
- if (!(opt->flags & VSH_OFLAG_REQ)) {
- vshError(ctl,
- _("internal error: bad options in command: '%s'"),
- def->name);
- return false;
- }
- snprintf(buf, sizeof(buf), _("[--%s] <string>"),
- opt->name);
- break;
- case VSH_OT_ARGV:
- snprintf(buf, sizeof(buf),
- shortopt ? _("[--%s] <string>") : _("<%s>"),
- opt->name);
- break;
- case VSH_OT_ALIAS:
- continue;
- }
-
- fprintf(stdout, " %-15s %s\n", buf, _(opt->help));
- }
- }
- fputc('\n', stdout);
- }
- return true;
-}
-
-/* ---------------
- * Utils for work with runtime commands data
- * ---------------
- */
-static void
-vshCommandOptFree(vshCmdOpt * arg)
-{
- vshCmdOpt *a = arg;
-
- while (a) {
- vshCmdOpt *tmp = a;
-
- a = a->next;
-
- VIR_FREE(tmp->data);
- VIR_FREE(tmp);
- }
-}
-
-static void
-vshCommandFree(vshCmd *cmd)
-{
- vshCmd *c = cmd;
-
- while (c) {
- vshCmd *tmp = c;
-
- c = c->next;
-
- if (tmp->opts)
- vshCommandOptFree(tmp->opts);
- VIR_FREE(tmp);
- }
-}
-
-/**
- * vshCommandOpt:
- * @cmd: parsed command line to search
- * @name: option name to search for
- * @opt: result of the search
- * @needData: true if option must be non-boolean
- *
- * Look up an option passed to CMD by NAME. Returns 1 with *OPT set
- * to the option if found, 0 with *OPT set to NULL if the name is
- * valid and the option is not required, -1 with *OPT set to NULL if
- * the option is required but not present, and assert if NAME is not
- * valid (which indicates a programming error). No error messages are
- * issued if a value is returned.
- */
-static int
-vshCommandOpt(const vshCmd *cmd, const char *name, vshCmdOpt **opt,
- bool needData)
-{
- vshCmdOpt *candidate = cmd->opts;
- const vshCmdOptDef *valid = cmd->def->opts;
- int ret = 0;
-
- /* See if option is valid and/or required. */
- *opt = NULL;
- while (valid) {
- assert(valid->name);
- if (STREQ(name, valid->name))
- break;
- valid++;
- }
- assert(!needData || valid->type != VSH_OT_BOOL);
- if (valid->flags & VSH_OFLAG_REQ)
- ret = -1;
-
- /* See if option is present on command line. */
- while (candidate) {
- if (STREQ(candidate->def->name, name)) {
- *opt = candidate;
- ret = 1;
- break;
- }
- candidate = candidate->next;
- }
- return ret;
-}
-
-/**
- * vshCommandOptInt:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- *
- * Convert option to int.
- * On error, a message is displayed.
- *
- * Return value:
- * >0 if option found and valid (@value updated)
- * 0 if option not found and not required (@value untouched)
- * <0 in all other cases (@value untouched)
- */
-int
-vshCommandOptInt(vshControl *ctl, const vshCmd *cmd,
- const char *name, int *value)
-{
- vshCmdOpt *arg;
- int ret;
-
- if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
- return ret;
-
- if ((ret = virStrToLong_i(arg->data, NULL, 10, value)) < 0)
- vshError(ctl,
- _("Numeric value '%s' for <%s> option is malformed or out of range"),
- arg->data, name);
- else
- ret = 1;
-
- return ret;
-}
-
-static int
-vshCommandOptUIntInternal(vshControl *ctl,
- const vshCmd *cmd,
- const char *name,
- unsigned int *value,
- bool wrap)
-{
- vshCmdOpt *arg;
- int ret;
-
- if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
- return ret;
-
- if (wrap)
- ret = virStrToLong_ui(arg->data, NULL, 10, value);
- else
- ret = virStrToLong_uip(arg->data, NULL, 10, value);
- if (ret < 0)
- vshError(ctl,
- _("Numeric value '%s' for <%s> option is malformed or out of range"),
- arg->data, name);
- else
- ret = 1;
-
- return ret;
-}
-
-/**
- * vshCommandOptUInt:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- *
- * Convert option to unsigned int, reject negative numbers
- * See vshCommandOptInt()
- */
-int
-vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned int *value)
-{
- return vshCommandOptUIntInternal(ctl, cmd, name, value, false);
-}
-
-/**
- * vshCommandOptUIntWrap:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- *
- * Convert option to unsigned int, wraps negative numbers to positive
- * See vshCommandOptInt()
- */
-int
-vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned int *value)
-{
- return vshCommandOptUIntInternal(ctl, cmd, name, value, true);
-}
-
-static int
-vshCommandOptULInternal(vshControl *ctl,
- const vshCmd *cmd,
- const char *name,
- unsigned long *value,
- bool wrap)
-{
- vshCmdOpt *arg;
- int ret;
-
- if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
- return ret;
-
- if (wrap)
- ret = virStrToLong_ul(arg->data, NULL, 10, value);
- else
- ret = virStrToLong_ulp(arg->data, NULL, 10, value);
- if (ret < 0)
- vshError(ctl,
- _("Numeric value '%s' for <%s> option is malformed or out of range"),
- arg->data, name);
- else
- ret = 1;
-
- return ret;
-}
-
-/*
- * vshCommandOptUL:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- *
- * Convert option to unsigned long
- * See vshCommandOptInt()
- */
-int
-vshCommandOptUL(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long *value)
-{
- return vshCommandOptULInternal(ctl, cmd, name, value, false);
-}
-
-/**
- * vshCommandOptULWrap:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- *
- * Convert option to unsigned long, wraps negative numbers to positive
- * See vshCommandOptInt()
- */
-int
-vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long *value)
-{
- return vshCommandOptULInternal(ctl, cmd, name, value, true);
-}
-
-/**
- * vshCommandOptString:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- *
- * Returns option as STRING
- * Return value:
- * >0 if option found and valid (@value updated)
- * 0 if option not found and not required (@value untouched)
- * <0 in all other cases (@value untouched)
- */
-int
-vshCommandOptString(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd,
- const char *name, const char **value)
-{
- vshCmdOpt *arg;
- int ret;
-
- if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
- return ret;
-
- if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK))
- return -1;
- *value = arg->data;
- return 1;
-}
-
-/**
- * vshCommandOptStringReq:
- * @ctl virsh control structure
- * @cmd command structure
- * @name option name
- * @value result (updated to NULL or the option argument)
- *
- * Gets a option argument as string.
- *
- * Returns 0 on success or when the option is not present and not
- * required, *value is set to the option argument. On error -1 is
- * returned and error message printed.
- */
-int
-vshCommandOptStringReq(vshControl *ctl,
- const vshCmd *cmd,
- const char *name,
- const char **value)
-{
- vshCmdOpt *arg;
- int ret;
- const char *error = NULL;
-
- /* clear out the value */
- *value = NULL;
-
- ret = vshCommandOpt(cmd, name, &arg, true);
- /* option is not required and not present */
- if (ret == 0)
- return 0;
- /* this should not be propagated here, just to be sure */
- if (ret == -1)
- error = N_("Mandatory option not present");
- else if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK))
- error = N_("Option argument is empty");
-
- if (error) {
- vshError(ctl, _("Failed to get option '%s': %s"), name, _(error));
- return -1;
- }
-
- *value = arg->data;
- return 0;
-}
-
-/**
- * vshCommandOptLongLong:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- *
- * Returns option as long long
- * See vshCommandOptInt()
- */
-int
-vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd,
- const char *name, long long *value)
-{
- vshCmdOpt *arg;
- int ret;
-
- if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
- return ret;
-
- if ((ret = virStrToLong_ll(arg->data, NULL, 10, value)) < 0)
- vshError(ctl,
- _("Numeric value '%s' for <%s> option is malformed or out of range"),
- arg->data, name);
- else
- ret = 1;
-
- return ret;
-}
-
-static int
-vshCommandOptULongLongInternal(vshControl *ctl,
- const vshCmd *cmd,
- const char *name,
- unsigned long long *value,
- bool wrap)
-{
- vshCmdOpt *arg;
- int ret;
-
- if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
- return ret;
-
- if (wrap)
- ret = virStrToLong_ull(arg->data, NULL, 10, value);
- else
- ret = virStrToLong_ullp(arg->data, NULL, 10, value);
- if (ret < 0)
- vshError(ctl,
- _("Numeric value '%s' for <%s> option is malformed or out of range"),
- arg->data, name);
- else
- ret = 1;
-
- return ret;
-}
-
-/**
- * vshCommandOptULongLong:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- *
- * Returns option as long long, rejects negative numbers
- * See vshCommandOptInt()
- */
-int
-vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long long *value)
-{
- return vshCommandOptULongLongInternal(ctl, cmd, name, value, false);
-}
-
-/**
- * vshCommandOptULongLongWrap:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- *
- * Returns option as long long, wraps negative numbers to positive
- * See vshCommandOptInt()
- */
-int
-vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long long *value)
-{
- return vshCommandOptULongLongInternal(ctl, cmd, name, value, true);
-}
-
-/**
- * vshCommandOptScaledInt:
- * @ctl virsh control structure
- * @cmd command reference
- * @name option name
- * @value result
- * @scale default of 1 or 1024, if no suffix is present
- * @max maximum value permitted
- *
- * Returns option as long long, scaled according to suffix
- * See vshCommandOptInt()
- */
-int
-vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long long *value,
- int scale, unsigned long long max)
-{
- vshCmdOpt *arg;
- char *end;
- int ret;
-
- if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
- return ret;
- if (virStrToLong_ullp(arg->data, &end, 10, value) < 0 ||
- virScaleInteger(value, end, scale, max) < 0)
- {
- vshError(ctl,
- _("Numeric value '%s' for <%s> option is malformed or out of range"),
- arg->data, name);
- ret = -1;
- } else {
- ret = 1;
- }
-
- return ret;
-}
-
-
-/**
- * vshCommandOptBool:
- * @cmd command reference
- * @name option name
- *
- * Returns true/false if the option exists. Note that this does NOT
- * validate whether the option is actually boolean, or even whether
- * name is legal; so that this can be used to probe whether a data
- * option is present without actually using that data.
- */
-bool
-vshCommandOptBool(const vshCmd *cmd, const char *name)
-{
- vshCmdOpt *dummy;
-
- return vshCommandOpt(cmd, name, &dummy, false) == 1;
-}
-
-/**
- * vshCommandOptArgv:
- * @ctl virsh control structure
- * @cmd command reference
- * @opt starting point for the search
- *
- * Returns the next argv argument after OPT (or the first one if OPT
- * is NULL), or NULL if no more are present.
- *
- * Requires that a VSH_OT_ARGV option be last in the
- * list of supported options in CMD->def->opts.
- */
-const vshCmdOpt *
-vshCommandOptArgv(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd,
- const vshCmdOpt *opt)
-{
- opt = opt ? opt->next : cmd->opts;
-
- while (opt) {
- if (opt->def->type == VSH_OT_ARGV)
- return opt;
- opt = opt->next;
- }
- return NULL;
-}
-
-/*
- * vshCommandOptTimeoutToMs:
- * @ctl virsh control structure
- * @cmd command reference
- * @timeout result
- *
- * Parse an optional --timeout parameter in seconds, but store the
- * value of the timeout in milliseconds.
- * See vshCommandOptInt()
- */
-int
-vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout)
-{
- int ret;
- unsigned int utimeout;
-
- if ((ret = vshCommandOptUInt(ctl, cmd, "timeout", &utimeout)) <= 0)
- return ret;
-
- /* Ensure that the timeout is not zero and that we can convert
- * it from seconds to milliseconds without overflowing. */
- if (utimeout == 0 || utimeout > INT_MAX / 1000) {
- vshError(ctl,
- _("Numeric value '%u' for <%s> option is malformed or out of range"),
- utimeout,
- "timeout");
- ret = -1;
- } else {
- *timeout = ((int) utimeout) * 1000;
- }
-
- return ret;
-}
-
-static bool
-vshConnectionUsability(vshControl *ctl, virConnectPtr conn)
-{
- if (!conn ||
- virConnectIsAlive(conn) == 0) {
- vshError(ctl, "%s", _("no valid connection"));
- return false;
- }
-
- /* The connection is considered dead only if
- * virConnectIsAlive() successfuly says so.
- */
- vshResetLibvirtError();
-
- return true;
-}
-
-/*
- * Executes command(s) and returns return code from last command
- */
-static bool
-vshCommandRun(vshControl *ctl, const vshCmd *cmd)
-{
- bool ret = true;
-
- while (cmd) {
- struct timeval before, after;
- bool enable_timing = ctl->timing;
-
- if ((ctl->conn == NULL || disconnected) &&
- !(cmd->def->flags & VSH_CMD_FLAG_NOCONNECT))
- vshReconnect(ctl);
-
- if (enable_timing)
- GETTIMEOFDAY(&before);
-
- if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) ||
- vshConnectionUsability(ctl, ctl->conn)) {
- ret = cmd->def->handler(ctl, cmd);
- } else {
- /* connection is not usable, return error */
- ret = false;
- }
-
- if (enable_timing)
- GETTIMEOFDAY(&after);
-
- /* try to automatically catch disconnections */
- if (!ret &&
- ((last_error != NULL) &&
- (((last_error->code == VIR_ERR_SYSTEM_ERROR) &&
- (last_error->domain == VIR_FROM_REMOTE)) ||
- (last_error->code == VIR_ERR_RPC) ||
- (last_error->code == VIR_ERR_NO_CONNECT) ||
- (last_error->code == VIR_ERR_INVALID_CONN))))
- disconnected++;
-
- if (!ret)
- vshReportError(ctl);
-
- if (STREQ(cmd->def->name, "quit") ||
- STREQ(cmd->def->name, "exit")) /* hack ... */
- return ret;
-
- if (enable_timing) {
- double diff_ms = (((after.tv_sec - before.tv_sec) * 1000.0) +
- ((after.tv_usec - before.tv_usec) / 1000.0));
-
- vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"), diff_ms);
- } else {
- vshPrintExtra(ctl, "\n");
- }
- cmd = cmd->next;
- }
- return ret;
-}
-
-/* ---------------
- * Command parsing
- * ---------------
- */
-
-typedef enum {
- VSH_TK_ERROR, /* Failed to parse a token */
- VSH_TK_ARG, /* Arbitrary argument, might be option or empty */
- VSH_TK_SUBCMD_END, /* Separation between commands */
- VSH_TK_END /* No more commands */
-} vshCommandToken;
-
-typedef struct _vshCommandParser vshCommandParser;
-struct _vshCommandParser {
- vshCommandToken(*getNextArg)(vshControl *, vshCommandParser *,
- char **);
- /* vshCommandStringGetArg() */
- char *pos;
- /* vshCommandArgvGetArg() */
- char **arg_pos;
- char **arg_end;
-};
-
-static bool
-vshCommandParse(vshControl *ctl, vshCommandParser *parser)
-{
- char *tkdata = NULL;
- vshCmd *clast = NULL;
- vshCmdOpt *first = NULL;
-
- if (ctl->cmd) {
- vshCommandFree(ctl->cmd);
- ctl->cmd = NULL;
- }
-
- while (1) {
- vshCmdOpt *last = NULL;
- const vshCmdDef *cmd = NULL;
- vshCommandToken tk;
- bool data_only = false;
- uint32_t opts_need_arg = 0;
- uint32_t opts_required = 0;
- uint32_t opts_seen = 0;
-
- first = NULL;
-
- while (1) {
- const vshCmdOptDef *opt = NULL;
-
- tkdata = NULL;
- tk = parser->getNextArg(ctl, parser, &tkdata);
-
- if (tk == VSH_TK_ERROR)
- goto syntaxError;
- if (tk != VSH_TK_ARG) {
- VIR_FREE(tkdata);
- break;
- }
-
- if (cmd == NULL) {
- /* first token must be command name */
- if (!(cmd = vshCmddefSearch(tkdata))) {
- vshError(ctl, _("unknown command: '%s'"), tkdata);
- goto syntaxError; /* ... or ignore this command only? */
- }
- if (vshCmddefOptParse(cmd, &opts_need_arg,
- &opts_required) < 0) {
- vshError(ctl,
- _("internal error: bad options in command: '%s'"),
- tkdata);
- goto syntaxError;
- }
- VIR_FREE(tkdata);
- } else if (data_only) {
- goto get_data;
- } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
- c_isalnum(tkdata[2])) {
- char *optstr = strchr(tkdata + 2, '=');
- int opt_index = 0;
-
- if (optstr) {
- *optstr = '\0'; /* convert the '=' to '\0' */
- optstr = vshStrdup(ctl, optstr + 1);
- }
- /* Special case 'help' to ignore all spurious options */
- if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2,
- &opts_seen, &opt_index,
- &optstr))) {
- VIR_FREE(optstr);
- if (STREQ(cmd->name, "help"))
- continue;
- goto syntaxError;
- }
- VIR_FREE(tkdata);
-
- if (opt->type != VSH_OT_BOOL) {
- /* option data */
- if (optstr)
- tkdata = optstr;
- else
- tk = parser->getNextArg(ctl, parser, &tkdata);
- if (tk == VSH_TK_ERROR)
- goto syntaxError;
- if (tk != VSH_TK_ARG) {
- vshError(ctl,
- _("expected syntax: --%s <%s>"),
- opt->name,
- opt->type ==
- VSH_OT_INT ? _("number") : _("string"));
- goto syntaxError;
- }
- if (opt->type != VSH_OT_ARGV)
- opts_need_arg &= ~(1 << opt_index);
- } else {
- tkdata = NULL;
- if (optstr) {
- vshError(ctl, _("invalid '=' after option --%s"),
- opt->name);
- VIR_FREE(optstr);
- goto syntaxError;
- }
- }
- } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
- tkdata[2] == '\0') {
- data_only = true;
- continue;
- } else {
- get_data:
- /* Special case 'help' to ignore spurious data */
- if (!(opt = vshCmddefGetData(cmd, &opts_need_arg,
- &opts_seen)) &&
- STRNEQ(cmd->name, "help")) {
- vshError(ctl, _("unexpected data '%s'"), tkdata);
- goto syntaxError;
- }
- }
- if (opt) {
- /* save option */
- vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
-
- arg->def = opt;
- arg->data = tkdata;
- arg->next = NULL;
- tkdata = NULL;
-
- if (!first)
- first = arg;
- if (last)
- last->next = arg;
- last = arg;
-
- vshDebug(ctl, VSH_ERR_INFO, "%s: %s(%s): %s\n",
- cmd->name,
- opt->name,
- opt->type != VSH_OT_BOOL ? _("optdata") : _("bool"),
- opt->type != VSH_OT_BOOL ? arg->data : _("(none)"));
- }
- }
-
- /* command parsed -- allocate new struct for the command */
- if (cmd) {
- vshCmd *c = vshMalloc(ctl, sizeof(vshCmd));
- vshCmdOpt *tmpopt = first;
-
- /* if we encountered --help, replace parsed command with
- * 'help <cmdname>' */
- for (tmpopt = first; tmpopt; tmpopt = tmpopt->next) {
- if (STRNEQ(tmpopt->def->name, "help"))
- continue;
-
- vshCommandOptFree(first);
- first = vshMalloc(ctl, sizeof(vshCmdOpt));
- first->def = &(opts_help[0]);
- first->data = vshStrdup(ctl, cmd->name);
- first->next = NULL;
-
- cmd = vshCmddefSearch("help");
- opts_required = 0;
- opts_seen = 0;
- break;
- }
-
- c->opts = first;
- c->def = cmd;
- c->next = NULL;
-
- if (vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0) {
- VIR_FREE(c);
- goto syntaxError;
- }
-
- if (!ctl->cmd)
- ctl->cmd = c;
- if (clast)
- clast->next = c;
- clast = c;
- }
-
- if (tk == VSH_TK_END)
- break;
- }
-
- return true;
-
- syntaxError:
- if (ctl->cmd) {
- vshCommandFree(ctl->cmd);
- ctl->cmd = NULL;
- }
- if (first)
- vshCommandOptFree(first);
- VIR_FREE(tkdata);
- return false;
-}
-
-/* --------------------
- * Command argv parsing
- * --------------------
- */
-
-static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
-vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
-{
- if (parser->arg_pos == parser->arg_end) {
- *res = NULL;
- return VSH_TK_END;
- }
-
- *res = vshStrdup(ctl, *parser->arg_pos);
- parser->arg_pos++;
- return VSH_TK_ARG;
-}
-
-static bool
-vshCommandArgvParse(vshControl *ctl, int nargs, char **argv)
-{
- vshCommandParser parser;
-
- if (nargs <= 0)
- return false;
-
- parser.arg_pos = argv;
- parser.arg_end = argv + nargs;
- parser.getNextArg = vshCommandArgvGetArg;
- return vshCommandParse(ctl, &parser);
-}
-
-/* ----------------------
- * Command string parsing
- * ----------------------
- */
-
-static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
-vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
-{
- bool single_quote = false;
- bool double_quote = false;
- int sz = 0;
- char *p = parser->pos;
- char *q = vshStrdup(ctl, p);
-
- *res = q;
-
- while (*p && (*p == ' ' || *p == '\t'))
- p++;
-
- if (*p == '\0')
- return VSH_TK_END;
- if (*p == ';') {
- parser->pos = ++p; /* = \0 or begin of next command */
- return VSH_TK_SUBCMD_END;
- }
-
- while (*p) {
- /* end of token is blank space or ';' */
- if (!double_quote && !single_quote &&
- (*p == ' ' || *p == '\t' || *p == ';'))
- break;
-
- if (!double_quote && *p == '\'') { /* single quote */
- single_quote = !single_quote;
- p++;
- continue;
- } else if (!single_quote && *p == '\\') { /* escape */
- /*
- * The same as the bash, a \ in "" is an escaper,
- * but a \ in '' is not an escaper.
- */
- p++;
- if (*p == '\0') {
- vshError(ctl, "%s", _("dangling \\"));
- return VSH_TK_ERROR;
- }
- } else if (!single_quote && *p == '"') { /* double quote */
- double_quote = !double_quote;
- p++;
- continue;
- }
-
- *q++ = *p++;
- sz++;
- }
- if (double_quote) {
- vshError(ctl, "%s", _("missing \""));
- return VSH_TK_ERROR;
- }
-
- *q = '\0';
- parser->pos = p;
- return VSH_TK_ARG;
-}
-
-static bool
-vshCommandStringParse(vshControl *ctl, char *cmdstr)
-{
- vshCommandParser parser;
-
- if (cmdstr == NULL || *cmdstr == '\0')
- return false;
-
- parser.pos = cmdstr;
- parser.getNextArg = vshCommandStringGetArg;
- return vshCommandParse(ctl, &parser);
-}
-
-/* ---------------
- * Misc utils
- * ---------------
- */
-int
-vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason)
-{
- virDomainInfo info;
-
- if (reason)
- *reason = -1;
-
- if (!ctl->useGetInfo) {
- int state;
- if (virDomainGetState(dom, &state, reason, 0) < 0) {
- virErrorPtr err = virGetLastError();
- if (err && err->code == VIR_ERR_NO_SUPPORT)
- ctl->useGetInfo = true;
- else
- return -1;
- } else {
- return state;
- }
- }
-
- /* fall back to virDomainGetInfo if virDomainGetState is not supported */
- if (virDomainGetInfo(dom, &info) < 0)
- return -1;
- else
- return info.state;
-}
-
-/* Return a non-NULL string representation of a typed parameter; exit
- * if we are out of memory. */
-char *
-vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item)
-{
- int ret = 0;
- char *str = NULL;
-
- switch (item->type) {
- case VIR_TYPED_PARAM_INT:
- ret = virAsprintf(&str, "%d", item->value.i);
- break;
-
- case VIR_TYPED_PARAM_UINT:
- ret = virAsprintf(&str, "%u", item->value.ui);
- break;
-
- case VIR_TYPED_PARAM_LLONG:
- ret = virAsprintf(&str, "%lld", item->value.l);
- break;
-
- case VIR_TYPED_PARAM_ULLONG:
- ret = virAsprintf(&str, "%llu", item->value.ul);
- break;
-
- case VIR_TYPED_PARAM_DOUBLE:
- ret = virAsprintf(&str, "%f", item->value.d);
- break;
-
- case VIR_TYPED_PARAM_BOOLEAN:
- str = vshStrdup(ctl, item->value.b ? _("yes") : _("no"));
- break;
-
- case VIR_TYPED_PARAM_STRING:
- str = vshStrdup(ctl, item->value.s);
- break;
-
- default:
- vshError(ctl, _("unimplemented parameter type %d"), item->type);
- }
-
- if (ret < 0) {
- vshError(ctl, "%s", _("Out of memory"));
- exit(EXIT_FAILURE);
- }
- return str;
-}
-
-void
-vshDebug(vshControl *ctl, int level, const char *format, ...)
-{
- va_list ap;
- char *str;
-
- /* Aligning log levels to that of libvirt.
- * Traces with levels >= user-specified-level
- * gets logged into file
- */
- if (level < ctl->debug)
- return;
-
- va_start(ap, format);
- vshOutputLogFile(ctl, level, format, ap);
- va_end(ap);
-
- va_start(ap, format);
- if (virVasprintf(&str, format, ap) < 0) {
- /* Skip debug messages on low memory */
- va_end(ap);
- return;
- }
- va_end(ap);
- fputs(str, stdout);
- VIR_FREE(str);
-}
-
-void
-vshPrintExtra(vshControl *ctl, const char *format, ...)
-{
- va_list ap;
- char *str;
-
- if (ctl && ctl->quiet)
- return;
-
- va_start(ap, format);
- if (virVasprintf(&str, format, ap) < 0) {
- vshError(ctl, "%s", _("Out of memory"));
- va_end(ap);
- return;
- }
- va_end(ap);
- fputs(str, stdout);
- VIR_FREE(str);
-}
-
-
-bool
-vshTTYIsInterruptCharacter(vshControl *ctl ATTRIBUTE_UNUSED,
- const char chr ATTRIBUTE_UNUSED)
-{
-#ifndef WIN32
- if (ctl->istty &&
- ctl->termattr.c_cc[VINTR] == chr)
- return true;
-#endif
-
- return false;
-}
-
-
-bool
-vshTTYAvailable(vshControl *ctl)
-{
- return ctl->istty;
-}
-
-
-int
-vshTTYDisableInterrupt(vshControl *ctl ATTRIBUTE_UNUSED)
-{
-#ifndef WIN32
- struct termios termset = ctl->termattr;
-
- if (!ctl->istty)
- return -1;
-
- /* check if we need to set the terminal */
- if (termset.c_cc[VINTR] == _POSIX_VDISABLE)
- return 0;
-
- termset.c_cc[VINTR] = _POSIX_VDISABLE;
- termset.c_lflag &= ~ICANON;
-
- if (tcsetattr(STDIN_FILENO, TCSANOW, &termset) < 0)
- return -1;
-#endif
-
- return 0;
-}
-
-
-int
-vshTTYRestore(vshControl *ctl ATTRIBUTE_UNUSED)
-{
-#ifndef WIN32
- if (!ctl->istty)
- return 0;
-
- if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &ctl->termattr) < 0)
- return -1;
-#endif
-
- return 0;
-}
-
-
-#if !defined(WIN32) && !defined(HAVE_CFMAKERAW)
-/* provide fallback in case cfmakeraw isn't available */
-static void
-cfmakeraw(struct termios *attr)
-{
- attr->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
- | INLCR | IGNCR | ICRNL | IXON);
- attr->c_oflag &= ~OPOST;
- attr->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- attr->c_cflag &= ~(CSIZE | PARENB);
- attr->c_cflag |= CS8;
-}
-#endif /* !WIN32 && !HAVE_CFMAKERAW */
-
-
-int
-vshTTYMakeRaw(vshControl *ctl ATTRIBUTE_UNUSED,
- bool report_errors ATTRIBUTE_UNUSED)
-{
-#ifndef WIN32
- struct termios rawattr = ctl->termattr;
- char ebuf[1024];
-
- if (!ctl->istty) {
- if (report_errors) {
- vshError(ctl, "%s",
- _("unable to make terminal raw: console isn't a tty"));
- }
-
- return -1;
- }
-
- cfmakeraw(&rawattr);
-
- if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
- if (report_errors)
- vshError(ctl, _("unable to set tty attributes: %s"),
- virStrerror(errno, ebuf, sizeof(ebuf)));
- return -1;
- }
-#endif
-
- return 0;
-}
-
-
-void
-vshError(vshControl *ctl, const char *format, ...)
-{
- va_list ap;
- char *str;
-
- if (ctl != NULL) {
- va_start(ap, format);
- vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
- va_end(ap);
- }
-
- /* Most output is to stdout, but if someone ran virsh 2>&1, then
- * printing to stderr will not interleave correctly with stdout
- * unless we flush between every transition between streams. */
- fflush(stdout);
- fputs(_("error: "), stderr);
-
- va_start(ap, format);
- /* We can't recursively call vshError on an OOM situation, so ignore
- failure here. */
- ignore_value(virVasprintf(&str, format, ap));
- va_end(ap);
-
- fprintf(stderr, "%s\n", NULLSTR(str));
- fflush(stderr);
- VIR_FREE(str);
-}
-
-
-static void
-vshEventLoop(void *opaque)
-{
- vshControl *ctl = opaque;
-
- while (1) {
- bool quit;
- virMutexLock(&ctl->lock);
- quit = ctl->quit;
- virMutexUnlock(&ctl->lock);
-
- if (quit)
- break;
+ if (priv->conn) {
+ int ret;
- if (virEventRunDefaultImpl() < 0)
- vshReportError(ctl);
+ virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect);
+ ret = virConnectClose(priv->conn);
+ if (ret < 0)
+ vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
+ else if (ret > 0)
+ vshError(ctl, "%s", _("One or more references were leaked after "
+ "disconnect from the hypervisor"));
+ priv->conn = NULL;
}
-}
-
-/*
- * Helpers for waiting for a libvirt event.
- */
+ VIR_FREE(ctl->connname);
+ if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0)
+ return false;
-/* We want to use SIGINT to cancel a wait; but as signal handlers
- * don't have an opaque argument, we have to use static storage. */
-static int vshEventFd = -1;
-static struct sigaction vshEventOldAction;
+ ctl->connname = vshStrdup(ctl, name);
+ priv->useGetInfo = false;
+ priv->useSnapshotOld = false;
+ priv->blockJobNoBytes = false;
+ priv->readonly = ro;
-/* Signal handler installed in vshEventStart, removed in vshEventCleanup. */
-static void
-vshEventInt(int sig ATTRIBUTE_UNUSED,
- siginfo_t *siginfo ATTRIBUTE_UNUSED,
- void *context ATTRIBUTE_UNUSED)
-{
- char reason = VSH_EVENT_INTERRUPT;
- if (vshEventFd >= 0)
- ignore_value(safewrite(vshEventFd, &reason, 1));
-}
+ priv->conn = virshConnect(ctl, ctl->connname, priv->readonly);
+ if (!priv->conn) {
+ vshError(ctl, "%s", _("Failed to connect to the hypervisor"));
+ return false;
+ }
-/* Event loop handler used to limit length of waiting for any other event. */
-static void
-vshEventTimeout(int timer ATTRIBUTE_UNUSED,
- void *opaque)
-{
- vshControl *ctl = opaque;
- char reason = VSH_EVENT_TIMEOUT;
+ if (virConnectRegisterCloseCallback(priv->conn, virshCatchDisconnect,
+ NULL, NULL) < 0)
+ vshError(ctl, "%s", _("Unable to register disconnect callback"));
- if (ctl->eventPipe[1] >= 0)
- ignore_value(safewrite(ctl->eventPipe[1], &reason, 1));
+ return true;
}
+/* ---------------
+ * Utils for work with runtime commands data
+ * ---------------
+ */
-/**
- * vshEventStart:
- * @ctl virsh command struct
- * @timeout_ms max wait time in milliseconds, or 0 for indefinite
- *
- * Set up a wait for a libvirt event. The wait can be canceled by
- * SIGINT or by calling vshEventDone() in your event handler. If
- * @timeout_ms is positive, the wait will also end if the timeout
- * expires. Call vshEventWait() to block the main thread (the event
- * handler runs in the event loop thread). When done (including if
- * there was an error registering for an event), use vshEventCleanup()
- * to quit waiting. Returns 0 on success, -1 on failure. */
-int
-vshEventStart(vshControl *ctl, int timeout_ms)
+static bool
+virshConnectionUsability(vshControl *ctl, virConnectPtr conn)
{
- struct sigaction action;
-
- assert(ctl->eventPipe[0] == -1 && ctl->eventPipe[1] == -1 &&
- vshEventFd == -1 && ctl->eventTimerId >= 0);
- if (pipe2(ctl->eventPipe, O_CLOEXEC) < 0) {
- char ebuf[1024];
-
- vshError(ctl, _("failed to create pipe: %s"),
- virStrerror(errno, ebuf, sizeof(ebuf)));
- return -1;
+ if (!conn ||
+ virConnectIsAlive(conn) == 0) {
+ vshError(ctl, "%s", _("no valid connection"));
+ return false;
}
- vshEventFd = ctl->eventPipe[1];
-
- action.sa_sigaction = vshEventInt;
- action.sa_flags = SA_SIGINFO;
- sigemptyset(&action.sa_mask);
- sigaction(SIGINT, &action, &vshEventOldAction);
- if (timeout_ms)
- virEventUpdateTimeout(ctl->eventTimerId, timeout_ms);
+ /* The connection is considered dead only if
+ * virConnectIsAlive() successfuly says so.
+ */
+ vshResetLibvirtError();
- return 0;
+ return true;
}
-
-/**
- * vshEventDone:
- * @ctl virsh command struct
- *
- * Call this from an event callback to let the main thread quit
- * blocking on further events.
- */
-void
-vshEventDone(vshControl *ctl)
+static void *
+virshConnectionHandler(vshControl *ctl)
{
- char reason = VSH_EVENT_DONE;
-
- if (ctl->eventPipe[1] >= 0)
- ignore_value(safewrite(ctl->eventPipe[1], &reason, 1));
-}
+ virshControlPtr priv = ctl->privData;
+ if (!priv->conn || disconnected)
+ virshReconnect(ctl);
-/**
- * vshEventWait:
- * @ctl virsh command struct
- *
- * Call this in the main thread after calling vshEventStart() then
- * registering for one or more events. This call will block until
- * SIGINT, the timeout registered at the start, or until one of your
- * event handlers calls vshEventDone(). Returns an enum VSH_EVENT_*
- * stating how the wait concluded, or -1 on error.
- */
-int
-vshEventWait(vshControl *ctl)
-{
- char buf;
- int rv;
-
- assert(ctl->eventPipe[0] >= 0);
- while ((rv = read(ctl->eventPipe[0], &buf, 1)) < 0 && errno == EINTR);
- if (rv != 1) {
- char ebuf[1024];
-
- if (!rv)
- errno = EPIPE;
- vshError(ctl, _("failed to determine loop exit status: %s"),
- virStrerror(errno, ebuf, sizeof(ebuf)));
- return -1;
- }
- return buf;
+ if (virshConnectionUsability(ctl, priv->conn))
+ return priv->conn;
+ return NULL;
}
-
-/**
- * vshEventCleanup:
- * @ctl virsh command struct
- *
- * Call at the end of any function that has used vshEventStart(), to
- * tear down any remaining SIGINT or timeout handlers.
+/* ---------------
+ * Misc utils
+ * ---------------
*/
-void
-vshEventCleanup(vshControl *ctl)
+int
+virshDomainState(vshControl *ctl, virDomainPtr dom, int *reason)
{
- if (vshEventFd >= 0) {
- sigaction(SIGINT, &vshEventOldAction, NULL);
- vshEventFd = -1;
- }
- VIR_FORCE_CLOSE(ctl->eventPipe[0]);
- VIR_FORCE_CLOSE(ctl->eventPipe[1]);
- virEventUpdateTimeout(ctl->eventTimerId, -1);
-}
+ virDomainInfo info;
+ virshControlPtr priv = ctl->privData;
+ if (reason)
+ *reason = -1;
-/*
- * Initialize debug settings.
- */
-static void
-vshInitDebug(vshControl *ctl)
-{
- const char *debugEnv;
-
- if (ctl->debug == VSH_DEBUG_DEFAULT) {
- /* log level not set from commandline, check env variable */
- debugEnv = virGetEnvAllowSUID("VIRSH_DEBUG");
- if (debugEnv) {
- int debug;
- if (virStrToLong_i(debugEnv, NULL, 10, &debug) < 0 ||
- debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) {
- vshError(ctl, "%s",
- _("VIRSH_DEBUG not set with a valid numeric value"));
- } else {
- ctl->debug = debug;
- }
+ if (!priv->useGetInfo) {
+ int state;
+ if (virDomainGetState(dom, &state, reason, 0) < 0) {
+ virErrorPtr err = virGetLastError();
+ if (err && err->code == VIR_ERR_NO_SUPPORT)
+ priv->useGetInfo = true;
+ else
+ return -1;
+ } else {
+ return state;
}
}
- if (ctl->logfile == NULL) {
- /* log file not set from cmdline */
- debugEnv = virGetEnvBlockSUID("VIRSH_LOG_FILE");
- if (debugEnv && *debugEnv) {
- ctl->logfile = vshStrdup(ctl, debugEnv);
- vshOpenLogFile(ctl);
- }
- }
+ /* fall back to virDomainGetInfo if virDomainGetState is not supported */
+ if (virDomainGetInfo(dom, &info) < 0)
+ return -1;
+ else
+ return info.state;
}
/*
* Initialize connection.
*/
static bool
-vshInit(vshControl *ctl)
+virshInit(vshControl *ctl)
{
+ virshControlPtr priv = ctl->privData;
+
/* Since we have the commandline arguments parsed, we need to
* re-initialize all the debugging to make it work properly */
vshInitDebug(ctl);
- if (ctl->conn)
+ if (priv->conn)
return false;
/* set up the library error handler */
- virSetErrorFunc(NULL, virshErrorHandler);
+ virSetErrorFunc(NULL, vshErrorHandler);
if (virEventRegisterDefaultImpl() < 0)
return false;
NULL)) < 0)
return false;
- if (ctl->name) {
- vshReconnect(ctl);
+ if (ctl->connname) {
+ virshReconnect(ctl);
/* Connecting to a named connection must succeed, but we delay
* connecting to the default connection until we need it
* (since the first command might be 'connect' which allows a
* non-default connection, or might be 'help' which needs no
* connection).
*/
- if (!ctl->conn) {
+ if (!priv->conn) {
vshReportError(ctl);
return false;
}
return true;
}
-#define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)
-
-/**
- * vshOpenLogFile:
- *
- * Open log file.
- */
-void
-vshOpenLogFile(vshControl *ctl)
-{
- if (ctl->logfile == NULL)
- return;
-
- if ((ctl->log_fd = open(ctl->logfile, LOGFILE_FLAGS, FILE_MODE)) < 0) {
- vshError(ctl, "%s",
- _("failed to open the log file. check the log file path"));
- exit(EXIT_FAILURE);
- }
-}
-
-/**
- * vshOutputLogFile:
- *
- * Outputting an error to log file.
- */
-void
-vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format,
- va_list ap)
-{
- virBuffer buf = VIR_BUFFER_INITIALIZER;
- char *str = NULL;
- size_t len;
- const char *lvl = "";
- time_t stTime;
- struct tm stTm;
-
- if (ctl->log_fd == -1)
- return;
-
- /**
- * create log format
- *
- * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
- */
- time(&stTime);
- localtime_r(&stTime, &stTm);
- virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s %d] ",
- (1900 + stTm.tm_year),
- (1 + stTm.tm_mon),
- stTm.tm_mday,
- stTm.tm_hour,
- stTm.tm_min,
- stTm.tm_sec,
- SIGN_NAME,
- (int) getpid());
- switch (log_level) {
- case VSH_ERR_DEBUG:
- lvl = LVL_DEBUG;
- break;
- case VSH_ERR_INFO:
- lvl = LVL_INFO;
- break;
- case VSH_ERR_NOTICE:
- lvl = LVL_INFO;
- break;
- case VSH_ERR_WARNING:
- lvl = LVL_WARNING;
- break;
- case VSH_ERR_ERROR:
- lvl = LVL_ERROR;
- break;
- default:
- lvl = LVL_DEBUG;
- break;
- }
- virBufferAsprintf(&buf, "%s ", lvl);
- virBufferVasprintf(&buf, msg_format, ap);
- virBufferAddChar(&buf, '\n');
-
- if (virBufferError(&buf))
- goto error;
-
- str = virBufferContentAndReset(&buf);
- len = strlen(str);
- if (len > 1 && str[len - 2] == '\n') {
- str[len - 1] = '\0';
- len--;
- }
-
- /* write log */
- if (safewrite(ctl->log_fd, str, len) < 0)
- goto error;
-
- VIR_FREE(str);
- return;
-
- error:
- vshCloseLogFile(ctl);
- vshError(ctl, "%s", _("failed to write the log file"));
- virBufferFreeAndReset(&buf);
- VIR_FREE(str);
-}
-
-/**
- * vshCloseLogFile:
- *
- * Close log file.
- */
-void
-vshCloseLogFile(vshControl *ctl)
-{
- char ebuf[1024];
-
- /* log file close */
- if (VIR_CLOSE(ctl->log_fd) < 0) {
- vshError(ctl, _("%s: failed to write log file: %s"),
- ctl->logfile ? ctl->logfile : "?",
- virStrerror(errno, ebuf, sizeof(ebuf)));
- }
-
- if (ctl->logfile) {
- VIR_FREE(ctl->logfile);
- ctl->logfile = NULL;
- }
-}
-
-#if WITH_READLINE
-
-/* -----------------
- * Readline stuff
- * -----------------
- */
-
-/*
- * Generator function for command completion. STATE lets us
- * know whether to start from scratch; without any state
- * (i.e. STATE == 0), then we start at the top of the list.
- */
-static char *
-vshReadlineCommandGenerator(const char *text, int state)
-{
- static int grp_list_index, cmd_list_index, len;
- const char *name;
- const vshCmdGrp *grp;
- const vshCmdDef *cmds;
-
- if (!state) {
- grp_list_index = 0;
- cmd_list_index = 0;
- len = strlen(text);
- }
-
- grp = cmdGroups;
-
- /* Return the next name which partially matches from the
- * command list.
- */
- while (grp[grp_list_index].name) {
- cmds = grp[grp_list_index].commands;
-
- if (cmds[cmd_list_index].name) {
- while ((name = cmds[cmd_list_index].name)) {
- cmd_list_index++;
-
- if (STREQLEN(name, text, len))
- return vshStrdup(NULL, name);
- }
- } else {
- cmd_list_index = 0;
- grp_list_index++;
- }
- }
-
- /* If no names matched, then return NULL. */
- return NULL;
-}
-
-static char *
-vshReadlineOptionsGenerator(const char *text, int state)
-{
- static int list_index, len;
- static const vshCmdDef *cmd;
- const char *name;
-
- if (!state) {
- /* determine command name */
- char *p;
- char *cmdname;
-
- if (!(p = strchr(rl_line_buffer, ' ')))
- return NULL;
-
- cmdname = vshCalloc(NULL, (p - rl_line_buffer) + 1, 1);
- memcpy(cmdname, rl_line_buffer, p - rl_line_buffer);
-
- cmd = vshCmddefSearch(cmdname);
- list_index = 0;
- len = strlen(text);
- VIR_FREE(cmdname);
- }
-
- if (!cmd)
- return NULL;
-
- if (!cmd->opts)
- return NULL;
-
- while ((name = cmd->opts[list_index].name)) {
- const vshCmdOptDef *opt = &cmd->opts[list_index];
- char *res;
-
- list_index++;
-
- if (opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV)
- /* ignore non --option */
- continue;
-
- if (len > 2) {
- if (STRNEQLEN(name, text + 2, len - 2))
- continue;
- }
- res = vshMalloc(NULL, strlen(name) + 3);
- snprintf(res, strlen(name) + 3, "--%s", name);
- return res;
- }
-
- /* If no names matched, then return NULL. */
- return NULL;
-}
-
-static char **
-vshReadlineCompletion(const char *text, int start,
- int end ATTRIBUTE_UNUSED)
-{
- char **matches = (char **) NULL;
-
- if (start == 0)
- /* command name generator */
- matches = rl_completion_matches(text, vshReadlineCommandGenerator);
- else
- /* commands options */
- matches = rl_completion_matches(text, vshReadlineOptionsGenerator);
- return matches;
-}
-
-# define VIRSH_HISTSIZE_MAX 500000
-
-static int
-vshReadlineInit(vshControl *ctl)
-{
- char *userdir = NULL;
- int max_history = 500;
- const char *histsize_str;
-
- /* Allow conditional parsing of the ~/.inputrc file.
- * Work around ancient readline 4.1 (hello Mac OS X),
- * which declared it as 'char *' instead of 'const char *'.
- */
- rl_readline_name = (char *) "virsh";
-
- /* Tell the completer that we want a crack first. */
- rl_attempted_completion_function = vshReadlineCompletion;
-
- /* Limit the total size of the history buffer */
- if ((histsize_str = virGetEnvBlockSUID("VIRSH_HISTSIZE"))) {
- if (virStrToLong_i(histsize_str, NULL, 10, &max_history) < 0) {
- vshError(ctl, "%s", _("Bad $VIRSH_HISTSIZE value."));
- VIR_FREE(userdir);
- return -1;
- } else if (max_history > VIRSH_HISTSIZE_MAX || max_history < 0) {
- vshError(ctl, _("$VIRSH_HISTSIZE value should be between 0 and %d"),
- VIRSH_HISTSIZE_MAX);
- VIR_FREE(userdir);
- return -1;
- }
- }
- stifle_history(max_history);
-
- /* Prepare to read/write history from/to the $XDG_CACHE_HOME/virsh/history file */
- userdir = virGetUserCacheDirectory();
-
- if (userdir == NULL) {
- vshError(ctl, "%s", _("Could not determine home directory"));
- return -1;
- }
-
- if (virAsprintf(&ctl->historydir, "%s/virsh", userdir) < 0) {
- vshError(ctl, "%s", _("Out of memory"));
- VIR_FREE(userdir);
- return -1;
- }
-
- if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir) < 0) {
- vshError(ctl, "%s", _("Out of memory"));
- VIR_FREE(userdir);
- return -1;
- }
-
- VIR_FREE(userdir);
-
- read_history(ctl->historyfile);
-
- return 0;
-}
-
-static void
-vshReadlineDeinit(vshControl *ctl)
-{
- if (ctl->historyfile != NULL) {
- if (virFileMakePathWithMode(ctl->historydir, 0755) < 0 &&
- errno != EEXIST) {
- char ebuf[1024];
- vshError(ctl, _("Failed to create '%s': %s"),
- ctl->historydir, virStrerror(errno, ebuf, sizeof(ebuf)));
- } else {
- write_history(ctl->historyfile);
- }
- }
-
- VIR_FREE(ctl->historydir);
- VIR_FREE(ctl->historyfile);
-}
-
-static char *
-vshReadline(vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt)
-{
- return readline(prompt);
-}
-
-#else /* !WITH_READLINE */
-
-static int
-vshReadlineInit(vshControl *ctl ATTRIBUTE_UNUSED)
-{
- /* empty */
- return 0;
-}
-
-static void
-vshReadlineDeinit(vshControl *ctl ATTRIBUTE_UNUSED)
-{
- /* empty */
-}
-
-static char *
-vshReadline(vshControl *ctl, const char *prompt)
-{
- char line[1024];
- char *r;
- int len;
-
- fputs(prompt, stdout);
- r = fgets(line, sizeof(line), stdin);
- if (r == NULL) return NULL; /* EOF */
-
- /* Chomp trailing \n */
- len = strlen(r);
- if (len > 0 && r[len-1] == '\n')
- r[len-1] = '\0';
-
- return vshStrdup(ctl, r);
-}
-
-#endif /* !WITH_READLINE */
-
static void
-vshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED)
+virshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED)
{
/* nothing to be done here */
}
* Deinitialize virsh
*/
static bool
-vshDeinit(vshControl *ctl)
+virshDeinit(vshControl *ctl)
{
- vshReadlineDeinit(ctl);
- vshCloseLogFile(ctl);
- VIR_FREE(ctl->name);
- if (ctl->conn) {
+ virshControlPtr priv = ctl->privData;
+
+ vshDeinit(ctl);
+ VIR_FREE(ctl->connname);
+ if (priv->conn) {
int ret;
- virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect);
- ret = virConnectClose(ctl->conn);
+ virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect);
+ ret = virConnectClose(priv->conn);
if (ret < 0)
vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
else if (ret > 0)
virMutexLock(&ctl->lock);
ctl->quit = true;
/* HACK: Add a dummy timeout to break event loop */
- timer = virEventAddTimeout(0, vshDeinitTimer, NULL, NULL);
+ timer = virEventAddTimeout(0, virshDeinitTimer, NULL, NULL);
virMutexUnlock(&ctl->lock);
virThreadJoin(&ctl->eventLoop);
* Print usage
*/
static void
-vshUsage(void)
+virshUsage(void)
{
const vshCmdGrp *grp;
const vshCmdDef *cmd;
" -v short version\n"
" -V long version\n"
" --version[=TYPE] version, TYPE is short or long (default short)\n"
- " commands (non interactive mode):\n\n"), progname, progname);
+ " commands (non interactive mode):\n\n"), progname,
+ progname);
for (grp = cmdGroups; grp->name; grp++) {
fprintf(stdout, _(" %s (help keyword '%s')\n"),
* Show version and options compiled in
*/
static void
-vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
+virshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
{
/* FIXME - list a copyright blurb, as in GNU programs? */
vshPrint(ctl, _("Virsh command line tool of libvirt %s\n"), VERSION);
}
static bool
-vshAllowedEscapeChar(char c)
+virshAllowedEscapeChar(char c)
{
/* Allowed escape characters:
* a-z A-Z @ [ \ ] ^ _
*
*/
static bool
-vshParseArgv(vshControl *ctl, int argc, char **argv)
+virshParseArgv(vshControl *ctl, int argc, char **argv)
{
int arg, len, debug, keepalive;
size_t i;
int longindex = -1;
+ virshControlPtr priv = ctl->privData;
struct option opt[] = {
{"connect", required_argument, NULL, 'c'},
{"debug", required_argument, NULL, 'd'},
while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:qrtvV", opt, &longindex)) != -1) {
switch (arg) {
case 'c':
- VIR_FREE(ctl->name);
- ctl->name = vshStrdup(ctl, optarg);
+ VIR_FREE(ctl->connname);
+ ctl->connname = vshStrdup(ctl, optarg);
break;
case 'd':
if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) {
len = strlen(optarg);
if ((len == 2 && *optarg == '^' &&
- vshAllowedEscapeChar(optarg[1])) ||
+ virshAllowedEscapeChar(optarg[1])) ||
(len == 1 && *optarg != '^')) {
- ctl->escapeChar = optarg;
+ priv->escapeChar = optarg;
} else {
vshError(ctl, _("Invalid string '%s' for escape sequence"),
optarg);
}
break;
case 'h':
- vshUsage();
+ virshUsage();
exit(EXIT_SUCCESS);
break;
case 'k':
ctl->timing = true;
break;
case 'r':
- ctl->readonly = true;
+ priv->readonly = true;
break;
case 'v':
if (STRNEQ_NULLABLE(optarg, "long")) {
}
/* fall through */
case 'V':
- vshShowVersion(ctl);
+ virshShowVersion(ctl);
exit(EXIT_SUCCESS);
case ':':
for (i = 0; opt[i].name != NULL; i++) {
}
static const vshCmdDef virshCmds[] = {
- {.name = "cd",
- .handler = cmdCd,
- .opts = opts_cd,
- .info = info_cd,
- .flags = VSH_CMD_FLAG_NOCONNECT
- },
+ VSH_CMD_CD,
+ VSH_CMD_ECHO,
+ VSH_CMD_EXIT,
+ VSH_CMD_HELP,
+ VSH_CMD_PWD,
+ VSH_CMD_QUIT,
{.name = "connect",
.handler = cmdConnect,
.opts = opts_connect,
.info = info_connect,
.flags = VSH_CMD_FLAG_NOCONNECT
},
- {.name = "echo",
- .handler = cmdEcho,
- .opts = opts_echo,
- .info = info_echo,
- .flags = VSH_CMD_FLAG_NOCONNECT
- },
- {.name = "exit",
- .handler = cmdQuit,
- .opts = NULL,
- .info = info_quit,
- .flags = VSH_CMD_FLAG_NOCONNECT
- },
- {.name = "help",
- .handler = cmdHelp,
- .opts = opts_help,
- .info = info_help,
- .flags = VSH_CMD_FLAG_NOCONNECT
- },
- {.name = "pwd",
- .handler = cmdPwd,
- .opts = NULL,
- .info = info_pwd,
- .flags = VSH_CMD_FLAG_NOCONNECT
- },
- {.name = "quit",
- .handler = cmdQuit,
- .opts = NULL,
- .info = info_quit,
- .flags = VSH_CMD_FLAG_NOCONNECT
- },
{.name = NULL}
};
static const vshCmdGrp cmdGroups[] = {
- {VSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds},
- {VSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds},
- {VSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds},
- {VSH_CMD_GRP_IFACE, "interface", ifaceCmds},
- {VSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds},
- {VSH_CMD_GRP_NETWORK, "network", networkCmds},
- {VSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds},
- {VSH_CMD_GRP_SECRET, "secret", secretCmds},
- {VSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds},
- {VSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds},
- {VSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds},
- {VSH_CMD_GRP_VIRSH, "virsh", virshCmds},
+ {VIRSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds},
+ {VIRSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds},
+ {VIRSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds},
+ {VIRSH_CMD_GRP_IFACE, "interface", ifaceCmds},
+ {VIRSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds},
+ {VIRSH_CMD_GRP_NETWORK, "network", networkCmds},
+ {VIRSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds},
+ {VIRSH_CMD_GRP_SECRET, "secret", secretCmds},
+ {VIRSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds},
+ {VIRSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds},
+ {VIRSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds},
+ {VIRSH_CMD_GRP_VIRSH, "virsh", virshCmds},
{NULL, NULL, NULL}
};
+static const vshClientHooks hooks = {
+ .connHandler = virshConnectionHandler
+};
+
int
main(int argc, char **argv)
{
vshControl _ctl, *ctl = &_ctl;
+ virshControl virshCtl;
const char *defaultConn;
bool ret = true;
memset(ctl, 0, sizeof(vshControl));
+ memset(&virshCtl, 0, sizeof(virshControl));
+ ctl->name = "virsh"; /* hardcoded name of the binary */
ctl->imode = true; /* default is interactive mode */
ctl->log_fd = -1; /* Initialize log file descriptor */
ctl->debug = VSH_DEBUG_DEFAULT;
- ctl->escapeChar = "^]"; /* Same default as telnet */
+ ctl->hooks = &hooks;
/* In order to distinguish default from setting to 0 */
ctl->keepalive_interval = -1;
ctl->eventPipe[0] = -1;
ctl->eventPipe[1] = -1;
ctl->eventTimerId = -1;
+ virshCtl.escapeChar = "^]"; /* Same default as telnet */
+ ctl->privData = &virshCtl;
+
+ if (!(progname = strrchr(argv[0], '/')))
+ progname = argv[0];
+ else
+ progname++;
+ ctl->progname = progname;
if (!setlocale(LC_ALL, "")) {
perror("setlocale");
virFileActivateDirOverride(argv[0]);
- if (!(progname = strrchr(argv[0], '/')))
- progname = argv[0];
- else
- progname++;
-
if ((defaultConn = virGetEnvBlockSUID("VIRSH_DEFAULT_CONNECT_URI")))
- ctl->name = vshStrdup(ctl, defaultConn);
+ ctl->connname = vshStrdup(ctl, defaultConn);
- vshInitDebug(ctl);
+ if (vshInit(ctl, cmdGroups, NULL) < 0)
+ exit(EXIT_FAILURE);
- if (!vshParseArgv(ctl, argc, argv) ||
- !vshInit(ctl)) {
- vshDeinit(ctl);
+ if (!virshParseArgv(ctl, argc, argv) ||
+ !virshInit(ctl)) {
+ virshDeinit(ctl);
exit(EXIT_FAILURE);
}
" 'quit' to quit\n\n"));
}
- if (vshReadlineInit(ctl) < 0) {
- vshDeinit(ctl);
- exit(EXIT_FAILURE);
- }
-
do {
- const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW;
+ const char *prompt = virshCtl.readonly ? VIRSH_PROMPT_RO
+ : VIRSH_PROMPT_RW;
ctl->cmdstr =
vshReadline(ctl, prompt);
if (ctl->cmdstr == NULL)
fputc('\n', stdout); /* line break after alone prompt */
}
- vshDeinit(ctl);
+ virshDeinit(ctl);
exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
}
# include "internal.h"
# include "virerror.h"
# include "virthread.h"
+# include "vsh.h"
-# define VSH_MAX_XML_FILE (10*1024*1024)
-
-# define VSH_PROMPT_RW "virsh # "
-# define VSH_PROMPT_RO "virsh > "
+# define VIRSH_PROMPT_RW "virsh # "
+# define VIRSH_PROMPT_RO "virsh > "
# define VIR_FROM_THIS VIR_FROM_NONE
-# define GETTIMEOFDAY(T) gettimeofday(T, NULL)
-
-# define VSH_MATCH(FLAG) (flags & (FLAG))
-
-/**
- * The log configuration
- */
-# define MSG_BUFFER 4096
-# define SIGN_NAME "virsh"
-# define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */
-# define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */
-# define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */
-# define LVL_DEBUG "DEBUG"
-# define LVL_INFO "INFO"
-# define LVL_NOTICE "NOTICE"
-# define LVL_WARNING "WARNING"
-# define LVL_ERROR "ERROR"
-
-/**
- * vshErrorLevel:
- *
- * Indicates the level of a log message
- */
-typedef enum {
- VSH_ERR_DEBUG = 0,
- VSH_ERR_INFO,
- VSH_ERR_NOTICE,
- VSH_ERR_WARNING,
- VSH_ERR_ERROR
-} vshErrorLevel;
-
-# define VSH_DEBUG_DEFAULT VSH_ERR_ERROR
-
-/*
- * virsh command line grammar:
- *
- * command_line = <command>\n | <command>; <command>; ...
- *
- * command = <keyword> <option> [--] <data>
- *
- * option = <bool_option> | <int_option> | <string_option>
- * data = <string>
- *
- * bool_option = --optionname
- * int_option = --optionname <number> | --optionname=<number>
- * string_option = --optionname <string> | --optionname=<string>
- *
- * keyword = [a-zA-Z][a-zA-Z-]*
- * number = [0-9]+
- * string = ('[^']*'|"([^\\"]|\\.)*"|([^ \t\n\\'"]|\\.))+
- *
- */
-
-/*
- * vshCmdOptType - command option type
- */
-typedef enum {
- VSH_OT_BOOL, /* optional boolean option */
- VSH_OT_STRING, /* optional string option */
- VSH_OT_INT, /* optional or mandatory int option */
- VSH_OT_DATA, /* string data (as non-option) */
- VSH_OT_ARGV, /* remaining arguments */
- VSH_OT_ALIAS, /* alternate spelling for a later argument */
-} vshCmdOptType;
-
/*
* Command group types
*/
-# define VSH_CMD_GRP_DOM_MANAGEMENT "Domain Management"
-# define VSH_CMD_GRP_DOM_MONITORING "Domain Monitoring"
-# define VSH_CMD_GRP_STORAGE_POOL "Storage Pool"
-# define VSH_CMD_GRP_STORAGE_VOL "Storage Volume"
-# define VSH_CMD_GRP_NETWORK "Networking"
-# define VSH_CMD_GRP_NODEDEV "Node Device"
-# define VSH_CMD_GRP_IFACE "Interface"
-# define VSH_CMD_GRP_NWFILTER "Network Filter"
-# define VSH_CMD_GRP_SECRET "Secret"
-# define VSH_CMD_GRP_SNAPSHOT "Snapshot"
-# define VSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor"
-# define VSH_CMD_GRP_VIRSH "Virsh itself"
+# define VIRSH_CMD_GRP_DOM_MANAGEMENT "Domain Management"
+# define VIRSH_CMD_GRP_DOM_MONITORING "Domain Monitoring"
+# define VIRSH_CMD_GRP_STORAGE_POOL "Storage Pool"
+# define VIRSH_CMD_GRP_STORAGE_VOL "Storage Volume"
+# define VIRSH_CMD_GRP_NETWORK "Networking"
+# define VIRSH_CMD_GRP_NODEDEV "Node Device"
+# define VIRSH_CMD_GRP_IFACE "Interface"
+# define VIRSH_CMD_GRP_NWFILTER "Network Filter"
+# define VIRSH_CMD_GRP_SECRET "Secret"
+# define VIRSH_CMD_GRP_SNAPSHOT "Snapshot"
+# define VIRSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor"
+# define VIRSH_CMD_GRP_VIRSH "Virsh itself"
-/*
- * Command Option Flags
- */
-enum {
- VSH_OFLAG_NONE = 0, /* without flags */
- VSH_OFLAG_REQ = (1 << 0), /* option required */
- VSH_OFLAG_EMPTY_OK = (1 << 1), /* empty string option allowed */
- VSH_OFLAG_REQ_OPT = (1 << 2), /* --optionname required */
-};
-
-/* forward declarations */
-typedef struct _vshCmd vshCmd;
-typedef struct _vshCmdDef vshCmdDef;
-typedef struct _vshCmdGrp vshCmdGrp;
-typedef struct _vshCmdInfo vshCmdInfo;
-typedef struct _vshCmdOpt vshCmdOpt;
-typedef struct _vshCmdOptDef vshCmdOptDef;
-typedef struct _vshControl vshControl;
-typedef struct _vshCtrlData vshCtrlData;
+typedef struct _virshControl virshControl;
+typedef virshControl *virshControlPtr;
-typedef char **(*vshCompleter)(unsigned int flags);
-
-/*
- * vshCmdInfo -- name/value pair for information about command
- *
- * Commands should have at least the following names:
- * "help" - short description of command
- * "desc" - description of command, or empty string
- */
-struct _vshCmdInfo {
- const char *name; /* name of information, or NULL for list end */
- const char *data; /* non-NULL information */
-};
-
-/*
- * vshCmdOptDef - command option definition
- */
-struct _vshCmdOptDef {
- const char *name; /* the name of option, or NULL for list end */
- vshCmdOptType type; /* option type */
- unsigned int flags; /* flags */
- const char *help; /* non-NULL help string; or for VSH_OT_ALIAS
- * the name of a later public option */
- vshCompleter completer; /* option completer */
- unsigned int completer_flags; /* option completer flags */
-};
-
-/*
- * vshCmdOpt - command options
- *
- * After parsing a command, all arguments to the command have been
- * collected into a list of these objects.
- */
-struct _vshCmdOpt {
- const vshCmdOptDef *def; /* non-NULL pointer to option definition */
- char *data; /* allocated data, or NULL for bool option */
- vshCmdOpt *next;
-};
-
-/*
- * Command Usage Flags
- */
-enum {
- VSH_CMD_FLAG_NOCONNECT = (1 << 0), /* no prior connection needed */
- VSH_CMD_FLAG_ALIAS = (1 << 1), /* command is an alias */
-};
-
-/*
- * vshCmdDef - command definition
- */
-struct _vshCmdDef {
- const char *name; /* name of command, or NULL for list end */
- bool (*handler) (vshControl *, const vshCmd *); /* command handler */
- const vshCmdOptDef *opts; /* definition of command options */
- const vshCmdInfo *info; /* details about command */
- unsigned int flags; /* bitwise OR of VSH_CMD_FLAG */
-};
-
-/*
- * vshCmd - parsed command
- */
-struct _vshCmd {
- const vshCmdDef *def; /* command definition */
- vshCmdOpt *opts; /* list of command arguments */
- vshCmd *next; /* next command */
-};
+typedef struct _virshCtrlData virshCtrlData;
/*
* vshControl
*/
-struct _vshControl {
- char *name; /* connection name */
+struct _virshControl {
virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */
- vshCmd *cmd; /* the current command */
- char *cmdstr; /* string with command */
- bool imode; /* interactive mode? */
- bool quiet; /* quiet mode */
- int debug; /* print debug messages? */
- bool timing; /* print timing info? */
bool readonly; /* connect readonly (first time only, not
* during explicit connect command)
*/
- char *logfile; /* log file name */
- int log_fd; /* log file descriptor */
- char *historydir; /* readline history directory name */
- char *historyfile; /* readline history file name */
bool useGetInfo; /* must use virDomainGetInfo, since
virDomainGetState is not supported */
bool useSnapshotOld; /* cannot use virDomainSnapshotGetParent or
virDomainSnapshotNumChildren */
bool blockJobNoBytes; /* true if _BANDWIDTH_BYTE blockjob flags
are missing */
- virThread eventLoop;
- virMutex lock;
- bool eventLoopStarted;
- bool quit;
- int eventPipe[2]; /* Write-to-self pipe to end waiting for an
- * event to occur */
- int eventTimerId; /* id of event loop timeout registration */
-
const char *escapeChar; /* String representation of
console escape character */
-
- int keepalive_interval; /* Client keepalive interval */
- int keepalive_count; /* Client keepalive count */
-
-# ifndef WIN32
- struct termios termattr; /* settings of the tty terminal */
-# endif
- bool istty; /* is the terminal a tty */
-};
-
-struct _vshCmdGrp {
- const char *name; /* name of group, or NULL for list end */
- const char *keyword; /* help keyword */
- const vshCmdDef *commands;
};
-void vshError(vshControl *ctl, const char *format, ...)
- ATTRIBUTE_FMT_PRINTF(2, 3);
-void vshOpenLogFile(vshControl *ctl);
-void vshOutputLogFile(vshControl *ctl, int log_level, const char *format,
- va_list ap)
- ATTRIBUTE_FMT_PRINTF(3, 0);
-void vshCloseLogFile(vshControl *ctl);
-
-virConnectPtr vshConnect(vshControl *ctl, const char *uri, bool readonly);
-
-const char *vshCmddefGetInfo(const vshCmdDef *cmd, const char *info);
-const vshCmdDef *vshCmddefSearch(const char *cmdname);
-bool vshCmddefHelp(vshControl *ctl, const char *name);
-const vshCmdGrp *vshCmdGrpSearch(const char *grpname);
-bool vshCmdGrpHelp(vshControl *ctl, const char *name);
-
-int vshCommandOptInt(vshControl *ctl, const vshCmd *cmd,
- const char *name, int *value)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned int *value)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned int *value)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptUL(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long *value)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long *value)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptString(vshControl *ctl, const vshCmd *cmd,
- const char *name, const char **value)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptStringReq(vshControl *ctl, const vshCmd *cmd,
- const char *name, const char **value)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd,
- const char *name, long long *value)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long long *value)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long long *value)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-int vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd,
- const char *name, unsigned long long *value,
- int scale, unsigned long long max)
- ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
-bool vshCommandOptBool(const vshCmd *cmd, const char *name);
-const vshCmdOpt *vshCommandOptArgv(vshControl *ctl, const vshCmd *cmd,
- const vshCmdOpt *opt);
-int vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout);
-
-/* Filter flags for various vshCommandOpt*By() functions */
-typedef enum {
- VSH_BYID = (1 << 1),
- VSH_BYUUID = (1 << 2),
- VSH_BYNAME = (1 << 3),
- VSH_BYMAC = (1 << 4),
-} vshLookupByFlags;
-
-/* Given an index, return either the name of that device (non-NULL) or
- * of its parent (NULL if a root). */
-typedef const char * (*vshTreeLookup)(int devid, bool parent, void *opaque);
-int vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
- int num_devices, int devid);
-
-void vshPrintExtra(vshControl *ctl, const char *format, ...)
- ATTRIBUTE_FMT_PRINTF(2, 3);
-void vshDebug(vshControl *ctl, int level, const char *format, ...)
- ATTRIBUTE_FMT_PRINTF(3, 4);
-
-/* XXX: add batch support */
-# define vshPrint(_ctl, ...) vshPrintExtra(NULL, __VA_ARGS__)
-
-/* User visible sort, so we want locale-specific case comparison. */
-# define vshStrcasecmp(S1, S2) strcasecmp(S1, S2)
-int vshNameSorter(const void *a, const void *b);
-
-int vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason);
-virTypedParameterPtr vshFindTypedParamByName(const char *name,
- virTypedParameterPtr list,
- int count);
-char *vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
-
-char *vshEditWriteToTempFile(vshControl *ctl, const char *doc);
-int vshEditFile(vshControl *ctl, const char *filename);
-char *vshEditReadBackFile(vshControl *ctl, const char *filename);
-int vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail);
-int vshStreamSink(virStreamPtr st, const char *bytes, size_t nbytes,
- void *opaque);
-double vshPrettyCapacity(unsigned long long val, const char **unit);
-int vshStringToArray(const char *str, char ***array);
-
/* Typedefs, function prototypes for job progress reporting.
* There are used by some long lingering commands like
* migrate, dump, save, managedsave.
*/
-struct _vshCtrlData {
+struct _virshCtrlData {
vshControl *ctl;
const vshCmd *cmd;
int writefd;
virConnectPtr dconn;
};
-/* error handling */
-extern virErrorPtr last_error;
-void vshReportError(vshControl *ctl);
-void vshResetLibvirtError(void);
-void vshSaveLibvirtError(void);
-
-/* terminal modifications */
-bool vshTTYIsInterruptCharacter(vshControl *ctl, const char chr);
-int vshTTYDisableInterrupt(vshControl *ctl);
-int vshTTYRestore(vshControl *ctl);
-int vshTTYMakeRaw(vshControl *ctl, bool report_errors);
-bool vshTTYAvailable(vshControl *ctl);
-
-/* waiting for events */
-enum {
- VSH_EVENT_INTERRUPT,
- VSH_EVENT_TIMEOUT,
- VSH_EVENT_DONE,
-};
-int vshEventStart(vshControl *ctl, int timeout_ms);
-void vshEventDone(vshControl *ctl);
-int vshEventWait(vshControl *ctl);
-void vshEventCleanup(vshControl *ctl);
-
-/* allocation wrappers */
-void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line);
-# define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
-
-void *_vshCalloc(vshControl *ctl, size_t nmemb, size_t sz,
- const char *filename, int line);
-# define vshCalloc(_ctl, _nmemb, _sz) \
- _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)
-
-char *_vshStrdup(vshControl *ctl, const char *s, const char *filename,
- int line);
-# define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__)
-
-/* Poison the raw allocating identifiers in favor of our vsh variants. */
-# undef malloc
-# undef calloc
-# undef realloc
-# undef strdup
-# define malloc use_vshMalloc_instead_of_malloc
-# define calloc use_vshCalloc_instead_of_calloc
-# define realloc use_vshRealloc_instead_of_realloc
-# define strdup use_vshStrdup_instead_of_strdup
-
-/* Macros to help dealing with mutually exclusive options. */
-
-/* VSH_EXCLUSIVE_OPTIONS_EXPR:
- *
- * @NAME1: String containing the name of the option.
- * @EXPR1: Expression to validate the variable (boolean variable)
- * @NAME2: String containing the name of the option.
- * @EXPR2: Expression to validate the variable (boolean variable)
- *
- * Reject mutually exclusive command options in virsh. Use the
- * provided expression to check the variables.
- *
- * This helper does an early return and therefore it has to be called
- * before anything that would require cleanup.
- */
-# define VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, EXPR1, NAME2, EXPR2) \
- if ((EXPR1) && (EXPR2)) { \
- vshError(ctl, _("Options --%s and --%s are mutually exclusive"), \
- NAME1, NAME2); \
- return false; \
- }
-
-/* VSH_EXCLUSIVE_OPTIONS:
- *
- * @NAME1: String containing the name of the option.
- * @NAME2: String containing the name of the option.
- *
- * Reject mutually exclusive command options in virsh. Use the
- * vshCommandOptBool call to request them.
- *
- * This helper does an early return and therefore it has to be called
- * before anything that would require cleanup.
- */
-# define VSH_EXCLUSIVE_OPTIONS(NAME1, NAME2) \
- VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \
- NAME2, vshCommandOptBool(cmd, NAME2))
-
-/* VSH_EXCLUSIVE_OPTIONS_VAR:
- *
- * @VARNAME1: Boolean variable containing the value of the option of same name
- * @VARNAME2: Boolean variable containing the value of the option of same name
- *
- * Reject mutually exclusive command options in virsh. Check in variables that
- * contain the value and have same name as the option.
- *
- * This helper does an early return and therefore it has to be called
- * before anything that would require cleanup.
- */
-# define VSH_EXCLUSIVE_OPTIONS_VAR(VARNAME1, VARNAME2) \
- VSH_EXCLUSIVE_OPTIONS_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2)
-
-/* Macros to help dealing with required options. */
-
-/* VSH_REQUIRE_OPTION_EXPR:
- *
- * @NAME1: String containing the name of the option.
- * @EXPR1: Expression to validate the variable (boolean variable).
- * @NAME2: String containing the name of required option.
- * @EXPR2: Expression to validate the variable (boolean variable).
- *
- * Check if required command options in virsh was set. Use the
- * provided expression to check the variables.
- *
- * This helper does an early return and therefore it has to be called
- * before anything that would require cleanup.
- */
-# define VSH_REQUIRE_OPTION_EXPR(NAME1, EXPR1, NAME2, EXPR2) \
- do { \
- if ((EXPR1) && !(EXPR2)) { \
- vshError(ctl, _("Option --%s is required by option --%s"), \
- NAME2, NAME1); \
- return false; \
- } \
- } while (0)
+/* Filter flags for various vshCommandOpt*By() functions */
+typedef enum {
+ VIRSH_BYID = (1 << 1),
+ VIRSH_BYUUID = (1 << 2),
+ VIRSH_BYNAME = (1 << 3),
+ VIRSH_BYMAC = (1 << 4),
+} virshLookupByFlags;
-/* VSH_REQUIRE_OPTION:
- *
- * @NAME1: String containing the name of the option.
- * @NAME2: String containing the name of required option.
- *
- * Check if required command options in virsh was set. Use the
- * vshCommandOptBool call to request them.
- *
- * This helper does an early return and therefore it has to be called
- * before anything that would require cleanup.
- */
-# define VSH_REQUIRE_OPTION(NAME1, NAME2) \
- VSH_REQUIRE_OPTION_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \
- NAME2, vshCommandOptBool(cmd, NAME2))
+virConnectPtr virshConnect(vshControl *ctl, const char *uri, bool readonly);
+int virshDomainState(vshControl *ctl, virDomainPtr dom, int *reason);
-/* VSH_REQUIRE_OPTION_VAR:
- *
- * @VARNAME1: Boolean variable containing the value of the option of same name.
- * @VARNAME2: Boolean variable containing the value of required option of
- * same name.
- *
- * Check if required command options in virsh was set. Check in variables
- * that contain the value and have same name as the option.
- *
- * This helper does an early return and therefore it has to be called
- * before anything that would require cleanup.
- */
-# define VSH_REQUIRE_OPTION_VAR(VARNAME1, VARNAME2) \
- VSH_REQUIRE_OPTION_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2)
+int virshStreamSink(virStreamPtr st, const char *bytes, size_t nbytes,
+ void *opaque);
#endif /* VIRSH_H */
--- /dev/null
+/*
+ * vsh.c: common data to be used by clients to exercise the libvirt API
+ *
+ * Copyright (C) 2005, 2007-2015 Red Hat, Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ * Karel Zak <kzak@redhat.com>
+ * Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#include <config.h>
+#include "vsh.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+#include "c-ctype.h"
+#include <fcntl.h>
+#include <locale.h>
+#include <time.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <inttypes.h>
+#include <strings.h>
+#include <signal.h>
+
+#if WITH_READLINE
+# include <readline/readline.h>
+# include <readline/history.h>
+#endif
+
+#include "internal.h"
+#include "virerror.h"
+#include "virbuffer.h"
+#include "viralloc.h"
+#include <libvirt/libvirt-qemu.h>
+#include <libvirt/libvirt-lxc.h>
+#include "virfile.h"
+#include "configmake.h"
+#include "virthread.h"
+#include "vircommand.h"
+#include "conf/domain_conf.h"
+#include "virtypedparam.h"
+#include "virstring.h"
+
+/* Gnulib doesn't guarantee SA_SIGINFO support. */
+#ifndef SA_SIGINFO
+# define SA_SIGINFO 0
+#endif
+
+/* NOTE: It would be much nicer to have these two as part of vshControl
+ * structure, unfortunately readline doesn't support passing opaque data
+ * and only relies on static data accessible from the user-side callback
+ */
+const vshCmdGrp *cmdGroups;
+const vshCmdDef *cmdSet;
+
+/* Bypass header poison */
+#undef strdup
+
+double
+vshPrettyCapacity(unsigned long long val, const char **unit)
+{
+ double limit = 1024;
+
+ if (val < limit) {
+ *unit = "B";
+ return val;
+ }
+ limit *= 1024;
+ if (val < limit) {
+ *unit = "KiB";
+ return val / (limit / 1024);
+ }
+ limit *= 1024;
+ if (val < limit) {
+ *unit = "MiB";
+ return val / (limit / 1024);
+ }
+ limit *= 1024;
+ if (val < limit) {
+ *unit = "GiB";
+ return val / (limit / 1024);
+ }
+ limit *= 1024;
+ if (val < limit) {
+ *unit = "TiB";
+ return val / (limit / 1024);
+ }
+ limit *= 1024;
+ if (val < limit) {
+ *unit = "PiB";
+ return val / (limit / 1024);
+ }
+ limit *= 1024;
+ *unit = "EiB";
+ return val / (limit / 1024);
+}
+
+
+void *
+_vshMalloc(vshControl *ctl, size_t size, const char *filename, int line)
+{
+ char *x;
+
+ if (VIR_ALLOC_N(x, size) == 0)
+ return x;
+ vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
+ filename, line, (int) size);
+ exit(EXIT_FAILURE);
+}
+
+void *
+_vshCalloc(vshControl *ctl, size_t nmemb, size_t size, const char *filename,
+ int line)
+{
+ char *x;
+
+ if (!xalloc_oversized(nmemb, size) &&
+ VIR_ALLOC_N(x, nmemb * size) == 0)
+ return x;
+ vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
+ filename, line, (int) (size*nmemb));
+ exit(EXIT_FAILURE);
+}
+
+char *
+_vshStrdup(vshControl *ctl, const char *s, const char *filename, int line)
+{
+ char *x;
+
+ if (VIR_STRDUP(x, s) >= 0)
+ return x;
+ vshError(ctl, _("%s: %d: failed to allocate %lu bytes"),
+ filename, line, (unsigned long)strlen(s));
+ exit(EXIT_FAILURE);
+}
+
+/* Poison the raw allocating identifiers in favor of our vsh variants. */
+#define strdup use_vshStrdup_instead_of_strdup
+
+int
+vshNameSorter(const void *a, const void *b)
+{
+ const char **sa = (const char**)a;
+ const char **sb = (const char**)b;
+
+ return vshStrcasecmp(*sa, *sb);
+}
+
+
+/*
+ * Convert the strings separated by ',' into array. The returned
+ * array is a NULL terminated string list. The caller has to free
+ * the array using virStringFreeList or a similar method.
+ *
+ * Returns the length of the filled array on success, or -1
+ * on error.
+ */
+int
+vshStringToArray(const char *str,
+ char ***array)
+{
+ char *str_copied = vshStrdup(NULL, str);
+ char *str_tok = NULL;
+ char *tmp;
+ unsigned int nstr_tokens = 0;
+ char **arr = NULL;
+ size_t len = strlen(str_copied);
+
+ /* tokenize the string from user and save its parts into an array */
+ nstr_tokens = 1;
+
+ /* count the delimiters, recognizing ,, as an escape for a
+ * literal comma */
+ str_tok = str_copied;
+ while ((str_tok = strchr(str_tok, ','))) {
+ if (str_tok[1] == ',')
+ str_tok++;
+ else
+ nstr_tokens++;
+ str_tok++;
+ }
+
+ /* reserve the NULL element at the end */
+ if (VIR_ALLOC_N(arr, nstr_tokens + 1) < 0) {
+ VIR_FREE(str_copied);
+ return -1;
+ }
+
+ /* tokenize the input string, while treating ,, as a literal comma */
+ nstr_tokens = 0;
+ tmp = str_tok = str_copied;
+ while ((tmp = strchr(tmp, ','))) {
+ if (tmp[1] == ',') {
+ memmove(&tmp[1], &tmp[2], len - (tmp - str_copied) - 2 + 1);
+ len--;
+ tmp++;
+ continue;
+ }
+ *tmp++ = '\0';
+ arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
+ str_tok = tmp;
+ }
+ arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
+
+ *array = arr;
+ VIR_FREE(str_copied);
+ return nstr_tokens;
+}
+
+virErrorPtr last_error;
+
+/*
+ * Quieten libvirt until we're done with the command.
+ */
+void
+vshErrorHandler(void *opaque ATTRIBUTE_UNUSED, virErrorPtr error)
+{
+ virFreeError(last_error);
+ last_error = virSaveLastError();
+ if (virGetEnvAllowSUID("VSH_DEBUG") != NULL)
+ virDefaultErrorFunc(error);
+}
+
+/* Store a libvirt error that is from a helper API that doesn't raise errors
+ * so it doesn't get overwritten */
+void
+vshSaveLibvirtError(void)
+{
+ virFreeError(last_error);
+ last_error = virSaveLastError();
+}
+
+/*
+ * Reset libvirt error on graceful fallback paths
+ */
+void
+vshResetLibvirtError(void)
+{
+ virFreeError(last_error);
+ last_error = NULL;
+}
+
+/*
+ * Report an error when a command finishes. This is better than before
+ * (when correct operation would report errors), but it has some
+ * problems: we lose the smarter formatting of virDefaultErrorFunc(),
+ * and it can become harder to debug problems, if errors get reported
+ * twice during one command. This case shouldn't really happen anyway,
+ * and it's IMHO a bug that libvirt does that sometimes.
+ */
+void
+vshReportError(vshControl *ctl)
+{
+ if (last_error == NULL) {
+ /* Calling directly into libvirt util functions won't trigger the
+ * error callback (which sets last_error), so check it ourselves.
+ *
+ * If the returned error has CODE_OK, this most likely means that
+ * no error was ever raised, so just ignore */
+ last_error = virSaveLastError();
+ if (!last_error || last_error->code == VIR_ERR_OK)
+ goto out;
+ }
+
+ if (last_error->code == VIR_ERR_OK) {
+ vshError(ctl, "%s", _("unknown error"));
+ goto out;
+ }
+
+ vshError(ctl, "%s", last_error->message);
+
+ out:
+ vshResetLibvirtError();
+}
+
+/*
+ * Detection of disconnections and automatic reconnection support
+ */
+static int disconnected; /* we may have been disconnected */
+
+/* ---------------
+ * Utils for work with command definition
+ * ---------------
+ */
+const char *
+vshCmddefGetInfo(const vshCmdDef * cmd, const char *name)
+{
+ const vshCmdInfo *info;
+
+ for (info = cmd->info; info && info->name; info++) {
+ if (STREQ(info->name, name))
+ return info->data;
+ }
+ return NULL;
+}
+
+/* Validate that the options associated with cmd can be parsed. */
+static int
+vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg,
+ uint32_t *opts_required)
+{
+ size_t i;
+ bool optional = false;
+
+ *opts_need_arg = 0;
+ *opts_required = 0;
+
+ if (!cmd->opts)
+ return 0;
+
+ for (i = 0; cmd->opts[i].name; i++) {
+ const vshCmdOptDef *opt = &cmd->opts[i];
+
+ if (i > 31)
+ return -1; /* too many options */
+ if (opt->type == VSH_OT_BOOL) {
+ optional = true;
+ if (opt->flags & VSH_OFLAG_REQ)
+ return -1; /* bool options can't be mandatory */
+ continue;
+ }
+ if (opt->type == VSH_OT_ALIAS) {
+ size_t j;
+ char *name = (char *)opt->help; /* cast away const */
+ char *p;
+
+ if (opt->flags || !opt->help)
+ return -1; /* alias options are tracked by the original name */
+ if ((p = strchr(name, '=')) &&
+ VIR_STRNDUP(name, name, p - name) < 0)
+ return -1;
+ for (j = i + 1; cmd->opts[j].name; j++) {
+ if (STREQ(name, cmd->opts[j].name) &&
+ cmd->opts[j].type != VSH_OT_ALIAS)
+ break;
+ }
+ if (name != opt->help) {
+ VIR_FREE(name);
+ /* If alias comes with value, replacement must not be bool */
+ if (cmd->opts[j].type == VSH_OT_BOOL)
+ return -1;
+ }
+ if (!cmd->opts[j].name)
+ return -1; /* alias option must map to a later option name */
+ continue;
+ }
+ if (opt->flags & VSH_OFLAG_REQ_OPT) {
+ if (opt->flags & VSH_OFLAG_REQ)
+ *opts_required |= 1 << i;
+ else
+ optional = true;
+ continue;
+ }
+
+ *opts_need_arg |= 1 << i;
+ if (opt->flags & VSH_OFLAG_REQ) {
+ if (optional && opt->type != VSH_OT_ARGV)
+ return -1; /* mandatory options must be listed first */
+ *opts_required |= 1 << i;
+ } else {
+ optional = true;
+ }
+
+ if (opt->type == VSH_OT_ARGV && cmd->opts[i + 1].name)
+ return -1; /* argv option must be listed last */
+ }
+ return 0;
+}
+
+static vshCmdOptDef helpopt = {
+ .name = "help",
+ .type = VSH_OT_BOOL,
+ .help = N_("print help for this function")
+};
+static const vshCmdOptDef *
+vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
+ uint32_t *opts_seen, int *opt_index, char **optstr)
+{
+ size_t i;
+ const vshCmdOptDef *ret = NULL;
+ char *alias = NULL;
+
+ if (STREQ(name, helpopt.name))
+ return &helpopt;
+
+ for (i = 0; cmd->opts && cmd->opts[i].name; i++) {
+ const vshCmdOptDef *opt = &cmd->opts[i];
+
+ if (STREQ(opt->name, name)) {
+ if (opt->type == VSH_OT_ALIAS) {
+ char *value;
+
+ /* Two types of replacements:
+ opt->help = "string": straight replacement of name
+ opt->help = "string=value": treat boolean flag as
+ alias of option and its default value */
+ sa_assert(!alias);
+ if (VIR_STRDUP(alias, opt->help) < 0)
+ goto cleanup;
+ name = alias;
+ if ((value = strchr(name, '='))) {
+ *value = '\0';
+ if (*optstr) {
+ vshError(ctl, _("invalid '=' after option --%s"),
+ opt->name);
+ goto cleanup;
+ }
+ if (VIR_STRDUP(*optstr, value + 1) < 0)
+ goto cleanup;
+ }
+ continue;
+ }
+ if ((*opts_seen & (1 << i)) && opt->type != VSH_OT_ARGV) {
+ vshError(ctl, _("option --%s already seen"), name);
+ goto cleanup;
+ }
+ *opts_seen |= 1 << i;
+ *opt_index = i;
+ ret = opt;
+ goto cleanup;
+ }
+ }
+
+ if (STRNEQ(cmd->name, "help")) {
+ vshError(ctl, _("command '%s' doesn't support option --%s"),
+ cmd->name, name);
+ }
+ cleanup:
+ VIR_FREE(alias);
+ return ret;
+}
+
+static const vshCmdOptDef *
+vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg,
+ uint32_t *opts_seen)
+{
+ size_t i;
+ const vshCmdOptDef *opt;
+
+ if (!*opts_need_arg)
+ return NULL;
+
+ /* Grab least-significant set bit */
+ i = ffs(*opts_need_arg) - 1;
+ opt = &cmd->opts[i];
+ if (opt->type != VSH_OT_ARGV)
+ *opts_need_arg &= ~(1 << i);
+ *opts_seen |= 1 << i;
+ return opt;
+}
+
+/*
+ * Checks for required options
+ */
+static int
+vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required,
+ uint32_t opts_seen)
+{
+ const vshCmdDef *def = cmd->def;
+ size_t i;
+
+ opts_required &= ~opts_seen;
+ if (!opts_required)
+ return 0;
+
+ for (i = 0; def->opts[i].name; i++) {
+ if (opts_required & (1 << i)) {
+ const vshCmdOptDef *opt = &def->opts[i];
+
+ vshError(ctl,
+ opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV ?
+ _("command '%s' requires <%s> option") :
+ _("command '%s' requires --%s option"),
+ def->name, opt->name);
+ }
+ }
+ return -1;
+}
+
+static const vshCmdDef *
+vshCmdDefSearchGrp(const char *cmdname)
+{
+ const vshCmdGrp *g;
+ const vshCmdDef *c;
+
+ for (g = cmdGroups; g->name; g++) {
+ for (c = g->commands; c->name; c++) {
+ if (STREQ(c->name, cmdname))
+ return c;
+ }
+ }
+
+ return NULL;
+}
+
+static const vshCmdDef *
+vshCmdDefSearchSet(const char *cmdname)
+{
+ const vshCmdDef *s;
+
+ for (s = cmdSet; s->name; s++) {
+ if (STREQ(s->name, cmdname))
+ return s;
+ }
+
+ return NULL;
+}
+
+const vshCmdDef *
+vshCmddefSearch(const char *cmdname)
+{
+ if (cmdGroups)
+ return vshCmdDefSearchGrp(cmdname);
+ else
+ return vshCmdDefSearchSet(cmdname);
+}
+
+const vshCmdGrp *
+vshCmdGrpSearch(const char *grpname)
+{
+ const vshCmdGrp *g;
+
+ for (g = cmdGroups; g->name; g++) {
+ if (STREQ(g->name, grpname) || STREQ(g->keyword, grpname))
+ return g;
+ }
+
+ return NULL;
+}
+
+bool
+vshCmdGrpHelp(vshControl *ctl, const char *grpname)
+{
+ const vshCmdGrp *grp = vshCmdGrpSearch(grpname);
+ const vshCmdDef *cmd = NULL;
+
+ if (!grp) {
+ vshError(ctl, _("command group '%s' doesn't exist"), grpname);
+ return false;
+ } else {
+ vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
+ grp->keyword);
+
+ for (cmd = grp->commands; cmd->name; cmd++) {
+ if (cmd->flags & VSH_CMD_FLAG_ALIAS)
+ continue;
+ vshPrint(ctl, " %-30s %s\n", cmd->name,
+ _(vshCmddefGetInfo(cmd, "help")));
+ }
+ }
+
+ return true;
+}
+
+bool
+vshCmddefHelp(vshControl *ctl, const char *cmdname)
+{
+ const vshCmdDef *def = vshCmddefSearch(cmdname);
+
+ if (!def) {
+ vshError(ctl, _("command '%s' doesn't exist"), cmdname);
+ return false;
+ } else {
+ /* Don't translate desc if it is "". */
+ const char *desc = vshCmddefGetInfo(def, "desc");
+ const char *help = _(vshCmddefGetInfo(def, "help"));
+ char buf[256];
+ uint32_t opts_need_arg;
+ uint32_t opts_required;
+ bool shortopt = false; /* true if 'arg' works instead of '--opt arg' */
+
+ if (vshCmddefOptParse(def, &opts_need_arg, &opts_required)) {
+ vshError(ctl, _("internal error: bad options in command: '%s'"),
+ def->name);
+ return false;
+ }
+
+ fputs(_(" NAME\n"), stdout);
+ fprintf(stdout, " %s - %s\n", def->name, help);
+
+ fputs(_("\n SYNOPSIS\n"), stdout);
+ fprintf(stdout, " %s", def->name);
+ if (def->opts) {
+ const vshCmdOptDef *opt;
+ for (opt = def->opts; opt->name; opt++) {
+ const char *fmt = "%s";
+ switch (opt->type) {
+ case VSH_OT_BOOL:
+ fmt = "[--%s]";
+ break;
+ case VSH_OT_INT:
+ /* xgettext:c-format */
+ fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>"
+ : _("[--%s <number>]"));
+ if (!(opt->flags & VSH_OFLAG_REQ_OPT))
+ shortopt = true;
+ break;
+ case VSH_OT_STRING:
+ /* xgettext:c-format */
+ fmt = _("[--%s <string>]");
+ if (!(opt->flags & VSH_OFLAG_REQ_OPT))
+ shortopt = true;
+ break;
+ case VSH_OT_DATA:
+ fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>" : "[<%s>]");
+ if (!(opt->flags & VSH_OFLAG_REQ_OPT))
+ shortopt = true;
+ break;
+ case VSH_OT_ARGV:
+ /* xgettext:c-format */
+ if (shortopt) {
+ fmt = (opt->flags & VSH_OFLAG_REQ)
+ ? _("{[--%s] <string>}...")
+ : _("[[--%s] <string>]...");
+ } else {
+ fmt = (opt->flags & VSH_OFLAG_REQ) ? _("<%s>...")
+ : _("[<%s>]...");
+ }
+ break;
+ case VSH_OT_ALIAS:
+ /* aliases are intentionally undocumented */
+ continue;
+ }
+ fputc(' ', stdout);
+ fprintf(stdout, fmt, opt->name);
+ }
+ }
+ fputc('\n', stdout);
+
+ if (desc[0]) {
+ /* Print the description only if it's not empty. */
+ fputs(_("\n DESCRIPTION\n"), stdout);
+ fprintf(stdout, " %s\n", _(desc));
+ }
+
+ if (def->opts && def->opts->name) {
+ const vshCmdOptDef *opt;
+ fputs(_("\n OPTIONS\n"), stdout);
+ for (opt = def->opts; opt->name; opt++) {
+ switch (opt->type) {
+ case VSH_OT_BOOL:
+ snprintf(buf, sizeof(buf), "--%s", opt->name);
+ break;
+ case VSH_OT_INT:
+ snprintf(buf, sizeof(buf),
+ (opt->flags & VSH_OFLAG_REQ) ? _("[--%s] <number>")
+ : _("--%s <number>"), opt->name);
+ break;
+ case VSH_OT_STRING:
+ /* OT_STRING should never be VSH_OFLAG_REQ */
+ if (opt->flags & VSH_OFLAG_REQ) {
+ vshError(ctl,
+ _("internal error: bad options in command: '%s'"),
+ def->name);
+ return false;
+ }
+ snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name);
+ break;
+ case VSH_OT_DATA:
+ /* OT_DATA should always be VSH_OFLAG_REQ */
+ if (!(opt->flags & VSH_OFLAG_REQ)) {
+ vshError(ctl,
+ _("internal error: bad options in command: '%s'"),
+ def->name);
+ return false;
+ }
+ snprintf(buf, sizeof(buf), _("[--%s] <string>"),
+ opt->name);
+ break;
+ case VSH_OT_ARGV:
+ snprintf(buf, sizeof(buf),
+ shortopt ? _("[--%s] <string>") : _("<%s>"),
+ opt->name);
+ break;
+ case VSH_OT_ALIAS:
+ continue;
+ }
+
+ fprintf(stdout, " %-15s %s\n", buf, _(opt->help));
+ }
+ }
+ fputc('\n', stdout);
+ }
+ return true;
+}
+
+/* ---------------
+ * Utils for work with runtime commands data
+ * ---------------
+ */
+static void
+vshCommandOptFree(vshCmdOpt * arg)
+{
+ vshCmdOpt *a = arg;
+
+ while (a) {
+ vshCmdOpt *tmp = a;
+
+ a = a->next;
+
+ VIR_FREE(tmp->data);
+ VIR_FREE(tmp);
+ }
+}
+
+static void
+vshCommandFree(vshCmd *cmd)
+{
+ vshCmd *c = cmd;
+
+ while (c) {
+ vshCmd *tmp = c;
+
+ c = c->next;
+
+ if (tmp->opts)
+ vshCommandOptFree(tmp->opts);
+ VIR_FREE(tmp);
+ }
+}
+
+/**
+ * vshCommandOpt:
+ * @cmd: parsed command line to search
+ * @name: option name to search for
+ * @opt: result of the search
+ * @needData: true if option must be non-boolean
+ *
+ * Look up an option passed to CMD by NAME. Returns 1 with *OPT set
+ * to the option if found, 0 with *OPT set to NULL if the name is
+ * valid and the option is not required, -1 with *OPT set to NULL if
+ * the option is required but not present, and assert if NAME is not
+ * valid (which indicates a programming error). No error messages are
+ * issued if a value is returned.
+ */
+static int
+vshCommandOpt(const vshCmd *cmd, const char *name, vshCmdOpt **opt,
+ bool needData)
+{
+ vshCmdOpt *candidate = cmd->opts;
+ const vshCmdOptDef *valid = cmd->def->opts;
+ int ret = 0;
+
+ /* See if option is valid and/or required. */
+ *opt = NULL;
+ while (valid) {
+ assert(valid->name);
+ if (STREQ(name, valid->name))
+ break;
+ valid++;
+ }
+ assert(!needData || valid->type != VSH_OT_BOOL);
+ if (valid->flags & VSH_OFLAG_REQ)
+ ret = -1;
+
+ /* See if option is present on command line. */
+ while (candidate) {
+ if (STREQ(candidate->def->name, name)) {
+ *opt = candidate;
+ ret = 1;
+ break;
+ }
+ candidate = candidate->next;
+ }
+ return ret;
+}
+
+/**
+ * vshCommandOptInt:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Convert option to int.
+ * On error, a message is displayed.
+ *
+ * Return value:
+ * >0 if option found and valid (@value updated)
+ * 0 if option not found and not required (@value untouched)
+ * <0 in all other cases (@value untouched)
+ */
+int
+vshCommandOptInt(vshControl *ctl, const vshCmd *cmd,
+ const char *name, int *value)
+{
+ vshCmdOpt *arg;
+ int ret;
+
+ if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
+ return ret;
+
+ if ((ret = virStrToLong_i(arg->data, NULL, 10, value)) < 0)
+ vshError(ctl,
+ _("Numeric value '%s' for <%s> option is malformed or out of range"),
+ arg->data, name);
+ else
+ ret = 1;
+
+ return ret;
+}
+
+static int
+vshCommandOptUIntInternal(vshControl *ctl,
+ const vshCmd *cmd,
+ const char *name,
+ unsigned int *value,
+ bool wrap)
+{
+ vshCmdOpt *arg;
+ int ret;
+
+ if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
+ return ret;
+
+ if (wrap)
+ ret = virStrToLong_ui(arg->data, NULL, 10, value);
+ else
+ ret = virStrToLong_uip(arg->data, NULL, 10, value);
+ if (ret < 0)
+ vshError(ctl,
+ _("Numeric value '%s' for <%s> option is malformed or out of range"),
+ arg->data, name);
+ else
+ ret = 1;
+
+ return ret;
+}
+
+/**
+ * vshCommandOptUInt:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Convert option to unsigned int, reject negative numbers
+ * See vshCommandOptInt()
+ */
+int
+vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned int *value)
+{
+ return vshCommandOptUIntInternal(ctl, cmd, name, value, false);
+}
+
+/**
+ * vshCommandOptUIntWrap:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Convert option to unsigned int, wraps negative numbers to positive
+ * See vshCommandOptInt()
+ */
+int
+vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned int *value)
+{
+ return vshCommandOptUIntInternal(ctl, cmd, name, value, true);
+}
+
+static int
+vshCommandOptULInternal(vshControl *ctl,
+ const vshCmd *cmd,
+ const char *name,
+ unsigned long *value,
+ bool wrap)
+{
+ vshCmdOpt *arg;
+ int ret;
+
+ if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
+ return ret;
+
+ if (wrap)
+ ret = virStrToLong_ul(arg->data, NULL, 10, value);
+ else
+ ret = virStrToLong_ulp(arg->data, NULL, 10, value);
+ if (ret < 0)
+ vshError(ctl,
+ _("Numeric value '%s' for <%s> option is malformed or out of range"),
+ arg->data, name);
+ else
+ ret = 1;
+
+ return ret;
+}
+
+/*
+ * vshCommandOptUL:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Convert option to unsigned long
+ * See vshCommandOptInt()
+ */
+int
+vshCommandOptUL(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long *value)
+{
+ return vshCommandOptULInternal(ctl, cmd, name, value, false);
+}
+
+/**
+ * vshCommandOptULWrap:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Convert option to unsigned long, wraps negative numbers to positive
+ * See vshCommandOptInt()
+ */
+int
+vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long *value)
+{
+ return vshCommandOptULInternal(ctl, cmd, name, value, true);
+}
+
+/**
+ * vshCommandOptString:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Returns option as STRING
+ * Return value:
+ * >0 if option found and valid (@value updated)
+ * 0 if option not found and not required (@value untouched)
+ * <0 in all other cases (@value untouched)
+ */
+int
+vshCommandOptString(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd,
+ const char *name, const char **value)
+{
+ vshCmdOpt *arg;
+ int ret;
+
+ if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
+ return ret;
+
+ if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK))
+ return -1;
+ *value = arg->data;
+ return 1;
+}
+
+/**
+ * vshCommandOptStringReq:
+ * @ctl virtshell control structure
+ * @cmd command structure
+ * @name option name
+ * @value result (updated to NULL or the option argument)
+ *
+ * Gets a option argument as string.
+ *
+ * Returns 0 on success or when the option is not present and not
+ * required, *value is set to the option argument. On error -1 is
+ * returned and error message printed.
+ */
+int
+vshCommandOptStringReq(vshControl *ctl,
+ const vshCmd *cmd,
+ const char *name,
+ const char **value)
+{
+ vshCmdOpt *arg;
+ int ret;
+ const char *error = NULL;
+
+ /* clear out the value */
+ *value = NULL;
+
+ ret = vshCommandOpt(cmd, name, &arg, true);
+ /* option is not required and not present */
+ if (ret == 0)
+ return 0;
+ /* this should not be propagated here, just to be sure */
+ if (ret == -1)
+ error = N_("Mandatory option not present");
+ else if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK))
+ error = N_("Option argument is empty");
+
+ if (error) {
+ vshError(ctl, _("Failed to get option '%s': %s"), name, _(error));
+ return -1;
+ }
+
+ *value = arg->data;
+ return 0;
+}
+
+/**
+ * vshCommandOptLongLong:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Returns option as long long
+ * See vshCommandOptInt()
+ */
+int
+vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd,
+ const char *name, long long *value)
+{
+ vshCmdOpt *arg;
+ int ret;
+
+ if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
+ return ret;
+
+ if ((ret = virStrToLong_ll(arg->data, NULL, 10, value)) < 0)
+ vshError(ctl,
+ _("Numeric value '%s' for <%s> option is malformed or out of range"),
+ arg->data, name);
+ else
+ ret = 1;
+
+ return ret;
+}
+
+static int
+vshCommandOptULongLongInternal(vshControl *ctl,
+ const vshCmd *cmd,
+ const char *name,
+ unsigned long long *value,
+ bool wrap)
+{
+ vshCmdOpt *arg;
+ int ret;
+
+ if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
+ return ret;
+
+ if (wrap)
+ ret = virStrToLong_ull(arg->data, NULL, 10, value);
+ else
+ ret = virStrToLong_ullp(arg->data, NULL, 10, value);
+ if (ret < 0)
+ vshError(ctl,
+ _("Numeric value '%s' for <%s> option is malformed or out of range"),
+ arg->data, name);
+ else
+ ret = 1;
+
+ return ret;
+}
+
+/**
+ * vshCommandOptULongLong:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Returns option as long long, rejects negative numbers
+ * See vshCommandOptInt()
+ */
+int
+vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long long *value)
+{
+ return vshCommandOptULongLongInternal(ctl, cmd, name, value, false);
+}
+
+/**
+ * vshCommandOptULongLongWrap:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Returns option as long long, wraps negative numbers to positive
+ * See vshCommandOptInt()
+ */
+int
+vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long long *value)
+{
+ return vshCommandOptULongLongInternal(ctl, cmd, name, value, true);
+}
+
+/**
+ * vshCommandOptScaledInt:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @name option name
+ * @value result
+ * @scale default of 1 or 1024, if no suffix is present
+ * @max maximum value permitted
+ *
+ * Returns option as long long, scaled according to suffix
+ * See vshCommandOptInt()
+ */
+int
+vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long long *value,
+ int scale, unsigned long long max)
+{
+ vshCmdOpt *arg;
+ char *end;
+ int ret;
+
+ if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
+ return ret;
+ if (virStrToLong_ullp(arg->data, &end, 10, value) < 0 ||
+ virScaleInteger(value, end, scale, max) < 0)
+ {
+ vshError(ctl,
+ _("Numeric value '%s' for <%s> option is malformed or out of range"),
+ arg->data, name);
+ ret = -1;
+ } else {
+ ret = 1;
+ }
+
+ return ret;
+}
+
+
+/**
+ * vshCommandOptBool:
+ * @cmd command reference
+ * @name option name
+ *
+ * Returns true/false if the option exists. Note that this does NOT
+ * validate whether the option is actually boolean, or even whether
+ * name is legal; so that this can be used to probe whether a data
+ * option is present without actually using that data.
+ */
+bool
+vshCommandOptBool(const vshCmd *cmd, const char *name)
+{
+ vshCmdOpt *dummy;
+
+ return vshCommandOpt(cmd, name, &dummy, false) == 1;
+}
+
+/**
+ * vshCommandOptArgv:
+ * @ctl virtshell control structure
+ * @cmd command reference
+ * @opt starting point for the search
+ *
+ * Returns the next argv argument after OPT (or the first one if OPT
+ * is NULL), or NULL if no more are present.
+ *
+ * Requires that a VSH_OT_ARGV option be last in the
+ * list of supported options in CMD->def->opts.
+ */
+const vshCmdOpt *
+vshCommandOptArgv(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd,
+ const vshCmdOpt *opt)
+{
+ opt = opt ? opt->next : cmd->opts;
+
+ while (opt) {
+ if (opt->def->type == VSH_OT_ARGV)
+ return opt;
+ opt = opt->next;
+ }
+ return NULL;
+}
+
+
+/*
+ * Executes command(s) and returns return code from last command
+ */
+bool
+vshCommandRun(vshControl *ctl, const vshCmd *cmd)
+{
+ const vshClientHooks *hooks = ctl->hooks;
+ bool ret = true;
+
+ while (cmd) {
+ struct timeval before, after;
+ bool enable_timing = ctl->timing;
+
+ if (enable_timing)
+ GETTIMEOFDAY(&before);
+
+ if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) ||
+ (hooks && hooks->connHandler && hooks->connHandler(ctl))) {
+ ret = cmd->def->handler(ctl, cmd);
+ } else {
+ /* connection is not usable, return error */
+ ret = false;
+ }
+
+ if (enable_timing)
+ GETTIMEOFDAY(&after);
+
+ /* try to automatically catch disconnections */
+ if (!ret &&
+ ((last_error != NULL) &&
+ (((last_error->code == VIR_ERR_SYSTEM_ERROR) &&
+ (last_error->domain == VIR_FROM_REMOTE)) ||
+ (last_error->code == VIR_ERR_RPC) ||
+ (last_error->code == VIR_ERR_NO_CONNECT) ||
+ (last_error->code == VIR_ERR_INVALID_CONN))))
+ disconnected++;
+
+ if (!ret)
+ vshReportError(ctl);
+
+ if (STREQ(cmd->def->name, "quit") ||
+ STREQ(cmd->def->name, "exit")) /* hack ... */
+ return ret;
+
+ if (enable_timing) {
+ double diff_ms = (((after.tv_sec - before.tv_sec) * 1000.0) +
+ ((after.tv_usec - before.tv_usec) / 1000.0));
+
+ vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"), diff_ms);
+ } else {
+ vshPrintExtra(ctl, "\n");
+ }
+ cmd = cmd->next;
+ }
+ return ret;
+}
+
+/* ---------------
+ * Command parsing
+ * ---------------
+ */
+
+typedef enum {
+ VSH_TK_ERROR, /* Failed to parse a token */
+ VSH_TK_ARG, /* Arbitrary argument, might be option or empty */
+ VSH_TK_SUBCMD_END, /* Separation between commands */
+ VSH_TK_END /* No more commands */
+} vshCommandToken;
+
+typedef struct _vshCommandParser vshCommandParser;
+struct _vshCommandParser {
+ vshCommandToken(*getNextArg)(vshControl *, vshCommandParser *,
+ char **);
+ /* vshCommandStringGetArg() */
+ char *pos;
+ /* vshCommandArgvGetArg() */
+ char **arg_pos;
+ char **arg_end;
+};
+
+static bool
+vshCommandParse(vshControl *ctl, vshCommandParser *parser)
+{
+ char *tkdata = NULL;
+ vshCmd *clast = NULL;
+ vshCmdOpt *first = NULL;
+
+ if (ctl->cmd) {
+ vshCommandFree(ctl->cmd);
+ ctl->cmd = NULL;
+ }
+
+ while (1) {
+ vshCmdOpt *last = NULL;
+ const vshCmdDef *cmd = NULL;
+ vshCommandToken tk;
+ bool data_only = false;
+ uint32_t opts_need_arg = 0;
+ uint32_t opts_required = 0;
+ uint32_t opts_seen = 0;
+
+ first = NULL;
+
+ while (1) {
+ const vshCmdOptDef *opt = NULL;
+
+ tkdata = NULL;
+ tk = parser->getNextArg(ctl, parser, &tkdata);
+
+ if (tk == VSH_TK_ERROR)
+ goto syntaxError;
+ if (tk != VSH_TK_ARG) {
+ VIR_FREE(tkdata);
+ break;
+ }
+
+ if (cmd == NULL) {
+ /* first token must be command name */
+ if (!(cmd = vshCmddefSearch(tkdata))) {
+ vshError(ctl, _("unknown command: '%s'"), tkdata);
+ goto syntaxError; /* ... or ignore this command only? */
+ }
+ if (vshCmddefOptParse(cmd, &opts_need_arg,
+ &opts_required) < 0) {
+ vshError(ctl,
+ _("internal error: bad options in command: '%s'"),
+ tkdata);
+ goto syntaxError;
+ }
+ VIR_FREE(tkdata);
+ } else if (data_only) {
+ goto get_data;
+ } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
+ c_isalnum(tkdata[2])) {
+ char *optstr = strchr(tkdata + 2, '=');
+ int opt_index = 0;
+
+ if (optstr) {
+ *optstr = '\0'; /* convert the '=' to '\0' */
+ optstr = vshStrdup(ctl, optstr + 1);
+ }
+ /* Special case 'help' to ignore all spurious options */
+ if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2,
+ &opts_seen, &opt_index,
+ &optstr))) {
+ VIR_FREE(optstr);
+ if (STREQ(cmd->name, "help"))
+ continue;
+ goto syntaxError;
+ }
+ VIR_FREE(tkdata);
+
+ if (opt->type != VSH_OT_BOOL) {
+ /* option data */
+ if (optstr)
+ tkdata = optstr;
+ else
+ tk = parser->getNextArg(ctl, parser, &tkdata);
+ if (tk == VSH_TK_ERROR)
+ goto syntaxError;
+ if (tk != VSH_TK_ARG) {
+ vshError(ctl,
+ _("expected syntax: --%s <%s>"),
+ opt->name,
+ opt->type ==
+ VSH_OT_INT ? _("number") : _("string"));
+ goto syntaxError;
+ }
+ if (opt->type != VSH_OT_ARGV)
+ opts_need_arg &= ~(1 << opt_index);
+ } else {
+ tkdata = NULL;
+ if (optstr) {
+ vshError(ctl, _("invalid '=' after option --%s"),
+ opt->name);
+ VIR_FREE(optstr);
+ goto syntaxError;
+ }
+ }
+ } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
+ tkdata[2] == '\0') {
+ data_only = true;
+ continue;
+ } else {
+ get_data:
+ /* Special case 'help' to ignore spurious data */
+ if (!(opt = vshCmddefGetData(cmd, &opts_need_arg,
+ &opts_seen)) &&
+ STRNEQ(cmd->name, "help")) {
+ vshError(ctl, _("unexpected data '%s'"), tkdata);
+ goto syntaxError;
+ }
+ }
+ if (opt) {
+ /* save option */
+ vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
+
+ arg->def = opt;
+ arg->data = tkdata;
+ arg->next = NULL;
+ tkdata = NULL;
+
+ if (!first)
+ first = arg;
+ if (last)
+ last->next = arg;
+ last = arg;
+
+ vshDebug(ctl, VSH_ERR_INFO, "%s: %s(%s): %s\n",
+ cmd->name,
+ opt->name,
+ opt->type != VSH_OT_BOOL ? _("optdata") : _("bool"),
+ opt->type != VSH_OT_BOOL ? arg->data : _("(none)"));
+ }
+ }
+
+ /* command parsed -- allocate new struct for the command */
+ if (cmd) {
+ vshCmd *c = vshMalloc(ctl, sizeof(vshCmd));
+ vshCmdOpt *tmpopt = first;
+
+ /* if we encountered --help, replace parsed command with
+ * 'help <cmdname>' */
+ for (tmpopt = first; tmpopt; tmpopt = tmpopt->next) {
+ if (STRNEQ(tmpopt->def->name, "help"))
+ continue;
+
+ const vshCmdDef *help = vshCmddefSearch("help");
+ vshCommandOptFree(first);
+ first = vshMalloc(ctl, sizeof(vshCmdOpt));
+ first->def = help->opts;
+ first->data = vshStrdup(ctl, cmd->name);
+ first->next = NULL;
+
+ cmd = help;
+ opts_required = 0;
+ opts_seen = 0;
+ break;
+ }
+
+ c->opts = first;
+ c->def = cmd;
+ c->next = NULL;
+
+ if (vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0) {
+ VIR_FREE(c);
+ goto syntaxError;
+ }
+
+ if (!ctl->cmd)
+ ctl->cmd = c;
+ if (clast)
+ clast->next = c;
+ clast = c;
+ }
+
+ if (tk == VSH_TK_END)
+ break;
+ }
+
+ return true;
+
+ syntaxError:
+ if (ctl->cmd) {
+ vshCommandFree(ctl->cmd);
+ ctl->cmd = NULL;
+ }
+ if (first)
+ vshCommandOptFree(first);
+ VIR_FREE(tkdata);
+ return false;
+}
+
+/* --------------------
+ * Command argv parsing
+ * --------------------
+ */
+
+static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
+{
+ if (parser->arg_pos == parser->arg_end) {
+ *res = NULL;
+ return VSH_TK_END;
+ }
+
+ *res = vshStrdup(ctl, *parser->arg_pos);
+ parser->arg_pos++;
+ return VSH_TK_ARG;
+}
+
+bool
+vshCommandArgvParse(vshControl *ctl, int nargs, char **argv)
+{
+ vshCommandParser parser;
+
+ if (nargs <= 0)
+ return false;
+
+ parser.arg_pos = argv;
+ parser.arg_end = argv + nargs;
+ parser.getNextArg = vshCommandArgvGetArg;
+ return vshCommandParse(ctl, &parser);
+}
+
+/* ----------------------
+ * Command string parsing
+ * ----------------------
+ */
+
+static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
+{
+ bool single_quote = false;
+ bool double_quote = false;
+ int sz = 0;
+ char *p = parser->pos;
+ char *q = vshStrdup(ctl, p);
+
+ *res = q;
+
+ while (*p && (*p == ' ' || *p == '\t'))
+ p++;
+
+ if (*p == '\0')
+ return VSH_TK_END;
+ if (*p == ';') {
+ parser->pos = ++p; /* = \0 or begin of next command */
+ return VSH_TK_SUBCMD_END;
+ }
+
+ while (*p) {
+ /* end of token is blank space or ';' */
+ if (!double_quote && !single_quote &&
+ (*p == ' ' || *p == '\t' || *p == ';'))
+ break;
+
+ if (!double_quote && *p == '\'') { /* single quote */
+ single_quote = !single_quote;
+ p++;
+ continue;
+ } else if (!single_quote && *p == '\\') { /* escape */
+ /*
+ * The same as the bash, a \ in "" is an escaper,
+ * but a \ in '' is not an escaper.
+ */
+ p++;
+ if (*p == '\0') {
+ vshError(ctl, "%s", _("dangling \\"));
+ return VSH_TK_ERROR;
+ }
+ } else if (!single_quote && *p == '"') { /* double quote */
+ double_quote = !double_quote;
+ p++;
+ continue;
+ }
+
+ *q++ = *p++;
+ sz++;
+ }
+ if (double_quote) {
+ vshError(ctl, "%s", _("missing \""));
+ return VSH_TK_ERROR;
+ }
+
+ *q = '\0';
+ parser->pos = p;
+ return VSH_TK_ARG;
+}
+
+bool
+vshCommandStringParse(vshControl *ctl, char *cmdstr)
+{
+ vshCommandParser parser;
+
+ if (cmdstr == NULL || *cmdstr == '\0')
+ return false;
+
+ parser.pos = cmdstr;
+ parser.getNextArg = vshCommandStringGetArg;
+ return vshCommandParse(ctl, &parser);
+}
+
+/**
+ * virshCommandOptTimeoutToMs:
+ * @ctl virsh control structure
+ * @cmd command reference
+ * @timeout result
+ *
+ * Parse an optional --timeout parameter in seconds, but store the
+ * value of the timeout in milliseconds.
+ * See vshCommandOptInt()
+ */
+int
+vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout)
+{
+ int ret;
+ unsigned int utimeout;
+
+ if ((ret = vshCommandOptUInt(ctl, cmd, "timeout", &utimeout)) <= 0)
+ return ret;
+
+ /* Ensure that the timeout is not zero and that we can convert
+ * it from seconds to milliseconds without overflowing. */
+ if (utimeout == 0 || utimeout > INT_MAX / 1000) {
+ vshError(ctl,
+ _("Numeric value '%u' for <%s> option is malformed or out of range"),
+ utimeout,
+ "timeout");
+ ret = -1;
+ } else {
+ *timeout = ((int) utimeout) * 1000;
+ }
+
+ return ret;
+}
+
+
+/* ---------------
+ * Misc utils
+ * ---------------
+ */
+
+/* Return a non-NULL string representation of a typed parameter; exit
+ * if we are out of memory. */
+char *
+vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item)
+{
+ int ret = 0;
+ char *str = NULL;
+
+ switch (item->type) {
+ case VIR_TYPED_PARAM_INT:
+ ret = virAsprintf(&str, "%d", item->value.i);
+ break;
+
+ case VIR_TYPED_PARAM_UINT:
+ ret = virAsprintf(&str, "%u", item->value.ui);
+ break;
+
+ case VIR_TYPED_PARAM_LLONG:
+ ret = virAsprintf(&str, "%lld", item->value.l);
+ break;
+
+ case VIR_TYPED_PARAM_ULLONG:
+ ret = virAsprintf(&str, "%llu", item->value.ul);
+ break;
+
+ case VIR_TYPED_PARAM_DOUBLE:
+ ret = virAsprintf(&str, "%f", item->value.d);
+ break;
+
+ case VIR_TYPED_PARAM_BOOLEAN:
+ str = vshStrdup(ctl, item->value.b ? _("yes") : _("no"));
+ break;
+
+ case VIR_TYPED_PARAM_STRING:
+ str = vshStrdup(ctl, item->value.s);
+ break;
+
+ default:
+ vshError(ctl, _("unimplemented parameter type %d"), item->type);
+ }
+
+ if (ret < 0) {
+ vshError(ctl, "%s", _("Out of memory"));
+ exit(EXIT_FAILURE);
+ }
+ return str;
+}
+
+void
+vshDebug(vshControl *ctl, int level, const char *format, ...)
+{
+ va_list ap;
+ char *str;
+
+ /* Aligning log levels to that of libvirt.
+ * Traces with levels >= user-specified-level
+ * gets logged into file
+ */
+ if (level < ctl->debug)
+ return;
+
+ va_start(ap, format);
+ vshOutputLogFile(ctl, level, format, ap);
+ va_end(ap);
+
+ va_start(ap, format);
+ if (virVasprintf(&str, format, ap) < 0) {
+ /* Skip debug messages on low memory */
+ va_end(ap);
+ return;
+ }
+ va_end(ap);
+ fputs(str, stdout);
+ VIR_FREE(str);
+}
+
+void
+vshPrintExtra(vshControl *ctl, const char *format, ...)
+{
+ va_list ap;
+ char *str;
+
+ if (ctl && ctl->quiet)
+ return;
+
+ va_start(ap, format);
+ if (virVasprintf(&str, format, ap) < 0) {
+ vshError(ctl, "%s", _("Out of memory"));
+ va_end(ap);
+ return;
+ }
+ va_end(ap);
+ fputs(str, stdout);
+ VIR_FREE(str);
+}
+
+
+bool
+vshTTYIsInterruptCharacter(vshControl *ctl ATTRIBUTE_UNUSED,
+ const char chr ATTRIBUTE_UNUSED)
+{
+#ifndef WIN32
+ if (ctl->istty &&
+ ctl->termattr.c_cc[VINTR] == chr)
+ return true;
+#endif
+
+ return false;
+}
+
+
+bool
+vshTTYAvailable(vshControl *ctl)
+{
+ return ctl->istty;
+}
+
+
+int
+vshTTYDisableInterrupt(vshControl *ctl ATTRIBUTE_UNUSED)
+{
+#ifndef WIN32
+ struct termios termset = ctl->termattr;
+
+ if (!ctl->istty)
+ return -1;
+
+ /* check if we need to set the terminal */
+ if (termset.c_cc[VINTR] == _POSIX_VDISABLE)
+ return 0;
+
+ termset.c_cc[VINTR] = _POSIX_VDISABLE;
+ termset.c_lflag &= ~ICANON;
+
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &termset) < 0)
+ return -1;
+#endif
+
+ return 0;
+}
+
+
+int
+vshTTYRestore(vshControl *ctl ATTRIBUTE_UNUSED)
+{
+#ifndef WIN32
+ if (!ctl->istty)
+ return 0;
+
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &ctl->termattr) < 0)
+ return -1;
+#endif
+
+ return 0;
+}
+
+
+#if !defined(WIN32) && !defined(HAVE_CFMAKERAW)
+/* provide fallback in case cfmakeraw isn't available */
+static void
+cfmakeraw(struct termios *attr)
+{
+ attr->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
+ | INLCR | IGNCR | ICRNL | IXON);
+ attr->c_oflag &= ~OPOST;
+ attr->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ attr->c_cflag &= ~(CSIZE | PARENB);
+ attr->c_cflag |= CS8;
+}
+#endif /* !WIN32 && !HAVE_CFMAKERAW */
+
+
+int
+vshTTYMakeRaw(vshControl *ctl ATTRIBUTE_UNUSED,
+ bool report_errors ATTRIBUTE_UNUSED)
+{
+#ifndef WIN32
+ struct termios rawattr = ctl->termattr;
+ char ebuf[1024];
+
+ if (!ctl->istty) {
+ if (report_errors) {
+ vshError(ctl, "%s",
+ _("unable to make terminal raw: console isn't a tty"));
+ }
+
+ return -1;
+ }
+
+ cfmakeraw(&rawattr);
+
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
+ if (report_errors)
+ vshError(ctl, _("unable to set tty attributes: %s"),
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+
+void
+vshError(vshControl *ctl, const char *format, ...)
+{
+ va_list ap;
+ char *str;
+
+ if (ctl != NULL) {
+ va_start(ap, format);
+ vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
+ va_end(ap);
+ }
+
+ /* Most output is to stdout, but if someone ran virsh 2>&1, then
+ * printing to stderr will not interleave correctly with stdout
+ * unless we flush between every transition between streams. */
+ fflush(stdout);
+ fputs(_("error: "), stderr);
+
+ va_start(ap, format);
+ /* We can't recursively call vshError on an OOM situation, so ignore
+ failure here. */
+ ignore_value(virVasprintf(&str, format, ap));
+ va_end(ap);
+
+ fprintf(stderr, "%s\n", NULLSTR(str));
+ fflush(stderr);
+ VIR_FREE(str);
+}
+
+
+void
+vshEventLoop(void *opaque)
+{
+ vshControl *ctl = opaque;
+
+ while (1) {
+ bool quit;
+ virMutexLock(&ctl->lock);
+ quit = ctl->quit;
+ virMutexUnlock(&ctl->lock);
+
+ if (quit)
+ break;
+
+ if (virEventRunDefaultImpl() < 0)
+ vshReportError(ctl);
+ }
+}
+
+
+/*
+ * Helpers for waiting for a libvirt event.
+ */
+
+/* We want to use SIGINT to cancel a wait; but as signal handlers
+ * don't have an opaque argument, we have to use static storage. */
+static int vshEventFd = -1;
+static struct sigaction vshEventOldAction;
+
+
+/* Signal handler installed in vshEventStart, removed in vshEventCleanup. */
+static void
+vshEventInt(int sig ATTRIBUTE_UNUSED,
+ siginfo_t *siginfo ATTRIBUTE_UNUSED,
+ void *context ATTRIBUTE_UNUSED)
+{
+ char reason = VSH_EVENT_INTERRUPT;
+ if (vshEventFd >= 0)
+ ignore_value(safewrite(vshEventFd, &reason, 1));
+}
+
+
+/* Event loop handler used to limit length of waiting for any other event. */
+void
+vshEventTimeout(int timer ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ vshControl *ctl = opaque;
+ char reason = VSH_EVENT_TIMEOUT;
+
+ if (ctl->eventPipe[1] >= 0)
+ ignore_value(safewrite(ctl->eventPipe[1], &reason, 1));
+}
+
+
+/**
+ * vshEventStart:
+ * @ctl vsh command struct
+ * @timeout_ms max wait time in milliseconds, or 0 for indefinite
+ *
+ * Set up a wait for a libvirt event. The wait can be canceled by
+ * SIGINT or by calling vshEventDone() in your event handler. If
+ * @timeout_ms is positive, the wait will also end if the timeout
+ * expires. Call vshEventWait() to block the main thread (the event
+ * handler runs in the event loop thread). When done (including if
+ * there was an error registering for an event), use vshEventCleanup()
+ * to quit waiting. Returns 0 on success, -1 on failure. */
+int
+vshEventStart(vshControl *ctl, int timeout_ms)
+{
+ struct sigaction action;
+
+ assert(ctl->eventPipe[0] == -1 && ctl->eventPipe[1] == -1 &&
+ vshEventFd == -1 && ctl->eventTimerId >= 0);
+ if (pipe2(ctl->eventPipe, O_CLOEXEC) < 0) {
+ char ebuf[1024];
+
+ vshError(ctl, _("failed to create pipe: %s"),
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ return -1;
+ }
+ vshEventFd = ctl->eventPipe[1];
+
+ action.sa_sigaction = vshEventInt;
+ action.sa_flags = SA_SIGINFO;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGINT, &action, &vshEventOldAction);
+
+ if (timeout_ms)
+ virEventUpdateTimeout(ctl->eventTimerId, timeout_ms);
+
+ return 0;
+}
+
+
+/**
+ * vshEventDone:
+ * @ctl vsh command struct
+ *
+ * Call this from an event callback to let the main thread quit
+ * blocking on further events.
+ */
+void
+vshEventDone(vshControl *ctl)
+{
+ char reason = VSH_EVENT_DONE;
+
+ if (ctl->eventPipe[1] >= 0)
+ ignore_value(safewrite(ctl->eventPipe[1], &reason, 1));
+}
+
+
+/**
+ * vshEventWait:
+ * @ctl vsh command struct
+ *
+ * Call this in the main thread after calling vshEventStart() then
+ * registering for one or more events. This call will block until
+ * SIGINT, the timeout registered at the start, or until one of your
+ * event handlers calls vshEventDone(). Returns an enum VSH_EVENT_*
+ * stating how the wait concluded, or -1 on error.
+ */
+int
+vshEventWait(vshControl *ctl)
+{
+ char buf;
+ int rv;
+
+ assert(ctl->eventPipe[0] >= 0);
+ while ((rv = read(ctl->eventPipe[0], &buf, 1)) < 0 && errno == EINTR);
+ if (rv != 1) {
+ char ebuf[1024];
+
+ if (!rv)
+ errno = EPIPE;
+ vshError(ctl, _("failed to determine loop exit status: %s"),
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ return -1;
+ }
+ return buf;
+}
+
+
+/**
+ * vshEventCleanup:
+ * @ctl vsh control struct
+ *
+ * Call at the end of any function that has used vshEventStart(), to
+ * tear down any remaining SIGINT or timeout handlers.
+ */
+void
+vshEventCleanup(vshControl *ctl)
+{
+ if (vshEventFd >= 0) {
+ sigaction(SIGINT, &vshEventOldAction, NULL);
+ vshEventFd = -1;
+ }
+ VIR_FORCE_CLOSE(ctl->eventPipe[0]);
+ VIR_FORCE_CLOSE(ctl->eventPipe[1]);
+ virEventUpdateTimeout(ctl->eventTimerId, -1);
+}
+
+#define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)
+
+/**
+ * vshOpenLogFile:
+ *
+ * Open log file.
+ */
+void
+vshOpenLogFile(vshControl *ctl)
+{
+ if (ctl->logfile == NULL)
+ return;
+
+ if ((ctl->log_fd = open(ctl->logfile, LOGFILE_FLAGS, FILE_MODE)) < 0) {
+ vshError(ctl, "%s",
+ _("failed to open the log file. check the log file path"));
+ exit(EXIT_FAILURE);
+ }
+}
+
+/**
+ * vshOutputLogFile:
+ *
+ * Outputting an error to log file.
+ */
+void
+vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format,
+ va_list ap)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *str = NULL;
+ size_t len;
+ const char *lvl = "";
+ time_t stTime;
+ struct tm stTm;
+
+ if (ctl->log_fd == -1)
+ return;
+
+ /**
+ * create log format
+ *
+ * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
+ */
+ time(&stTime);
+ localtime_r(&stTime, &stTm);
+ virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s %d] ",
+ (1900 + stTm.tm_year),
+ (1 + stTm.tm_mon),
+ stTm.tm_mday,
+ stTm.tm_hour,
+ stTm.tm_min,
+ stTm.tm_sec,
+ ctl->progname,
+ (int) getpid());
+ switch (log_level) {
+ case VSH_ERR_DEBUG:
+ lvl = LVL_DEBUG;
+ break;
+ case VSH_ERR_INFO:
+ lvl = LVL_INFO;
+ break;
+ case VSH_ERR_NOTICE:
+ lvl = LVL_INFO;
+ break;
+ case VSH_ERR_WARNING:
+ lvl = LVL_WARNING;
+ break;
+ case VSH_ERR_ERROR:
+ lvl = LVL_ERROR;
+ break;
+ default:
+ lvl = LVL_DEBUG;
+ break;
+ }
+ virBufferAsprintf(&buf, "%s ", lvl);
+ virBufferVasprintf(&buf, msg_format, ap);
+ virBufferAddChar(&buf, '\n');
+
+ if (virBufferError(&buf))
+ goto error;
+
+ str = virBufferContentAndReset(&buf);
+ len = strlen(str);
+ if (len > 1 && str[len - 2] == '\n') {
+ str[len - 1] = '\0';
+ len--;
+ }
+
+ /* write log */
+ if (safewrite(ctl->log_fd, str, len) < 0)
+ goto error;
+
+ VIR_FREE(str);
+ return;
+
+ error:
+ vshCloseLogFile(ctl);
+ vshError(ctl, "%s", _("failed to write the log file"));
+ virBufferFreeAndReset(&buf);
+ VIR_FREE(str);
+}
+
+/**
+ * vshCloseLogFile:
+ *
+ * Close log file.
+ */
+void
+vshCloseLogFile(vshControl *ctl)
+{
+ char ebuf[1024];
+
+ /* log file close */
+ if (VIR_CLOSE(ctl->log_fd) < 0) {
+ vshError(ctl, _("%s: failed to write log file: %s"),
+ ctl->logfile ? ctl->logfile : "?",
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ }
+
+ if (ctl->logfile) {
+ VIR_FREE(ctl->logfile);
+ ctl->logfile = NULL;
+ }
+}
+
+#ifndef WIN32
+static void
+vshPrintRaw(vshControl *ctl, ...)
+{
+ va_list ap;
+ char *key;
+
+ va_start(ap, ctl);
+ while ((key = va_arg(ap, char *)) != NULL)
+ vshPrint(ctl, "%s\r\n", key);
+ va_end(ap);
+}
+
+/**
+ * vshAskReedit:
+ * @msg: Question to ask user
+ *
+ * Ask user if he wants to return to previously
+ * edited file.
+ *
+ * Returns 'y' if he wants to
+ * 'n' if he doesn't want to
+ * 'i' if he wants to try defining it again while ignoring validation
+ * 'f' if he forcibly wants to
+ * -1 on error
+ * 0 otherwise
+ */
+int
+vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail)
+{
+ int c = -1;
+
+ if (!isatty(STDIN_FILENO))
+ return -1;
+
+ vshReportError(ctl);
+
+ if (vshTTYMakeRaw(ctl, false) < 0)
+ return -1;
+
+ while (true) {
+ vshPrint(ctl, "\r%s %s %s: ", msg, _("Try again?"),
+ relax_avail ? "[y,n,i,f,?]" : "[y,n,f,?]");
+ c = c_tolower(getchar());
+
+ if (c == '?') {
+ vshPrintRaw(ctl,
+ "",
+ _("y - yes, start editor again"),
+ _("n - no, throw away my changes"),
+ NULL);
+
+ if (relax_avail) {
+ vshPrintRaw(ctl,
+ _("i - turn off validation and try to redefine "
+ "again"),
+ NULL);
+ }
+
+ vshPrintRaw(ctl,
+ _("f - force, try to redefine again"),
+ _("? - print this help"),
+ NULL);
+ continue;
+ } else if (c == 'y' || c == 'n' || c == 'f' ||
+ (relax_avail && c == 'i')) {
+ break;
+ }
+ }
+
+ vshTTYRestore(ctl);
+
+ vshPrint(ctl, "\r\n");
+ return c;
+}
+#else /* WIN32 */
+int
+vshAskReedit(vshControl *ctl,
+ const char *msg ATTRIBUTE_UNUSED,
+ bool relax_avail ATTRIBUTE_UNUSED)
+{
+ vshDebug(ctl, VSH_ERR_WARNING, "%s", _("This function is not "
+ "supported on WIN32 platform"));
+ return 0;
+}
+#endif /* WIN32 */
+
+
+/* Common code for the edit / net-edit / pool-edit functions which follow. */
+char *
+vshEditWriteToTempFile(vshControl *ctl, const char *doc)
+{
+ char *ret;
+ const char *tmpdir;
+ int fd;
+ char ebuf[1024];
+
+ tmpdir = virGetEnvBlockSUID("TMPDIR");
+ if (!tmpdir) tmpdir = "/tmp";
+ if (virAsprintf(&ret, "%s/virshXXXXXX.xml", tmpdir) < 0) {
+ vshError(ctl, "%s", _("out of memory"));
+ return NULL;
+ }
+ fd = mkostemps(ret, 4, O_CLOEXEC);
+ if (fd == -1) {
+ vshError(ctl, _("mkostemps: failed to create temporary file: %s"),
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ VIR_FREE(ret);
+ return NULL;
+ }
+
+ if (safewrite(fd, doc, strlen(doc)) == -1) {
+ vshError(ctl, _("write: %s: failed to write to temporary file: %s"),
+ ret, virStrerror(errno, ebuf, sizeof(ebuf)));
+ VIR_FORCE_CLOSE(fd);
+ unlink(ret);
+ VIR_FREE(ret);
+ return NULL;
+ }
+ if (VIR_CLOSE(fd) < 0) {
+ vshError(ctl, _("close: %s: failed to write or close temporary file: %s"),
+ ret, virStrerror(errno, ebuf, sizeof(ebuf)));
+ unlink(ret);
+ VIR_FREE(ret);
+ return NULL;
+ }
+
+ /* Temporary filename: caller frees. */
+ return ret;
+}
+
+/* Characters permitted in $EDITOR environment variable and temp filename. */
+#define ACCEPTED_CHARS \
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@"
+
+int
+vshEditFile(vshControl *ctl, const char *filename)
+{
+ const char *editor;
+ virCommandPtr cmd;
+ int ret = -1;
+ int outfd = STDOUT_FILENO;
+ int errfd = STDERR_FILENO;
+
+ editor = virGetEnvBlockSUID("VISUAL");
+ if (!editor)
+ editor = virGetEnvBlockSUID("EDITOR");
+ if (!editor)
+ editor = DEFAULT_EDITOR;
+
+ /* Check that filename doesn't contain shell meta-characters, and
+ * if it does, refuse to run. Follow the Unix conventions for
+ * EDITOR: the user can intentionally specify command options, so
+ * we don't protect any shell metacharacters there. Lots more
+ * than virsh will misbehave if EDITOR has bogus contents (which
+ * is why sudo scrubs it by default). Conversely, if the editor
+ * is safe, we can run it directly rather than wasting a shell.
+ */
+ if (strspn(editor, ACCEPTED_CHARS) != strlen(editor)) {
+ if (strspn(filename, ACCEPTED_CHARS) != strlen(filename)) {
+ vshError(ctl,
+ _("%s: temporary filename contains shell meta or other "
+ "unacceptable characters (is $TMPDIR wrong?)"),
+ filename);
+ return -1;
+ }
+ cmd = virCommandNewArgList("sh", "-c", NULL);
+ virCommandAddArgFormat(cmd, "%s %s", editor, filename);
+ } else {
+ cmd = virCommandNewArgList(editor, filename, NULL);
+ }
+
+ virCommandSetInputFD(cmd, STDIN_FILENO);
+ virCommandSetOutputFD(cmd, &outfd);
+ virCommandSetErrorFD(cmd, &errfd);
+ if (virCommandRunAsync(cmd, NULL) < 0 ||
+ virCommandWait(cmd, NULL) < 0) {
+ vshReportError(ctl);
+ goto cleanup;
+ }
+ ret = 0;
+
+ cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
+
+char *
+vshEditReadBackFile(vshControl *ctl, const char *filename)
+{
+ char *ret;
+ char ebuf[1024];
+
+ if (virFileReadAll(filename, VSH_MAX_XML_FILE, &ret) == -1) {
+ vshError(ctl,
+ _("%s: failed to read temporary file: %s"),
+ filename, virStrerror(errno, ebuf, sizeof(ebuf)));
+ return NULL;
+ }
+ return ret;
+}
+
+
+/* Tree listing helpers. */
+
+static int
+vshTreePrintInternal(vshControl *ctl,
+ vshTreeLookup lookup,
+ void *opaque,
+ int num_devices,
+ int devid,
+ int lastdev,
+ bool root,
+ virBufferPtr indent)
+{
+ size_t i;
+ int nextlastdev = -1;
+ int ret = -1;
+ const char *dev = (lookup)(devid, false, opaque);
+
+ if (virBufferError(indent))
+ goto cleanup;
+
+ /* Print this device, with indent if not at root */
+ vshPrint(ctl, "%s%s%s\n", virBufferCurrentContent(indent),
+ root ? "" : "+- ", dev);
+
+ /* Update indent to show '|' or ' ' for child devices */
+ if (!root) {
+ virBufferAddChar(indent, devid == lastdev ? ' ' : '|');
+ virBufferAddChar(indent, ' ');
+ if (virBufferError(indent))
+ goto cleanup;
+ }
+
+ /* Determine the index of the last child device */
+ for (i = 0; i < num_devices; i++) {
+ const char *parent = (lookup)(i, true, opaque);
+
+ if (parent && STREQ(parent, dev))
+ nextlastdev = i;
+ }
+
+ /* If there is a child device, then print another blank line */
+ if (nextlastdev != -1)
+ vshPrint(ctl, "%s |\n", virBufferCurrentContent(indent));
+
+ /* Finally print all children */
+ virBufferAddLit(indent, " ");
+ if (virBufferError(indent))
+ goto cleanup;
+ for (i = 0; i < num_devices; i++) {
+ const char *parent = (lookup)(i, true, opaque);
+
+ if (parent && STREQ(parent, dev) &&
+ vshTreePrintInternal(ctl, lookup, opaque,
+ num_devices, i, nextlastdev,
+ false, indent) < 0)
+ goto cleanup;
+ }
+ virBufferTrim(indent, " ", -1);
+
+ /* If there was no child device, and we're the last in
+ * a list of devices, then print another blank line */
+ if (nextlastdev == -1 && devid == lastdev)
+ vshPrint(ctl, "%s\n", virBufferCurrentContent(indent));
+
+ if (!root)
+ virBufferTrim(indent, NULL, 2);
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
+int
+vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
+ int num_devices, int devid)
+{
+ int ret;
+ virBuffer indent = VIR_BUFFER_INITIALIZER;
+
+ ret = vshTreePrintInternal(ctl, lookup, opaque, num_devices,
+ devid, devid, true, &indent);
+ if (ret < 0)
+ vshError(ctl, "%s", _("Failed to complete tree listing"));
+ virBufferFreeAndReset(&indent);
+ return ret;
+}
+
+#if WITH_READLINE
+
+/* -----------------
+ * Readline stuff
+ * -----------------
+ */
+
+/*
+ * Generator function for command completion. STATE lets us
+ * know whether to start from scratch; without any state
+ * (i.e. STATE == 0), then we start at the top of the list.
+ */
+static char *
+vshReadlineCommandGenerator(const char *text, int state)
+{
+ static int grp_list_index, cmd_list_index, len;
+ const char *name;
+ const vshCmdGrp *grp;
+ const vshCmdDef *cmds;
+
+ if (!state) {
+ grp_list_index = 0;
+ cmd_list_index = 0;
+ len = strlen(text);
+ }
+
+ grp = cmdGroups;
+
+ /* Return the next name which partially matches from the
+ * command list.
+ */
+ while (grp[grp_list_index].name) {
+ cmds = grp[grp_list_index].commands;
+
+ if (cmds[cmd_list_index].name) {
+ while ((name = cmds[cmd_list_index].name)) {
+ cmd_list_index++;
+
+ if (STREQLEN(name, text, len))
+ return vshStrdup(NULL, name);
+ }
+ } else {
+ cmd_list_index = 0;
+ grp_list_index++;
+ }
+ }
+
+ /* If no names matched, then return NULL. */
+ return NULL;
+}
+
+static char *
+vshReadlineOptionsGenerator(const char *text, int state)
+{
+ static int list_index, len;
+ static const vshCmdDef *cmd;
+ const char *name;
+
+ if (!state) {
+ /* determine command name */
+ char *p;
+ char *cmdname;
+
+ if (!(p = strchr(rl_line_buffer, ' ')))
+ return NULL;
+
+ cmdname = vshCalloc(NULL, (p - rl_line_buffer) + 1, 1);
+ memcpy(cmdname, rl_line_buffer, p - rl_line_buffer);
+
+ cmd = vshCmddefSearch(cmdname);
+ list_index = 0;
+ len = strlen(text);
+ VIR_FREE(cmdname);
+ }
+
+ if (!cmd)
+ return NULL;
+
+ if (!cmd->opts)
+ return NULL;
+
+ while ((name = cmd->opts[list_index].name)) {
+ const vshCmdOptDef *opt = &cmd->opts[list_index];
+ char *res;
+
+ list_index++;
+
+ if (opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV)
+ /* ignore non --option */
+ continue;
+
+ if (len > 2) {
+ if (STRNEQLEN(name, text + 2, len - 2))
+ continue;
+ }
+ res = vshMalloc(NULL, strlen(name) + 3);
+ snprintf(res, strlen(name) + 3, "--%s", name);
+ return res;
+ }
+
+ /* If no names matched, then return NULL. */
+ return NULL;
+}
+
+static char **
+vshReadlineCompletion(const char *text, int start,
+ int end ATTRIBUTE_UNUSED)
+{
+ char **matches = (char **) NULL;
+
+ if (start == 0)
+ /* command name generator */
+ matches = rl_completion_matches(text, vshReadlineCommandGenerator);
+ else
+ /* commands options */
+ matches = rl_completion_matches(text, vshReadlineOptionsGenerator);
+ return matches;
+}
+
+# define HISTSIZE_MAX 500000
+
+static int
+vshReadlineInit(vshControl *ctl)
+{
+ char *userdir = NULL;
+ char *name_capitalized = NULL;
+ int max_history = 500;
+ int ret = -1;
+ const char *histsize_str = NULL;
+ const char *histsize_env = NULL;
+ const char *strings[] = {
+ name_capitalized,
+ "HISTSIZE",
+ NULL
+ };
+
+ /* Allow conditional parsing of the ~/.inputrc file.
+ * Work around ancient readline 4.1 (hello Mac OS X),
+ * which declared it as 'char *' instead of 'const char *'.
+ */
+ rl_readline_name = ctl->name;
+
+ /* Tell the completer that we want a crack first. */
+ rl_attempted_completion_function = vshReadlineCompletion;
+
+ if (virStringToUpper(&name_capitalized, ctl->name) < 0 ||
+ !(histsize_env = virStringJoin(strings, "_")))
+ goto cleanup;
+
+ /* Limit the total size of the history buffer */
+ if ((histsize_str = virGetEnvBlockSUID(histsize_env))) {
+ if (virStrToLong_i(histsize_str, NULL, 10, &max_history) < 0) {
+ vshError(ctl, _("Bad $%s value."), histsize_env);
+ goto cleanup;
+ } else if (max_history > HISTSIZE_MAX || max_history < 0) {
+ vshError(ctl, _("$%s value should be between 0 "
+ "and %d"),
+ histsize_env, HISTSIZE_MAX);
+ goto cleanup;
+ }
+ }
+ stifle_history(max_history);
+
+ /* Prepare to read/write history from/to the
+ * $XDG_CACHE_HOME/virtshell/history file
+ */
+ userdir = virGetUserCacheDirectory();
+
+ if (userdir == NULL) {
+ vshError(ctl, "%s", _("Could not determine home directory"));
+ goto cleanup;
+ }
+
+ if (virAsprintf(&ctl->historydir, "%s/%s", userdir, ctl->name) < 0) {
+ vshError(ctl, "%s", _("Out of memory"));
+ goto cleanup;
+ }
+
+ if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir) < 0) {
+ vshError(ctl, "%s", _("Out of memory"));
+ goto cleanup;
+ }
+
+ read_history(ctl->historyfile);
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(userdir);
+ VIR_FREE(name_capitalized);
+ return ret;
+}
+
+static void
+vshReadlineDeinit(vshControl *ctl)
+{
+ if (ctl->historyfile != NULL) {
+ if (virFileMakePathWithMode(ctl->historydir, 0755) < 0 &&
+ errno != EEXIST) {
+ char ebuf[1024];
+ vshError(ctl, _("Failed to create '%s': %s"),
+ ctl->historydir, virStrerror(errno, ebuf, sizeof(ebuf)));
+ } else {
+ write_history(ctl->historyfile);
+ }
+ }
+
+ VIR_FREE(ctl->historydir);
+ VIR_FREE(ctl->historyfile);
+}
+
+char *
+vshReadline(vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt)
+{
+ return readline(prompt);
+}
+
+#else /* !WITH_READLINE */
+
+static int
+vshReadlineInit(vshControl *ctl ATTRIBUTE_UNUSED)
+{
+ /* empty */
+ return 0;
+}
+
+static void
+vshReadlineDeinit(vshControl *ctl ATTRIBUTE_UNUSED)
+{
+ /* empty */
+}
+
+static char *
+vshReadline(vshControl *ctl, const char *prompt)
+{
+ char line[1024];
+ char *r;
+ int len;
+
+ fputs(prompt, stdout);
+ r = fgets(line, sizeof(line), stdin);
+ if (r == NULL) return NULL; /* EOF */
+
+ /* Chomp trailing \n */
+ len = strlen(r);
+ if (len > 0 && r[len-1] == '\n')
+ r[len-1] = '\0';
+
+ return vshStrdup(ctl, r);
+}
+
+#endif /* !WITH_READLINE */
+
+/*
+ * Initialize debug settings.
+ */
+void
+vshInitDebug(vshControl *ctl)
+{
+ const char *debugEnv;
+
+ if (ctl->debug == VSH_DEBUG_DEFAULT) {
+ /* log level not set from commandline, check env variable */
+ debugEnv = virGetEnvAllowSUID("VSH_DEBUG");
+ if (debugEnv) {
+ int debug;
+ if (virStrToLong_i(debugEnv, NULL, 10, &debug) < 0 ||
+ debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) {
+ vshError(ctl, "%s",
+ _("VSH_DEBUG not set with a valid numeric value"));
+ } else {
+ ctl->debug = debug;
+ }
+ }
+ }
+
+ if (ctl->logfile == NULL) {
+ /* log file not set from cmdline */
+ debugEnv = virGetEnvBlockSUID("VSH_LOG_FILE");
+ if (debugEnv && *debugEnv) {
+ ctl->logfile = vshStrdup(ctl, debugEnv);
+ vshOpenLogFile(ctl);
+ }
+ }
+}
+
+
+/*
+ * Initialize global data
+ */
+int
+vshInit(vshControl *ctl, const vshCmdGrp *groups, const vshCmdDef *set)
+{
+ int ret = -1;
+
+ if (!ctl->hooks) {
+ vshError(ctl, "%s", _("client hooks cannot be NULL"));
+ goto error;
+ }
+
+ if (!groups && !set) {
+ vshError(ctl, "%s", _("command groups and command set "
+ "cannot both be NULL"));
+ goto error;
+ }
+
+ cmdGroups = groups;
+ cmdSet = set;
+ vshInitDebug(ctl);
+
+ if (ctl->imode && vshReadlineInit(ctl) < 0)
+ goto error;
+
+ ret = 0;
+ error:
+ return ret;
+}
+
+void
+vshDeinit(vshControl *ctl)
+{
+ if (ctl->imode)
+ vshReadlineDeinit(ctl);
+ vshCloseLogFile(ctl);
+}
+
+/* -----------------------------------------------
+ * Generic commands available to use by any client
+ * -----------------------------------------------
+ */
+const vshCmdOptDef opts_help[] = {
+ {.name = "command",
+ .type = VSH_OT_STRING,
+ .help = N_("Prints global help, command specific help, or help for a group of related commands")
+ },
+ {.name = NULL}
+};
+
+const vshCmdInfo info_help[] = {
+ {.name = "help",
+ .data = N_("print help")
+ },
+ {.name = "desc",
+ .data = N_("Prints global help, command specific help, or help for a\n"
+ " group of related commands")
+ },
+ {.name = NULL}
+};
+
+bool
+cmdHelp(vshControl *ctl, const vshCmd *cmd)
+ {
+ const char *name = NULL;
+
+ if (vshCommandOptString(ctl, cmd, "command", &name) <= 0) {
+ const vshCmdGrp *grp;
+ const vshCmdDef *def;
+
+ vshPrint(ctl, "%s", _("Grouped commands:\n\n"));
+
+ for (grp = cmdGroups; grp->name; grp++) {
+ vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
+ grp->keyword);
+
+ for (def = grp->commands; def->name; def++) {
+ if (def->flags & VSH_CMD_FLAG_ALIAS)
+ continue;
+ vshPrint(ctl, " %-30s %s\n", def->name,
+ _(vshCmddefGetInfo(def, "help")));
+ }
+
+ vshPrint(ctl, "\n");
+ }
+
+ return true;
+ }
+
+ if (vshCmddefSearch(name)) {
+ return vshCmddefHelp(ctl, name);
+ } else if (vshCmdGrpSearch(name)) {
+ return vshCmdGrpHelp(ctl, name);
+ } else {
+ vshError(ctl, _("command or command group '%s' doesn't exist"), name);
+ return false;
+ }
+}
+
+const vshCmdOptDef opts_cd[] = {
+ {.name = "dir",
+ .type = VSH_OT_STRING,
+ .help = N_("directory to switch to (default: home or else root)")
+ },
+ {.name = NULL}
+};
+
+const vshCmdInfo info_cd[] = {
+ {.name = "help",
+ .data = N_("change the current directory")
+ },
+ {.name = "desc",
+ .data = N_("Change the current directory.")
+ },
+ {.name = NULL}
+};
+
+bool
+cmdCd(vshControl *ctl, const vshCmd *cmd)
+{
+ const char *dir = NULL;
+ char *dir_malloced = NULL;
+ bool ret = true;
+ char ebuf[1024];
+
+ if (!ctl->imode) {
+ vshError(ctl, "%s", _("cd: command valid only in interactive mode"));
+ return false;
+ }
+
+ if (vshCommandOptString(ctl, cmd, "dir", &dir) <= 0)
+ dir = dir_malloced = virGetUserDirectory();
+ if (!dir)
+ dir = "/";
+
+ if (chdir(dir) == -1) {
+ vshError(ctl, _("cd: %s: %s"),
+ virStrerror(errno, ebuf, sizeof(ebuf)), dir);
+ ret = false;
+ }
+
+ VIR_FREE(dir_malloced);
+ return ret;
+}
+
+const vshCmdOptDef opts_echo[] = {
+ {.name = "shell",
+ .type = VSH_OT_BOOL,
+ .help = N_("escape for shell use")
+ },
+ {.name = "xml",
+ .type = VSH_OT_BOOL,
+ .help = N_("escape for XML use")
+ },
+ {.name = "str",
+ .type = VSH_OT_ALIAS,
+ .help = "string"
+ },
+ {.name = "hi",
+ .type = VSH_OT_ALIAS,
+ .help = "string=hello"
+ },
+ {.name = "string",
+ .type = VSH_OT_ARGV,
+ .help = N_("arguments to echo")
+ },
+ {.name = NULL}
+};
+
+const vshCmdInfo info_echo[] = {
+ {.name = "help",
+ .data = N_("echo arguments")
+ },
+ {.name = "desc",
+ .data = N_("Echo back arguments, possibly with quoting.")
+ },
+ {.name = NULL}
+};
+
+/* Exists mainly for debugging virsh, but also handy for adding back
+ * quotes for later evaluation.
+ */
+bool
+cmdEcho(vshControl *ctl, const vshCmd *cmd)
+{
+ bool shell = false;
+ bool xml = false;
+ int count = 0;
+ const vshCmdOpt *opt = NULL;
+ char *arg;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ if (vshCommandOptBool(cmd, "shell"))
+ shell = true;
+ if (vshCommandOptBool(cmd, "xml"))
+ xml = true;
+
+ while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
+ char *str;
+ virBuffer xmlbuf = VIR_BUFFER_INITIALIZER;
+
+ arg = opt->data;
+
+ if (count)
+ virBufferAddChar(&buf, ' ');
+
+ if (xml) {
+ virBufferEscapeString(&xmlbuf, "%s", arg);
+ if (virBufferError(&xmlbuf)) {
+ vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+ return false;
+ }
+ str = virBufferContentAndReset(&xmlbuf);
+ } else {
+ str = vshStrdup(ctl, arg);
+ }
+
+ if (shell)
+ virBufferEscapeShell(&buf, str);
+ else
+ virBufferAdd(&buf, str, -1);
+ count++;
+ VIR_FREE(str);
+ }
+
+ if (virBufferError(&buf)) {
+ vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+ return false;
+ }
+ arg = virBufferContentAndReset(&buf);
+ if (arg)
+ vshPrint(ctl, "%s", arg);
+ VIR_FREE(arg);
+ return true;
+}
+
+const vshCmdInfo info_pwd[] = {
+ {.name = "help",
+ .data = N_("print the current directory")
+ },
+ {.name = "desc",
+ .data = N_("Print the current directory.")
+ },
+ {.name = NULL}
+};
+
+bool
+cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ char *cwd;
+ bool ret = true;
+ char ebuf[1024];
+
+ cwd = getcwd(NULL, 0);
+ if (!cwd) {
+ vshError(ctl, _("pwd: cannot get current directory: %s"),
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ ret = false;
+ } else {
+ vshPrint(ctl, _("%s\n"), cwd);
+ VIR_FREE(cwd);
+ }
+
+ return ret;
+}
+
+const vshCmdInfo info_quit[] = {
+ {.name = "help",
+ .data = N_("quit this interactive terminal")
+ },
+ {.name = "desc",
+ .data = ""
+ },
+ {.name = NULL}
+};
+
+bool
+cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ ctl->imode = false;
+ return true;
+}
--- /dev/null
+/*
+ * vsh.h: common data to be used by clients to exercise the libvirt API
+ *
+ * Copyright (C) 2005, 2007-2015 Red Hat, Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ * Karel Zak <kzak@redhat.com>
+ * Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#ifndef VSH_H
+# define VSH_H
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <stdarg.h>
+# include <unistd.h>
+# include <sys/stat.h>
+# include <termios.h>
+
+# include "internal.h"
+# include "virerror.h"
+# include "virthread.h"
+
+# define VIR_FROM_THIS VIR_FROM_NONE
+
+# define GETTIMEOFDAY(T) gettimeofday(T, NULL)
+# define VSH_MAX_XML_FILE (10*1024*1024)
+# define VSH_MATCH(FLAG) (flags & (FLAG))
+
+/**
+ * The log configuration
+ */
+# define MSG_BUFFER 4096
+# define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */
+# define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */
+# define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */
+# define LVL_DEBUG "DEBUG"
+# define LVL_INFO "INFO"
+# define LVL_NOTICE "NOTICE"
+# define LVL_WARNING "WARNING"
+# define LVL_ERROR "ERROR"
+
+/**
+ * vshErrorLevel:
+ *
+ * Indicates the level of a log message
+ */
+typedef enum {
+ VSH_ERR_DEBUG = 0,
+ VSH_ERR_INFO,
+ VSH_ERR_NOTICE,
+ VSH_ERR_WARNING,
+ VSH_ERR_ERROR
+} vshErrorLevel;
+
+# define VSH_DEBUG_DEFAULT VSH_ERR_ERROR
+
+/*
+ * virsh command line grammar:
+ *
+ * command_line = <command>\n | <command>; <command>; ...
+ *
+ * command = <keyword> <option> [--] <data>
+ *
+ * option = <bool_option> | <int_option> | <string_option>
+ * data = <string>
+ *
+ * bool_option = --optionname
+ * int_option = --optionname <number> | --optionname=<number>
+ * string_option = --optionname <string> | --optionname=<string>
+ *
+ * keyword = [a-zA-Z][a-zA-Z-]*
+ * number = [0-9]+
+ * string = ('[^']*'|"([^\\"]|\\.)*"|([^ \t\n\\'"]|\\.))+
+ *
+ */
+
+/*
+ * vshCmdOptType - command option type
+ */
+typedef enum {
+ VSH_OT_BOOL, /* optional boolean option */
+ VSH_OT_STRING, /* optional string option */
+ VSH_OT_INT, /* optional or mandatory int option */
+ VSH_OT_DATA, /* string data (as non-option) */
+ VSH_OT_ARGV, /* remaining arguments */
+ VSH_OT_ALIAS, /* alternate spelling for a later argument */
+} vshCmdOptType;
+
+/*
+ * Command Option Flags
+ */
+enum {
+ VSH_OFLAG_NONE = 0, /* without flags */
+ VSH_OFLAG_REQ = (1 << 0), /* option required */
+ VSH_OFLAG_EMPTY_OK = (1 << 1), /* empty string option allowed */
+ VSH_OFLAG_REQ_OPT = (1 << 2), /* --optionname required */
+};
+
+/* forward declarations */
+typedef struct _vshClientHooks vshClientHooks;
+typedef struct _vshCmd vshCmd;
+typedef struct _vshCmdDef vshCmdDef;
+typedef struct _vshCmdGrp vshCmdGrp;
+typedef struct _vshCmdInfo vshCmdInfo;
+typedef struct _vshCmdOpt vshCmdOpt;
+typedef struct _vshCmdOptDef vshCmdOptDef;
+typedef struct _vshControl vshControl;
+
+typedef char **(*vshCompleter)(unsigned int flags);
+
+/*
+ * vshCmdInfo -- name/value pair for information about command
+ *
+ * Commands should have at least the following names:
+ * "help" - short description of command
+ * "desc" - description of command, or empty string
+ */
+struct _vshCmdInfo {
+ const char *name; /* name of information, or NULL for list end */
+ const char *data; /* non-NULL information */
+};
+
+/*
+ * vshCmdOptDef - command option definition
+ */
+struct _vshCmdOptDef {
+ const char *name; /* the name of option, or NULL for list end */
+ vshCmdOptType type; /* option type */
+ unsigned int flags; /* flags */
+ const char *help; /* non-NULL help string; or for VSH_OT_ALIAS
+ * the name of a later public option */
+ vshCompleter completer; /* option completer */
+ unsigned int completer_flags; /* option completer flags */
+};
+
+/*
+ * vshCmdOpt - command options
+ *
+ * After parsing a command, all arguments to the command have been
+ * collected into a list of these objects.
+ */
+struct _vshCmdOpt {
+ const vshCmdOptDef *def; /* non-NULL pointer to option definition */
+ char *data; /* allocated data, or NULL for bool option */
+ vshCmdOpt *next;
+};
+
+/*
+ * Command Usage Flags
+ */
+enum {
+ VSH_CMD_FLAG_NOCONNECT = (1 << 0), /* no prior connection needed */
+ VSH_CMD_FLAG_ALIAS = (1 << 1), /* command is an alias */
+};
+
+/*
+ * vshCmdDef - command definition
+ */
+struct _vshCmdDef {
+ const char *name; /* name of command, or NULL for list end */
+ bool (*handler) (vshControl *, const vshCmd *); /* command handler */
+ const vshCmdOptDef *opts; /* definition of command options */
+ const vshCmdInfo *info; /* details about command */
+ unsigned int flags; /* bitwise OR of VSH_CMD_FLAG */
+};
+
+/*
+ * vshCmd - parsed command
+ */
+struct _vshCmd {
+ const vshCmdDef *def; /* command definition */
+ vshCmdOpt *opts; /* list of command arguments */
+ vshCmd *next; /* next command */
+};
+
+/*
+ * vshControl
+ */
+struct _vshControl {
+ const char *name; /* hardcoded name of the binary that cannot
+ * be changed without recompilation compared
+ * to program name */
+ char *connname; /* connection name */
+ char *progname; /* program name */
+ vshCmd *cmd; /* the current command */
+ char *cmdstr; /* string with command */
+ bool imode; /* interactive mode? */
+ bool quiet; /* quiet mode */
+ bool timing; /* print timing info? */
+ int debug; /* print debug messages? */
+ char *logfile; /* log file name */
+ int log_fd; /* log file descriptor */
+ char *historydir; /* readline history directory name */
+ char *historyfile; /* readline history file name */
+ virThread eventLoop;
+ virMutex lock;
+ bool eventLoopStarted;
+ bool quit;
+ int eventPipe[2]; /* Write-to-self pipe to end waiting for an
+ * event to occur */
+ int eventTimerId; /* id of event loop timeout registration */
+
+ int keepalive_interval; /* Client keepalive interval */
+ int keepalive_count; /* Client keepalive count */
+
+# ifndef WIN32
+ struct termios termattr; /* settings of the tty terminal */
+# endif
+ bool istty; /* is the terminal a tty */
+
+ const vshClientHooks *hooks;/* mandatory client specific hooks */
+ void *privData; /* client specific data */
+};
+
+typedef void *
+(*vshConnectionHook)(vshControl *ctl);
+
+struct _vshClientHooks {
+ vshConnectionHook connHandler;
+};
+
+struct _vshCmdGrp {
+ const char *name; /* name of group, or NULL for list end */
+ const char *keyword; /* help keyword */
+ const vshCmdDef *commands;
+};
+
+void vshError(vshControl *ctl, const char *format, ...)
+ ATTRIBUTE_FMT_PRINTF(2, 3);
+void vshOpenLogFile(vshControl *ctl);
+void vshOutputLogFile(vshControl *ctl, int log_level, const char *format,
+ va_list ap)
+ ATTRIBUTE_FMT_PRINTF(3, 0);
+void vshCloseLogFile(vshControl *ctl);
+
+const char *vshCmddefGetInfo(const vshCmdDef *cmd, const char *info);
+const vshCmdDef *vshCmddefSearch(const char *cmdname);
+bool vshCmddefHelp(vshControl *ctl, const char *name);
+const vshCmdGrp *vshCmdGrpSearch(const char *grpname);
+bool vshCmdGrpHelp(vshControl *ctl, const char *name);
+
+int vshCommandOptInt(vshControl *ctl, const vshCmd *cmd,
+ const char *name, int *value)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned int *value)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned int *value)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptUL(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long *value)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long *value)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptString(vshControl *ctl, const vshCmd *cmd,
+ const char *name, const char **value)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptStringReq(vshControl *ctl, const vshCmd *cmd,
+ const char *name, const char **value)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd,
+ const char *name, long long *value)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long long *value)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long long *value)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd,
+ const char *name, unsigned long long *value,
+ int scale, unsigned long long max)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+bool vshCommandOptBool(const vshCmd *cmd, const char *name);
+bool vshCommandRun(vshControl *ctl, const vshCmd *cmd);
+bool vshCommandStringParse(vshControl *ctl, char *cmdstr);
+
+const vshCmdOpt *vshCommandOptArgv(vshControl *ctl, const vshCmd *cmd,
+ const vshCmdOpt *opt);
+bool vshCommandArgvParse(vshControl *ctl, int nargs, char **argv);
+int vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout);
+
+void vshPrintExtra(vshControl *ctl, const char *format, ...)
+ ATTRIBUTE_FMT_PRINTF(2, 3);
+int vshInit(vshControl *ctl, const vshCmdGrp *groups, const vshCmdDef *set);
+void vshDeinit(vshControl *ctl);
+void vshInitDebug(vshControl *ctl);
+void vshDebug(vshControl *ctl, int level, const char *format, ...)
+ ATTRIBUTE_FMT_PRINTF(3, 4);
+
+/* XXX: add batch support */
+# define vshPrint(_ctl, ...) vshPrintExtra(NULL, __VA_ARGS__)
+
+/* User visible sort, so we want locale-specific case comparison. */
+# define vshStrcasecmp(S1, S2) strcasecmp(S1, S2)
+int vshNameSorter(const void *a, const void *b);
+
+virTypedParameterPtr vshFindTypedParamByName(const char *name,
+ virTypedParameterPtr list,
+ int count);
+char *vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+double vshPrettyCapacity(unsigned long long val, const char **unit);
+int vshStringToArray(const char *str, char ***array);
+
+/* Given an index, return either the name of that device (non-NULL) or
+ * of its parent (NULL if a root). */
+typedef const char * (*vshTreeLookup)(int devid, bool parent, void *opaque);
+int vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
+ int num_devices, int devid);
+
+/* error handling */
+extern virErrorPtr last_error;
+void vshErrorHandler(void *opaque, virErrorPtr error);
+void vshReportError(vshControl *ctl);
+void vshResetLibvirtError(void);
+void vshSaveLibvirtError(void);
+
+/* file handling */
+char *vshEditWriteToTempFile(vshControl *ctl, const char *doc);
+int vshEditFile(vshControl *ctl, const char *filename);
+char *vshEditReadBackFile(vshControl *ctl, const char *filename);
+int vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail);
+
+/* terminal modifications */
+bool vshTTYIsInterruptCharacter(vshControl *ctl, const char chr);
+int vshTTYDisableInterrupt(vshControl *ctl);
+int vshTTYRestore(vshControl *ctl);
+int vshTTYMakeRaw(vshControl *ctl, bool report_errors);
+bool vshTTYAvailable(vshControl *ctl);
+
+/* waiting for events */
+enum {
+ VSH_EVENT_INTERRUPT,
+ VSH_EVENT_TIMEOUT,
+ VSH_EVENT_DONE,
+};
+void vshEventCleanup(vshControl *ctl);
+void vshEventDone(vshControl *ctl);
+void vshEventLoop(void *opaque);
+int vshEventStart(vshControl *ctl, int timeout_ms);
+void vshEventTimeout(int timer, void *opaque);
+int vshEventWait(vshControl *ctl);
+
+/* generic commands */
+extern const vshCmdOptDef opts_help[];
+extern const vshCmdInfo info_help[];
+extern const vshCmdOptDef opts_cd[];
+extern const vshCmdInfo info_cd[];
+extern const vshCmdOptDef opts_echo[];
+extern const vshCmdInfo info_echo[];
+extern const vshCmdInfo info_pwd[];
+extern const vshCmdInfo info_quit[];
+
+bool cmdHelp(vshControl *ctl, const vshCmd *cmd);
+bool cmdCd(vshControl *ctl, const vshCmd *cmd);
+bool cmdEcho(vshControl *ctl, const vshCmd *cmd);
+bool cmdPwd(vshControl *ctl, const vshCmd *cmd);
+bool cmdQuit(vshControl *ctl, const vshCmd *cmd);
+
+# define VSH_CMD_CD \
+ { \
+ .name = "cd", \
+ .handler = cmdCd, \
+ .opts = opts_cd, \
+ .info = info_cd, \
+ .flags = VSH_CMD_FLAG_NOCONNECT \
+ }
+
+# define VSH_CMD_ECHO \
+ { \
+ .name = "echo", \
+ .handler = cmdEcho, \
+ .opts = opts_echo, \
+ .info = info_echo, \
+ .flags = VSH_CMD_FLAG_NOCONNECT \
+ }
+
+# define VSH_CMD_EXIT \
+ { \
+ .name = "exit", \
+ .handler = cmdQuit, \
+ .opts = NULL, \
+ .info = info_quit, \
+ .flags = VSH_CMD_FLAG_NOCONNECT \
+ }
+
+# define VSH_CMD_HELP \
+ { \
+ .name = "help", \
+ .handler = cmdHelp, \
+ .opts = opts_help, \
+ .info = info_help, \
+ .flags = VSH_CMD_FLAG_NOCONNECT \
+ }
+
+# define VSH_CMD_PWD \
+ { \
+ .name = "pwd", \
+ .handler = cmdPwd, \
+ .opts = NULL, \
+ .info = info_pwd, \
+ .flags = VSH_CMD_FLAG_NOCONNECT \
+ }
+
+# define VSH_CMD_QUIT \
+ { \
+ .name = "quit", \
+ .handler = cmdQuit, \
+ .opts = NULL, \
+ .info = info_quit, \
+ .flags = VSH_CMD_FLAG_NOCONNECT \
+ }
+
+
+/* readline */
+char * vshReadline(vshControl *ctl, const char *prompt);
+
+/* allocation wrappers */
+void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line);
+# define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
+
+void *_vshCalloc(vshControl *ctl, size_t nmemb, size_t sz,
+ const char *filename, int line);
+# define vshCalloc(_ctl, _nmemb, _sz) \
+ _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)
+
+char *_vshStrdup(vshControl *ctl, const char *s, const char *filename,
+ int line);
+# define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__)
+
+/* Poison the raw allocating identifiers in favor of our vsh variants. */
+# undef malloc
+# undef calloc
+# undef realloc
+# undef strdup
+# define malloc use_vshMalloc_instead_of_malloc
+# define calloc use_vshCalloc_instead_of_calloc
+# define realloc use_vshRealloc_instead_of_realloc
+# define strdup use_vshStrdup_instead_of_strdup
+
+/* Macros to help dealing with mutually exclusive options. */
+
+/* VSH_EXCLUSIVE_OPTIONS_EXPR:
+ *
+ * @NAME1: String containing the name of the option.
+ * @EXPR1: Expression to validate the variable (boolean variable)
+ * @NAME2: String containing the name of the option.
+ * @EXPR2: Expression to validate the variable (boolean variable)
+ *
+ * Reject mutually exclusive command options in virsh. Use the
+ * provided expression to check the variables.
+ *
+ * This helper does an early return and therefore it has to be called
+ * before anything that would require cleanup.
+ */
+# define VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, EXPR1, NAME2, EXPR2) \
+ if ((EXPR1) && (EXPR2)) { \
+ vshError(ctl, _("Options --%s and --%s are mutually exclusive"), \
+ NAME1, NAME2); \
+ return false; \
+ }
+
+/* VSH_EXCLUSIVE_OPTIONS:
+ *
+ * @NAME1: String containing the name of the option.
+ * @NAME2: String containing the name of the option.
+ *
+ * Reject mutually exclusive command options in virsh. Use the
+ * vshCommandOptBool call to request them.
+ *
+ * This helper does an early return and therefore it has to be called
+ * before anything that would require cleanup.
+ */
+# define VSH_EXCLUSIVE_OPTIONS(NAME1, NAME2) \
+ VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \
+ NAME2, vshCommandOptBool(cmd, NAME2))
+
+/* VSH_EXCLUSIVE_OPTIONS_VAR:
+ *
+ * @VARNAME1: Boolean variable containing the value of the option of same name
+ * @VARNAME2: Boolean variable containing the value of the option of same name
+ *
+ * Reject mutually exclusive command options in virsh. Check in variables that
+ * contain the value and have same name as the option.
+ *
+ * This helper does an early return and therefore it has to be called
+ * before anything that would require cleanup.
+ */
+# define VSH_EXCLUSIVE_OPTIONS_VAR(VARNAME1, VARNAME2) \
+ VSH_EXCLUSIVE_OPTIONS_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2)
+
+/* Macros to help dealing with required options. */
+
+/* VSH_REQUIRE_OPTION_EXPR:
+ *
+ * @NAME1: String containing the name of the option.
+ * @EXPR1: Expression to validate the variable (boolean variable).
+ * @NAME2: String containing the name of required option.
+ * @EXPR2: Expression to validate the variable (boolean variable).
+ *
+ * Check if required command options in virsh was set. Use the
+ * provided expression to check the variables.
+ *
+ * This helper does an early return and therefore it has to be called
+ * before anything that would require cleanup.
+ */
+# define VSH_REQUIRE_OPTION_EXPR(NAME1, EXPR1, NAME2, EXPR2) \
+ do { \
+ if ((EXPR1) && !(EXPR2)) { \
+ vshError(ctl, _("Option --%s is required by option --%s"), \
+ NAME2, NAME1); \
+ return false; \
+ } \
+ } while (0)
+
+/* VSH_REQUIRE_OPTION:
+ *
+ * @NAME1: String containing the name of the option.
+ * @NAME2: String containing the name of required option.
+ *
+ * Check if required command options in virsh was set. Use the
+ * vshCommandOptBool call to request them.
+ *
+ * This helper does an early return and therefore it has to be called
+ * before anything that would require cleanup.
+ */
+# define VSH_REQUIRE_OPTION(NAME1, NAME2) \
+ VSH_REQUIRE_OPTION_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \
+ NAME2, vshCommandOptBool(cmd, NAME2))
+
+/* VSH_REQUIRE_OPTION_VAR:
+ *
+ * @VARNAME1: Boolean variable containing the value of the option of same name.
+ * @VARNAME2: Boolean variable containing the value of required option of
+ * same name.
+ *
+ * Check if required command options in virsh was set. Check in variables
+ * that contain the value and have same name as the option.
+ *
+ * This helper does an early return and therefore it has to be called
+ * before anything that would require cleanup.
+ */
+# define VSH_REQUIRE_OPTION_VAR(VARNAME1, VARNAME2) \
+ VSH_REQUIRE_OPTION_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2)
+
+#endif /* VSH_H */