Skip to content

Instantly share code, notes, and snippets.

@hifi
Last active October 13, 2016 20:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hifi/4321ffe9d56612b2449f to your computer and use it in GitHub Desktop.
Save hifi/4321ffe9d56612b2449f to your computer and use it in GitHub Desktop.
TigerVNC SSH pipe
diff --git a/common/network/Socket.h b/common/network/Socket.h
index 378a900..11a4318 100644
--- a/common/network/Socket.h
+++ b/common/network/Socket.h
@@ -43,7 +43,7 @@ namespace network {
}
rdr::FdInStream &inStream() {return *instream;}
rdr::FdOutStream &outStream() {return *outstream;}
- int getFd() {return outstream->getFd();}
+ int getFd() {return instream->getFd();}
// if shutdown() is overridden then the override MUST call on to here
virtual void shutdown() {isShutdown_ = true;}
diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx
index f8b45af..f561377 100644
--- a/vncviewer/CConn.cxx
+++ b/vncviewer/CConn.cxx
@@ -49,6 +49,7 @@
#include "i18n.h"
#include "parameters.h"
#include "vncviewer.h"
+#include "PipeSocket.h"
#ifdef WIN32
#include "win32.h"
@@ -105,10 +106,14 @@ CConn::CConn(const char* vncServerName, network::Socket* socket=NULL)
if(sock == NULL) {
try {
+#if 0
getHostAndPort(vncServerName, &serverHost, &serverPort);
sock = new network::TcpSocket(serverHost, serverPort);
vlog.info(_("connected to host %s port %d"), serverHost, serverPort);
+#endif
+ char *args[] = { "/bin/sh", "-c", (char *)vncServerName, NULL };
+ sock = new PipeSocket(args[0], args);
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
fl_alert("%s", e.str());
diff --git a/vncviewer/PipeSocket.h b/vncviewer/PipeSocket.h
new file mode 100644
index 0000000..80f0bb8
--- /dev/null
+++ b/vncviewer/PipeSocket.h
@@ -0,0 +1,48 @@
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include <network/Socket.h>
+
+class PipeSocket : public network::Socket {
+ public:
+ PipeSocket(const char *path, char *const args[]) {
+#ifdef WIN32
+ throw rdr::SystemException(_("pipe is only supported on non-Windows platforms"));
+#else
+ int stdin_fds[2];
+ int stdout_fds[2];
+
+ pipe(stdin_fds);
+ pipe(stdout_fds);
+
+ if (fork() == 0) {
+ dup2(stdin_fds[0], STDIN_FILENO);
+ dup2(stdout_fds[1], STDOUT_FILENO);
+
+ close(stdin_fds[1]);
+ close(stdout_fds[0]);
+ close(STDERR_FILENO);
+
+ execv(path, args);
+ perror("execv");
+ exit(1);
+ }
+
+ close(stdin_fds[0]);
+ close(stdout_fds[1]);
+
+ instream = new rdr::FdInStream(stdout_fds[0]);
+ outstream = new rdr::FdOutStream(stdin_fds[1]);
+ ownStreams = true;
+#endif
+ }
+
+ int getMyPort() { return 0; };
+
+ char* getPeerAddress() { return "pipe"; };
+ int getPeerPort() { return 0; }
+ char* getPeerEndpoint() { return "pipe"; }
+
+ bool sameMachine() { return 0; }
+};
#!/bin/perl
use strict;
use POSIX;
use IO::Socket::UNIX;
use IO::Select;
my $spath = '.Xvnc.sock';
if (!-e $spath) {
my $pid;
my $server = IO::Socket::UNIX->new(
Type => SOCK_STREAM(),
Local => $spath,
Listen => 1,
) or die "Failed to open $spath: $!";
if (!defined($pid = fork())) {
die "cannot fork: $!";
} elsif ($pid == 0) {
POSIX::dup2($server->fileno(), 0);
POSIX::close(1);
POSIX::close(2);
open STDOUT, '>/dev/null';
open STDERR, '>/dev/null';
system "/usr/bin/xinit", "--", "/usr/bin/Xvnc", "-inetd", "-nolisten", "tcp", "-once", "-SecurityTypes", "none";
unlink $spath;
exit;
}
}
my $pipe = IO::Socket::UNIX->new(
Type => SOCK_STREAM(),
Peer => $spath,
) or die;
my $select = IO::Select->new();
$select->add(\*STDIN);
$select->add($pipe);
while (my @ready = $select->can_read()) {
foreach my $fh (@ready) {
my $buf;
if ($fh == \*STDIN) {
my $len = sysread STDIN, $buf, 1024;
$len > 0 || exit;
syswrite $pipe, $buf, $len;
} else {
my $len = sysread $pipe, $buf, 1024;
$len > 0 || exit;
syswrite STDOUT, $buf, $len;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment