Am Sun, 28. Dec 2008, 02:05:54 +0100 schrieb Jö Fahlke:
> Hi!
> 
> I wrote a little patch for this, see attachment.  On the way, I came across
> Bug#509949, the fix for that bug is included in this patch, since the changes
> had to be made to the same part of the code.

Oh yeah.  Here is the attachment.

Bye,
Jö.

-- 
The irony is that Bill Gates claims to be making a stable operating
system and Linus Torvalds claims to be trying to take over the world.
-- seen on the net
diff -ru vnc4-4.1.1+X4.3.0_orig/unix/vncviewer/CConn.cxx vnc4-4.1.1+X4.3.0/unix/vncviewer/CConn.cxx
--- vnc4-4.1.1+X4.3.0_orig/unix/vncviewer/CConn.cxx	2008-12-27 22:32:48.000000000 +0100
+++ vnc4-4.1.1+X4.3.0/unix/vncviewer/CConn.cxx	2008-12-28 01:35:03.000000000 +0100
@@ -22,6 +22,8 @@
 #include <termios.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #include "CConn.h"
 #include <rfb/CMsgWriter.h>
 #include <rfb/encodings.h>
@@ -85,29 +87,74 @@
     vlog.info("Accepted connection from %s", name);
     if (name) free(name);
   } else {
-    if (vncServerName) {
-      getHostAndPort(vncServerName, &serverHost, &serverPort);
-    } else {
+    // automatically freed buffer in case we need some scratch for
+    // vncServerName later
+    char vncServerNameBuf[128];
+
+    if (!vncServerName) {
+      vncServerName = vncServerNameBuf;
+
       int popup = popupXDialog;
       if (!popup) {
         /* Get server */
         fprintf(stderr, "Server: ");
-        vncServerName = new char[128];
-        fgets(vncServerName, 128, stdin);
-	/* remove \n at the end */
-	vncServerName[strlen(vncServerName)-1] = '\0';
-        getHostAndPort(vncServerName, &serverHost, &serverPort);
+        if(fgets(vncServerName, 128, stdin)) {
+          size_t len = strlen(vncServerName);
+          /* remove \n at the end */
+          if(vncServerName[len-1] == '\n') {
+            vncServerName[len-1] = '\0';
+            --len;
+          }
+          if(len == 128-1) {
+            /* either the line _was_ 127 characters long or it was too long to
+               fit into the buffer.  Since we can't tell the difference, we
+               deem both too long. */
+            vlog.error("Server name too long");
+            exit(1);
+          }
+        } else {
+          /* fgets failed, probably eof -- assume empty string as input */
+          vlog.error("Server name empty");
+          exit(1);
+        }
       } else {
         ServerDialog dlg(dpy, &options, &about);
         if (!dlg.show() || dlg.entry.getText()[0] == 0) {
           exit(1);
         }
-        getHostAndPort(dlg.entry.getText(), &serverHost, &serverPort);
+        if(strlen(dlg.entry.getText()) >= 128) {
+          vlog.error("Server name too long");
+          exit(1);
+        }
+        strcpy(vncServerName, dlg.entry.getText());
       }
     }
+    /* assume its a unix domain socket if it contains a '/' */
+    if(strchr(vncServerName, '/')) {
+      int unix_sock = socket(PF_LOCAL, SOCK_STREAM, 0);
+      size_t sock_name_size = offsetof(sockaddr_un, sun_path)
+        + strlen(vncServerName) + 1;
+      sockaddr_un *name = new sockaddr_un;
+      name->sun_family = AF_LOCAL;
+      strcpy(name->sun_path, vncServerName);
+      int result = connect(unix_sock, (const sockaddr *)name, sock_name_size);
+      /* delete name _before_ we do anything which might throw an exception,
+         which might leave us with a potential memory leak */
+      delete name;
+      if(result == -1) {
+        /* connecting socket failed */
+        vlog.error("Can't connect to unix domain socket %s", vncServerName);
+        exit(1);
+      }
 
-    sock = new network::TcpSocket(serverHost, serverPort);
-    vlog.info("connected to host %s port %d", serverHost, serverPort);
+      sock = new network::TcpSocket(unix_sock);
+      vlog.info("connected to unix domain socket %s", vncServerName);
+     } else {
+      getHostAndPort(vncServerName, &serverHost, &serverPort);
+
+      sock = new network::TcpSocket(serverHost, serverPort);
+      vlog.info("connected to host %s port %d", serverHost, serverPort);
+    }
   }
 
   sameMachine = sock->sameMachine();
diff -ru vnc4-4.1.1+X4.3.0_orig/unix/vncviewer/vncviewer.man vnc4-4.1.1+X4.3.0/unix/vncviewer/vncviewer.man
--- vnc4-4.1.1+X4.3.0_orig/unix/vncviewer/vncviewer.man	2008-12-27 22:32:48.000000000 +0100
+++ vnc4-4.1.1+X4.3.0/unix/vncviewer/vncviewer.man	2008-12-28 01:40:52.000000000 +0100
@@ -8,6 +8,10 @@
 .br
 .B vncviewer
 .RI [ options ] 
+.RI [ unix_domain_socket ]
+.br
+.B vncviewer
+.RI [ options ] 
 .B \-listen
 .RI [ port ]
 .SH DESCRIPTION
@@ -27,6 +31,10 @@
 omitted.  So for example ":1" means display number 1 on the same machine, and
 "snoopy" means "snoopy:0" i.e. display 0 on machine "snoopy".
 
+A server specification containing a '/' is recognised as a path to an unix
+domain socket.  The viewer will then connect to a server listening on that
+socket, for example a QEMU virtual machine.
+
 If the VNC server is successfully contacted, you will be prompted for a
 password to authenticate you.  If the password is correct, a window will appear
 showing the desktop of the VNC server.

Attachment: signature.asc
Description: Digital signature

Reply via email to