From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JNFj4-0004Pp-7m for qemu-devel@nongnu.org; Thu, 07 Feb 2008 18:00:14 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JNFj2-0004P7-Tf for qemu-devel@nongnu.org; Thu, 07 Feb 2008 18:00:12 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JNFj2-0004P4-EV for qemu-devel@nongnu.org; Thu, 07 Feb 2008 18:00:12 -0500 Received: from e36.co.us.ibm.com ([32.97.110.154]) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1JNFj1-0003GS-RG for qemu-devel@nongnu.org; Thu, 07 Feb 2008 18:00:12 -0500 Received: from d03relay02.boulder.ibm.com (d03relay02.boulder.ibm.com [9.17.195.227]) by e36.co.us.ibm.com (8.13.8/8.13.8) with ESMTP id m17N07R4026571 for ; Thu, 7 Feb 2008 18:00:07 -0500 Received: from d03av03.boulder.ibm.com (d03av03.boulder.ibm.com [9.17.195.169]) by d03relay02.boulder.ibm.com (8.13.8/8.13.8/NCO v8.7) with ESMTP id m17N07u8151572 for ; Thu, 7 Feb 2008 16:00:07 -0700 Received: from d03av03.boulder.ibm.com (loopback [127.0.0.1]) by d03av03.boulder.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id m17N065D021074 for ; Thu, 7 Feb 2008 16:00:06 -0700 Received: from [9.53.41.160] (squirrel-009053041160.austin.ibm.com [9.53.41.160]) by d03av03.boulder.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id m17N0662020711 for ; Thu, 7 Feb 2008 16:00:06 -0700 Message-ID: <47AB8D73.6060608@us.ibm.com> Date: Thu, 07 Feb 2008 17:00:03 -0600 From: Anthony Liguori MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH] Add script hook for VNC server to support mDNS/DNS-SD References: <1202424073-24316-1-git-send-email-aliguori@us.ibm.com> In-Reply-To: <1202424073-24316-1-git-send-email-aliguori@us.ibm.com> Content-Type: multipart/mixed; boundary="------------040003010406000904080004" Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------040003010406000904080004 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit This version is still a bit chatty when -name isn't specified so attached is an updated version of the patch which is less chatty when -name isn't specified. Regards, Anthony Liguori Anthony Liguori wrote: > Modern DNS clients (like vinagre) support mDNS/DNS-SD discovery of VNC servers. > VNC servers like Vino link directly against libavahi to publish themselves. > Fitting libavahi into QEMU though would be pretty hairy and not as flexible as > simply calling out to a helper script and using the avahi utilities. > > This patch adds support for a ',script=/patch/to/script' option to the existing > -vnc option. It also includes an example script which uses avahi-publish the > presence of the QEMU instance. Care has been taken to ensure that errors are > silenced if either bash or avahi aren't present and the user hasn't explicitly > specified ',script='. > --------------040003010406000904080004 Content-Type: text/x-patch; name="mdns-script.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="mdns-script.patch" Subject: [PATCH] Add script hook for VNC server to support mDNS/DNS-SD Modern DNS clients (like vinagre) support mDNS/DNS-SD discovery of VNC servers. VNC servers like Vino link directly against libavahi to publish themselves. Fitting libavahi into QEMU though would be pretty hairy and not as flexible as simply calling out to a helper script and using the avahi utilities. This patch adds support for a ',script=/patch/to/script' option to the existing -vnc option. It also includes an example script which uses avahi-publish the presence of the QEMU instance. Care has been taken to ensure that errors are silenced if either bash or avahi aren't present and the user hasn't explicitly specified ',script='. diff --git a/qemu-doc.texi b/qemu-doc.texi index f9924d2..cd59aab 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -486,6 +486,21 @@ path following this option specifies where the x509 certificates are to be loaded from. See the @ref{vnc_security} section for details on generating certificates. +@item script=@var{/path/to/script} + +Launch a script when the VNC server is started. The script is expected to +continue running as long as the VNC server is running. When the VNC server +closes, the script will receive either a SIGTERM or standard input will be +shutdown. The script will be passed arguments in the order of @var{NAME} +@var{ADDRESS} @var{PORT} where @var{NAME} is the value passed to the +@option{-name} option, @var{ADDRESS} is the address the server is bound to, +and @var{PORT} is the port the server is listening on. + +This script will not be executed if @var{reverse} is being used or if the +server is listening on a Unix domain socket. If the @option{-name} option is +not specified, the script will not be executed. The default location of the +script is @file{/etc/qemu-vncup}. + @end table @item -k @var{language} diff --git a/qemu-vncup b/qemu-vncup new file mode 100755 index 0000000..78b9d2d --- /dev/null +++ b/qemu-vncup @@ -0,0 +1,27 @@ +#!/bin/bash + +function dokill() { + kill -SIGTERM $1 >& /dev/null +} + +if [ -z "$1" -o -z "$3" ]; then + echo "Usage: $0 NAME ADDRESS PORT" + exit 1 +fi + +which avahi-publish >& /dev/null +if [ $? != 0 ] ; then + exit 0 +fi + +avahi-publish -s "$1 Virtual Console" '_rfb._tcp' $3 > /dev/null 2>&1 < /dev/null & + +pid=`jobs -p %1` + +trap "dokill -SIGTERM $pid; exit" SIGINT SIGTERM + +while read LINE ; do + echo $LINE +done + +dokill -SIGTERM $pid diff --git a/vnc.c b/vnc.c index e7f3255..8d68770 100644 --- a/vnc.c +++ b/vnc.c @@ -31,6 +31,8 @@ #define VNC_REFRESH_INTERVAL (1000 / 30) +#define VNC_DEFAULT_SCRIPT "/etc/qemu-vncup" + #include "vnc_keysym.h" #include "keymaps.c" #include "d3des.h" @@ -40,6 +42,11 @@ #include #endif /* CONFIG_VNC_TLS */ +#ifndef _WIN32 +#include +#include +#endif + // #define _VNC_DEBUG 1 #if _VNC_DEBUG @@ -174,6 +181,11 @@ struct VncState size_t read_handler_expect; /* input */ uint8_t modifiers_state[256]; + +#ifndef _WIN32 + pid_t script_pid; + int script_fd; +#endif }; static VncState *vnc_state; /* needed for info vnc */ @@ -2056,6 +2068,13 @@ void vnc_display_close(DisplayState *ds) vs->wiremode = VNC_WIREMODE_CLEAR; #endif /* CONFIG_VNC_TLS */ } +#ifndef _WIN32 + if (vs->script_pid) { + close(vs->script_fd); + while (waitpid(vs->script_pid, NULL, 0) == -1 && errno == EINTR); + vs->script_pid = -1; + } +#endif vs->auth = VNC_AUTH_INVALID; #if CONFIG_VNC_TLS vs->subauth = VNC_AUTH_INVALID; @@ -2079,6 +2098,54 @@ int vnc_display_password(DisplayState *ds, const char *password) return 0; } +#ifndef _WIN32 +static int launch_vnc_script(VncState *vs, const char *script, + const char *name, const char *addr, + int port) +{ + int fds[2]; + int quiet = 0; + + vs->script_pid = 0; + + if (pipe(fds) == -1) { + fprintf(stderr, "qemu: pipe failed\n"); + return -1; + } + + if (script == NULL) { + quiet = 1; + script = strdup(VNC_DEFAULT_SCRIPT); + } + + vs->script_pid = fork(); + vs->script_fd = fds[1]; + if (vs->script_pid == 0) { + int fd; + char port_str[32]; + + dup2(fds[0], STDIN_FILENO); + for (fd = 3; fd < sysconf(_SC_OPEN_MAX); fd++) + close(fd); + + snprintf(port_str, sizeof(port_str), "%d", port); + execlp(script, script, name, addr, port_str, NULL); + if (!quiet) + fprintf(stderr, "qemu: failed to exec vnc script: %m\n"); + exit(1); + } else if (vs->script_pid < 0) { + fprintf(stderr, "qemu: fork failed\n"); + return -1; + } else + close(fds[0]); + + if (quiet) + qemu_free((char *)script); + + return 0; +} +#endif + int vnc_display_open(DisplayState *ds, const char *display) { struct sockaddr *addr; @@ -2096,6 +2163,8 @@ int vnc_display_open(DisplayState *ds, const char *display) #if CONFIG_VNC_TLS int tls = 0, x509 = 0; #endif + char *script = NULL; + char *bind_address = NULL; vnc_display_close(ds); if (strcmp(display, "none") == 0) @@ -2111,6 +2180,17 @@ int vnc_display_open(DisplayState *ds, const char *display) password = 1; /* Require password auth */ } else if (strncmp(options, "reverse", 7) == 0) { reverse = 1; + } else if (strncmp(options, "script=", 7) == 0) { + const char *ptr, *end; + + ptr = options + 7; + end = strchr(ptr, ','); + if (end == NULL) + end = ptr + strlen(ptr); + + script = qemu_malloc((end - ptr) + 1); + memcpy(script, ptr, end - ptr); + script[end - ptr] = 0; #if CONFIG_VNC_TLS } else if (strncmp(options, "tls", 3) == 0) { tls = 1; /* Require TLS */ @@ -2210,6 +2290,8 @@ int vnc_display_open(DisplayState *ds, const char *display) } else #endif { + char *ptr; + addr = (struct sockaddr *)&iaddr; addrlen = sizeof(iaddr); @@ -2222,6 +2304,18 @@ int vnc_display_open(DisplayState *ds, const char *display) iaddr.sin_port = htons(ntohs(iaddr.sin_port) + (reverse ? 0 : 5900)); + bind_address = strdup(display); + if (bind_address == NULL) { + fprintf(stderr, "qemu: strdup failed\n"); + return -1; + } + + ptr = strchr(bind_address, ':'); + if (ptr == NULL) + ptr = strchr(bind_address, ','); + if (ptr) + *ptr = 0; + vs->lsock = socket(PF_INET, SOCK_STREAM, 0); if (vs->lsock == -1) { fprintf(stderr, "Could not create socket\n"); @@ -2277,5 +2371,27 @@ int vnc_display_open(DisplayState *ds, const char *display) return -1; } +#ifndef _WIN32 + if (addr->sa_family != AF_INET) { + if (script) + fprintf(stderr, "qemu: cannot call vnc script with unix socket\n"); + } else if (reverse) { + if (script) + fprintf(stderr, + "qemu: cannot call vnc script with reverse connect\n"); + } else if (!qemu_name) { + if (script) + fprintf(stderr, "qemu: cannot call vnc script without -name\n"); + } else { + ret = launch_vnc_script(vs, script, qemu_name, bind_address, + ntohs(iaddr.sin_port)); + if (ret == -1) + return -1; + } +#endif + + qemu_free(script); + qemu_free(bind_address); + return qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs); } --------------040003010406000904080004--