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);
 

Reply via email to