Package: gvncviewer Version: 0.5.0-2 Severity: normal Tags: patch gvncviewer can't currently connect to VNC servers running over unix domain sockets, such as those provided by the qemu and kvm utilities.
The attached patch enables this feature. It should apply cleanly at the end of the current patch series in gvncviewer 0.5.0-2. The logic is: test the provided hostname to see if a matching file exists and is a unix-domain socket. If it is, try to connect to it that way. otherwise, proceed with argument parsing and TCP sockets as usual. I've also filed this with upstream at: https://bugzilla.gnome.org/show_bug.cgi?id=667396 Regards, --dkg
Description: allow Unix domain sockets in gvncviewer gvncviewer is useful when connecting to unix domain sockets. Author: Daniel Kahn Gillmor <d...@fifthhorseman.net> --- gtk-vnc-0.5.0.orig/examples/gvncviewer.c +++ gtk-vnc-0.5.0/examples/gvncviewer.c @@ -30,6 +30,11 @@ #include <stdlib.h> #include <string.h> #include <glib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/un.h> #if WITH_LIBVIEW #include <libview/autoDrawer.h> @@ -586,6 +591,8 @@ int main(int argc, char **argv) GtkWidget *scaling; GtkWidget *showgrabkeydlg; const char *help_msg = "Run 'gvncviewer --help' to see a full list of available command line options"; + struct stat sockstat; + int sock; name = g_strdup_printf("- Simple VNC Client on Gtk-VNC %s", vnc_util_get_version_string()); @@ -688,17 +695,36 @@ int main(int argc, char **argv) gtk_widget_realize(vnc); snprintf(hostname, sizeof(hostname), "%s", args[0]); - display = strchr(hostname, ':'); - - if (display) { - *display = 0; - snprintf(port, sizeof(port), "%d", 5900 + atoi(display + 1)); - } else - snprintf(port, sizeof(port), "%d", 5900); - - if (!*hostname) - snprintf(hostname, sizeof(hostname), "%s", "127.0.0.1"); - vnc_display_open_host(VNC_DISPLAY(vnc), hostname, port); + if ((0 == stat(hostname, &sockstat)) && + S_ISSOCK(sockstat.st_mode)) { + size_t sockaddrsize = offsetof(struct sockaddr_un, sun_path) + strlen(hostname) + 1; + struct sockaddr_un* addr = malloc(sockaddrsize); + + /* the argument refers to a unix domain socket */ + sock = socket(AF_UNIX, SOCK_STREAM, 0); + addr->sun_family = AF_UNIX; + strcpy(addr->sun_path, hostname); + if (0 == connect(sock, (const struct sockaddr *)addr, sockaddrsize)) { + vnc_display_open_fd(VNC_DISPLAY(vnc), sock); + } else { + fprintf(stderr, "Failed to open unix domain socket %s\n", hostname); + return 1; + } + free(addr); + } else { + /* treat it as a regular hostname */ + display = strchr(hostname, ':'); + + if (display) { + *display = 0; + snprintf(port, sizeof(port), "%d", 5900 + atoi(display + 1)); + } else + snprintf(port, sizeof(port), "%d", 5900); + + if (!*hostname) + snprintf(hostname, sizeof(hostname), "%s", "127.0.0.1"); + vnc_display_open_host(VNC_DISPLAY(vnc), hostname, port); + } vnc_display_set_keyboard_grab(VNC_DISPLAY(vnc), TRUE); vnc_display_set_pointer_grab(VNC_DISPLAY(vnc), TRUE);