diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index dc6e3b5020..f82aa49745 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -11659,30 +11659,203 @@ static const vshCmdOptDef opts_domdisplay[] = {
{.name = NULL}
};
+
+static char *
+virshGetOneDisplay(vshControl *ctl,
+ const char *scheme,
+ xmlXPathContext *ctxt)
+{
+ const char *xpath_fmt = "string(/domain/devices/graphics[@type='%s']/%s)";
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+ char *xpath = NULL;
+ char *listen_addr = NULL;
+ int port = 0;
+ int tls_port = 0;
+ char *type_conn = NULL;
+ char *sockpath = NULL;
+ char *passwd = NULL;
+ int tmp;
+ bool params = false;
+ virSocketAddr addr;
+
+ /* Create our XPATH lookup for the current display's port */
+ VIR_FREE(xpath);
+ xpath = g_strdup_printf(xpath_fmt, scheme, "@port");
+
+ /* Attempt to get the port number for the current graphics scheme */
+ tmp = virXPathInt(xpath, ctxt, &port);
+ VIR_FREE(xpath);
+
+ /* If there is no port number for this type, then jump to the next
+ * scheme */
+ if (tmp)
+ port = 0;
+
+ /* Create our XPATH lookup for TLS Port (automatically skipped
+ * for unsupported schemes */
+ xpath = g_strdup_printf(xpath_fmt, scheme, "@tlsPort");
+
+ /* Attempt to get the TLS port number */
+ tmp = virXPathInt(xpath, ctxt, &tls_port);
+ VIR_FREE(xpath);
+ if (tmp)
+ tls_port = 0;
+
+ /* Create our XPATH lookup for the current display's address */
+ xpath = g_strdup_printf(xpath_fmt, scheme, "@listen");
+
+ /* Attempt to get the listening addr if set for the current
+ * graphics scheme */
+ VIR_FREE(listen_addr);
+ listen_addr = virXPathString(xpath, ctxt);
+ VIR_FREE(xpath);
+
+ /* Create our XPATH lookup for the current spice type. */
+ xpath = g_strdup_printf(xpath_fmt, scheme, "listen/@type");
+
+ /* Attempt to get the type of spice connection */
+ VIR_FREE(type_conn);
+ type_conn = virXPathString(xpath, ctxt);
+ VIR_FREE(xpath);
+
+ if (STREQ_NULLABLE(type_conn, "socket")) {
+ if (!sockpath) {
+ xpath = g_strdup_printf(xpath_fmt, scheme, "listen/@socket");
+
+ sockpath = virXPathString(xpath, ctxt);
+
+ VIR_FREE(xpath);
+ }
+ }
+
+ if (!port && !tls_port && !sockpath)
+ goto cleanup;
+
+ if (!listen_addr) {
+ /* The subelement address - -
+ * *should* have been automatically backfilled into its
+ * parent (which we just tried to
+ * retrieve into listen_addr above) but in some cases it
+ * isn't, so we also do an explicit check for the
+ * subelement (which, by the way, doesn't exist on libvirt
+ * < 0.9.4, so we really do need to check both places)
+ */
+ xpath = g_strdup_printf(xpath_fmt, scheme, "listen/@address");
+
+ listen_addr = virXPathString(xpath, ctxt);
+ VIR_FREE(xpath);
+ } else {
+ /* If listen_addr is 0.0.0.0 or [::] we should try to parse URI and set
+ * listen_addr based on current URI. */
+ if (virSocketAddrParse(&addr, listen_addr, AF_UNSPEC) > 0 &&
+ virSocketAddrIsWildcard(&addr)) {
+
+ virConnectPtr conn = ((virshControl *)(ctl->privData))->conn;
+ char *uriStr = virConnectGetURI(conn);
+ virURI *uri = NULL;
+
+ if (uriStr) {
+ uri = virURIParse(uriStr);
+ VIR_FREE(uriStr);
+ }
+
+ /* It's safe to free the listen_addr even if parsing of URI
+ * fails, if there is no listen_addr we will print "localhost". */
+ VIR_FREE(listen_addr);
+
+ if (uri) {
+ listen_addr = g_strdup(uri->server);
+ virURIFree(uri);
+ }
+ }
+ }
+
+ /* We can query this info for all the graphics types since we'll
+ * get nothing for the unsupported ones (just rdp for now).
+ * Also the parameter '--include-password' was already taken
+ * care of when getting the XML */
+
+ /* Create our XPATH lookup for the password */
+ xpath = g_strdup_printf(xpath_fmt, scheme, "@passwd");
+
+ /* Attempt to get the password */
+ VIR_FREE(passwd);
+ passwd = virXPathString(xpath, ctxt);
+ VIR_FREE(xpath);
+
+ /* Build up the full URI, starting with the scheme */
+ if (sockpath)
+ virBufferAsprintf(&buf, "%s+unix://", scheme);
+ else
+ virBufferAsprintf(&buf, "%s://", scheme);
+
+ /* There is no user, so just append password if there's any */
+ if (STREQ(scheme, "vnc") && passwd)
+ virBufferAsprintf(&buf, ":%s@", passwd);
+
+ /* Then host name or IP */
+ if (!listen_addr && !sockpath)
+ virBufferAddLit(&buf, "localhost");
+ else if (!sockpath && strchr(listen_addr, ':'))
+ virBufferAsprintf(&buf, "[%s]", listen_addr);
+ else if (sockpath)
+ virBufferAsprintf(&buf, "%s", sockpath);
+ else
+ virBufferAsprintf(&buf, "%s", listen_addr);
+
+ /* Free socket to prepare the pointer for the next iteration */
+ VIR_FREE(sockpath);
+
+ /* Add the port */
+ if (port) {
+ if (STREQ(scheme, "vnc")) {
+ /* VNC protocol handlers take their port number as
+ * 'port' - 5900 */
+ port -= 5900;
+ }
+
+ virBufferAsprintf(&buf, ":%d", port);
+ }
+
+ /* TLS Port */
+ if (tls_port) {
+ virBufferAsprintf(&buf,
+ "?tls-port=%d",
+ tls_port);
+ params = true;
+ }
+
+ if (STREQ(scheme, "spice") && passwd) {
+ virBufferAsprintf(&buf,
+ "%spassword=%s",
+ params ? "&" : "?",
+ passwd);
+ params = true;
+ }
+
+ cleanup:
+ VIR_FREE(xpath);
+ VIR_FREE(type_conn);
+ VIR_FREE(sockpath);
+ VIR_FREE(passwd);
+ VIR_FREE(listen_addr);
+
+ return virBufferContentAndReset(&buf);
+}
+
+
static bool
cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
{
g_autoptr(xmlDoc) xml = NULL;
g_autoptr(xmlXPathContext) ctxt = NULL;
g_autoptr(virshDomain) dom = NULL;
- g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
bool ret = false;
- char *xpath = NULL;
- char *listen_addr = NULL;
- int port, tls_port = 0;
- char *type_conn = NULL;
- char *sockpath = NULL;
- char *passwd = NULL;
- char *output = NULL;
const char *scheme[] = { "vnc", "spice", "rdp", NULL };
const char *type = NULL;
int iter = 0;
- int tmp;
int flags = 0;
- bool params = false;
bool all = vshCommandOptBool(cmd, "all");
- const char *xpath_fmt = "string(/domain/devices/graphics[@type='%s']/%s)";
- virSocketAddr addr;
VSH_EXCLUSIVE_OPTIONS("all", "type");
@@ -11705,169 +11878,16 @@ cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
/* Attempt to grab our display info */
for (iter = 0; scheme[iter] != NULL; iter++) {
+ g_autofree char *display = NULL;
+
/* Particular scheme requested */
if (!all && type && STRNEQ(type, scheme[iter]))
continue;
- /* Create our XPATH lookup for the current display's port */
- VIR_FREE(xpath);
- xpath = g_strdup_printf(xpath_fmt, scheme[iter], "@port");
-
- /* Attempt to get the port number for the current graphics scheme */
- tmp = virXPathInt(xpath, ctxt, &port);
- VIR_FREE(xpath);
-
- /* If there is no port number for this type, then jump to the next
- * scheme */
- if (tmp)
- port = 0;
-
- /* Create our XPATH lookup for TLS Port (automatically skipped
- * for unsupported schemes */
- xpath = g_strdup_printf(xpath_fmt, scheme[iter], "@tlsPort");
-
- /* Attempt to get the TLS port number */
- tmp = virXPathInt(xpath, ctxt, &tls_port);
- VIR_FREE(xpath);
- if (tmp)
- tls_port = 0;
-
- /* Create our XPATH lookup for the current display's address */
- xpath = g_strdup_printf(xpath_fmt, scheme[iter], "@listen");
-
- /* Attempt to get the listening addr if set for the current
- * graphics scheme */
- VIR_FREE(listen_addr);
- listen_addr = virXPathString(xpath, ctxt);
- VIR_FREE(xpath);
-
- /* Create our XPATH lookup for the current spice type. */
- xpath = g_strdup_printf(xpath_fmt, scheme[iter], "listen/@type");
-
- /* Attempt to get the type of spice connection */
- VIR_FREE(type_conn);
- type_conn = virXPathString(xpath, ctxt);
- VIR_FREE(xpath);
-
- if (STREQ_NULLABLE(type_conn, "socket")) {
- if (!sockpath) {
- xpath = g_strdup_printf(xpath_fmt, scheme[iter], "listen/@socket");
-
- sockpath = virXPathString(xpath, ctxt);
-
- VIR_FREE(xpath);
- }
- }
-
- if (!port && !tls_port && !sockpath)
+ if (!(display = virshGetOneDisplay(ctl, scheme[iter], ctxt)))
continue;
- if (!listen_addr) {
- /* The subelement address - -
- * *should* have been automatically backfilled into its
- * parent (which we just tried to
- * retrieve into listen_addr above) but in some cases it
- * isn't, so we also do an explicit check for the
- * subelement (which, by the way, doesn't exist on libvirt
- * < 0.9.4, so we really do need to check both places)
- */
- xpath = g_strdup_printf(xpath_fmt, scheme[iter], "listen/@address");
-
- listen_addr = virXPathString(xpath, ctxt);
- VIR_FREE(xpath);
- } else {
- /* If listen_addr is 0.0.0.0 or [::] we should try to parse URI and set
- * listen_addr based on current URI. */
- if (virSocketAddrParse(&addr, listen_addr, AF_UNSPEC) > 0 &&
- virSocketAddrIsWildcard(&addr)) {
-
- virConnectPtr conn = ((virshControl *)(ctl->privData))->conn;
- char *uriStr = virConnectGetURI(conn);
- virURI *uri = NULL;
-
- if (uriStr) {
- uri = virURIParse(uriStr);
- VIR_FREE(uriStr);
- }
-
- /* It's safe to free the listen_addr even if parsing of URI
- * fails, if there is no listen_addr we will print "localhost". */
- VIR_FREE(listen_addr);
-
- if (uri) {
- listen_addr = g_strdup(uri->server);
- virURIFree(uri);
- }
- }
- }
-
- /* We can query this info for all the graphics types since we'll
- * get nothing for the unsupported ones (just rdp for now).
- * Also the parameter '--include-password' was already taken
- * care of when getting the XML */
-
- /* Create our XPATH lookup for the password */
- xpath = g_strdup_printf(xpath_fmt, scheme[iter], "@passwd");
-
- /* Attempt to get the password */
- VIR_FREE(passwd);
- passwd = virXPathString(xpath, ctxt);
- VIR_FREE(xpath);
-
- /* Build up the full URI, starting with the scheme */
- if (sockpath)
- virBufferAsprintf(&buf, "%s+unix://", scheme[iter]);
- else
- virBufferAsprintf(&buf, "%s://", scheme[iter]);
-
- /* There is no user, so just append password if there's any */
- if (STREQ(scheme[iter], "vnc") && passwd)
- virBufferAsprintf(&buf, ":%s@", passwd);
-
- /* Then host name or IP */
- if (!listen_addr && !sockpath)
- virBufferAddLit(&buf, "localhost");
- else if (!sockpath && strchr(listen_addr, ':'))
- virBufferAsprintf(&buf, "[%s]", listen_addr);
- else if (sockpath)
- virBufferAsprintf(&buf, "%s", sockpath);
- else
- virBufferAsprintf(&buf, "%s", listen_addr);
-
- /* Free socket to prepare the pointer for the next iteration */
- VIR_FREE(sockpath);
-
- /* Add the port */
- if (port) {
- if (STREQ(scheme[iter], "vnc")) {
- /* VNC protocol handlers take their port number as
- * 'port' - 5900 */
- port -= 5900;
- }
-
- virBufferAsprintf(&buf, ":%d", port);
- }
-
- /* TLS Port */
- if (tls_port) {
- virBufferAsprintf(&buf,
- "?tls-port=%d",
- tls_port);
- params = true;
- }
-
- if (STREQ(scheme[iter], "spice") && passwd) {
- virBufferAsprintf(&buf,
- "%spassword=%s",
- params ? "&" : "?",
- passwd);
- params = true;
- }
-
- /* Print out our full URI */
- VIR_FREE(output);
- output = virBufferContentAndReset(&buf);
- vshPrint(ctl, "%s", output);
+ vshPrint(ctl, "%s", display);
/* We got what we came for so return successfully */
ret = true;
@@ -11884,12 +11904,6 @@ cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
}
cleanup:
- VIR_FREE(xpath);
- VIR_FREE(type_conn);
- VIR_FREE(sockpath);
- VIR_FREE(passwd);
- VIR_FREE(listen_addr);
- VIR_FREE(output);
return ret;
}