#!/bin/sh
#
# ss_vncviewer:  wrapper for vncviewer to use an stunnel SSL tunnel
#                or an SSH tunnel.
#
# Copyright (c) 2006-2008 by Karl J. Runge <runge@karlrunge.com>
#
# You must have stunnel(8) installed on the system and in your PATH
# (however, see the -ssh option below, in which case you will need ssh(1)
# installed)  Note: stunnel is usually installed in an "sbin" subdirectory.
#
# You should have "x11vnc -ssl ..." or "x11vnc -stunnel ..." 
# already running as the VNC server on the remote machine.
# (or use stunnel on the server side for any other VNC server)
#
#
# Usage: ss_vncviewer [cert-args] host:display <vncviewer-args>
#
# e.g.:  ss_vncviewer snoopy:0
#        ss_vncviewer snoopy:0 -encodings "copyrect tight zrle hextile"
#
# [cert-args] can be:
#
#	-verify /path/to/cacert.pem		
#	-mycert /path/to/mycert.pem		
#	-proxy  host:port
#
# -verify specifies a CA cert PEM file (or a self-signed one) for
#         authenticating the VNC server.
#
# -mycert specifies this client's cert+key PEM file for the VNC server to
#	  authenticate this client. 
#
# -proxy  try host:port as a Web proxy to use the CONNECT method
#         to reach the VNC server (e.g. your firewall requires a proxy).
#
#         For the "double proxy" case use -proxy host1:port1,host2:port2
#         (the first CONNECT is done through host1:port1 to host2:port2
#         and then a 2nd CONNECT to the destination VNC server.)
#
#         Use socks://host:port, socks4://host:port, or socks5://host,port
#         to force usage of a SOCKS proxy.
#
# -showcert  Only fetch the certificate using the 'openssl s_client'
#            command (openssl(1) must in installed).
#
#    See http://www.karlrunge.com/x11vnc/#faq-ssl-ca for details on SSL
#    certificates with VNC.
#
# A few other args (not related to SSL and certs):
#
# -2nd    Run the vncviewer a 2nd time if the first connections fails.
#
# -ssh    Use ssh instead of stunnel SSL.  ssh(1) must be installed and you
#         must be able to log into the remote machine via ssh.
#
#         In this case "host:display" may be of the form "user@host:display"
#         where "user@host" is used for the ssh login (see ssh(1) manpage).
#
#         If -proxy is supplied it can be of the forms: "gwhost" "gwhost:port"
#         "user@gwhost" or "user@gwhost:port".  "gwhost" is an incoming ssh 
#         gateway machine (the VNC server is not running there), an ssh -L
#         redir is used to "host" in "host:display" from "gwhost". Any "user@"
#         part must be in the -proxy string (not in "host:display").
#
#         Under -proxy use "gwhost:port" if connecting to any ssh port
#         other than the default (22).  (even for the non-gateway case,
#         -proxy must be used to specify a non-standard ssh port)
#
#         A "double ssh" can be specified via a -proxy string with the two
#         hosts separated by a comma:
#
#             [user1@]host1[:port1],[user2@]host2[:port2]
#
#         in which case a ssh to host1 and thru it via a -L redir a 2nd
#         ssh is established to host2.  
#
#         Examples:
#
#         ss_vncviewer -ssh bob@bobs-home.net:0
#         ss_vncviewer -ssh -sshcmd 'x11vnc -localhost' bob@bobs-home.net:0
#
#         ss_vncviewer -ssh -proxy fred@mygate.com:2022 mymachine:0
#         ss_vncviewer -ssh -proxy bob@bobs-home.net:2222 localhost:0
#
#         ss_vncviewer -ssh -proxy fred@gw-host,fred@peecee localhost:0
#
# -sshcmd cmd   Run "cmd" via ssh instead of the default "sleep 15"
#               e.g. -sshcmd 'x11vnc -display :0 -localhost -rfbport 5900'
#
# -sshargs "args"  pass "args" to the ssh process, e.g. -L/-R port redirs.
#
# -sshssl Tunnel the SSL connection thru a SSH connection.  The tunnel as
#         under -ssh is set up and the SSL connection goes thru it.  Use
#         this if you want to have and end-to-end SSL connection but must
#         go thru a SSH gateway host (e.g. not the vnc server).  Or use
#         this if you need to tunnel additional services via -R and -L 
#         (see -sshargs above).
#
#         ss_vncviewer -sshssl -proxy fred@mygate.com mymachine:0
#
# -listen (or -reverse) set up a reverse connection.
#
# -alpha  turn on cursor alphablending hack if you are using the
#         enhanced tightvnc vncviewer.
#
# -grab   turn on XGrabServer hack if you are using the enhanced tightvnc
#         vncviewer (e.g. for fullscreen mode in some windowmanagers like
#         fvwm that do not otherwise work in fullscreen mode)
#
#
# set VNCVIEWERCMD to whatever vncviewer command you want to use.
#
VNCIPCMD=${VNCVIEWERCMD:-vncip}
VNCVIEWERCMD=${VNCVIEWERCMD:-vncviewer}
#
# Same for STUNNEL, e.g. set it to /path/to/stunnel or stunnel4, etc.
#

# turn on verbose debugging output
if [ "X$SS_DEBUG" != "X" ]; then
	set -xv 
fi

PATH=$PATH:/usr/sbin:/usr/local/sbin:/dist/sbin; export PATH

# work out which stunnel t use (debian installs as stunnel4)
if [ "X$STUNNEL" = "X" ]; then
	type stunnel4 > /dev/null 2>&1
	if [ $? = 0 ]; then
		STUNNEL=stunnel4
	else
		STUNNEL=stunnel
	fi
fi

help() {
	tail -n +2 "$0" | sed -e '/^$/ q'
}

secondtry=""
gotalpha=""
use_ssh=""
use_sshssl=""
direct_connect=""
ssh_sleep=15

# sleep longer in -listen mode:
if echo "$*" | grep '.*-listen' > /dev/null; then
	ssh_sleep=1800
fi


ssh_cmd=""
# env override of ssh_cmd:
if [ "X$SS_VNCVIEWER_SSH_CMD" != "X" ]; then
	ssh_cmd="$SS_VNCVIEWER_SSH_CMD"
fi

ssh_args=""
showcert=""
reverse=""

if [ "X$1" = "X-viewerflavor" ]; then
	# special case, try to guess which viewer:
	#
	if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then
		echo "unknown"
		exit 0
	fi
	if echo "$VNCVIEWERCMD" | grep -i chicken.of > /dev/null; then
		echo "cotvnc"
		exit 0
	fi
	if echo "$VNCVIEWERCMD" | grep -i ultra > /dev/null; then
		echo "ultravnc"
		exit 0
	fi
	# OK, run it for help output...
	str=`$VNCVIEWERCMD -h 2>&1 | head -n 5`
	if echo "$str" | grep -i 'TightVNC.viewer' > /dev/null; then
		echo "tightvnc"
	elif echo "$str" | grep -i 'RealVNC.Ltd' > /dev/null; then
		echo "realvnc4"
	elif echo "$str" | grep -i 'VNC viewer version 3' > /dev/null; then
		echo "realvnc3"
	else
		echo "unknown"
	fi
	exit 0
fi

# maxconn is something we added to stunnel, this disables it:
if [ "X$SS_VNCVIEWER_NO_MAXCONN" != "X" ]; then
	STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'`
elif echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then
	STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'`
fi

# grab our cmdline options:
while [ "X$1" != "X" ]
do
    case $1 in 
	"-verify")	shift; verify="$1"
                ;;
	"-mycert")	shift; mycert="$1"
                ;;
	"-proxy")	shift; proxy="$1"
                ;;
	"-ssh")		use_ssh=1
                ;;
	"-sshssl")	use_ssh=1
			use_sshssl=1
                ;;
	"-sshcmd")	shift; ssh_cmd="$1"
                ;;
	"-sshargs")	shift; ssh_args="$1"
                ;;
	"-alpha")	gotalpha=1
                ;;
	"-showcert")	showcert=1
                ;;
	"-listen")	reverse=1
                ;;
	"-reverse")	reverse=1
                ;;
	"-2nd")		secondtry=1
                ;;
	"-grab")	VNCVIEWER_GRAB_SERVER=1; export VNCVIEWER_GRAB_SERVER
                ;;
	"-h"*)	help; exit 0
                ;;
	"--h"*)	help; exit 0
                ;;
	*)	break
                ;;
    esac
    shift
done

# this is the -t ssh option (gives better keyboard responsd thru SSH tunnel)
targ="-t"
if [ "X$SS_VNCVIEWER_NO_T" != "X" ]; then
	targ=""
fi

# set the alpha blending env. hack: 
if [ "X$gotalpha" = "X1" ]; then
	VNCVIEWER_ALPHABLEND=1
	export VNCVIEWER_ALPHABLEND
else
	NO_ALPHABLEND=1
	export NO_ALPHABLEND
fi

if [ "X$reverse" != "X" ]; then
	ssh_sleep=1800
	if [ "X$proxy" != "X" ]; then
		# check proxy usage under reverse connection:
		if [ "X$use_ssh" = "X" -a "X$use_sshssl" = "X" ]; then
			echo ""
			echo "*Warning*: SSL -listen and a Web proxy does not make sense."
			sleep 3
		elif echo "$proxy" | grep "," > /dev/null; then
			:
		else
			echo ""
			echo "*Warning*: -listen and a single proxy/gateway does not make sense."
			sleep 3
		fi
	fi
fi
if [ "X$ssh_cmd" = "X" ]; then
	# if no remote ssh cmd, sleep a bit:
	ssh_cmd="sleep $ssh_sleep"
fi

# this should be a host:display:
#
orig="$1"
shift

# check -ssh and -mycert/-verify conflict:
if [ "X$use_ssh" = "X1" -a "X$use_sshssl" = "X" ]; then
	if [ "X$mycert" != "X" -o "X$verify" != "X" ]; then
		echo "-mycert and -verify cannot be used in -ssh mode" 
		exit 1
	fi
fi

# direct mode Vnc:// means show no warnings.
# direct mode vnc:// will show warnings.
if echo "$orig" | grep '^V[Nn][Cc]://' > /dev/null; then
	SSVNC_NO_ENC_WARN=1
	export SSVNC_NO_ENC_WARN
	orig=`echo "$orig" | sed -e 's/^...:/vnc:/'`
fi

# interprest the pseudo URL proto:// strings:
if echo "$orig" | grep '^vnc://' > /dev/null; then
	orig=`echo "$orig" | sed -e 's,vnc://,,'`
	verify=""
	mycert=""
	use_ssh=""
	use_sshssl=""
	direct_connect=1
elif echo "$orig" | grep '^vncs://' > /dev/null; then
	orig=`echo "$orig" | sed -e 's,vncs://,,'`
elif echo "$orig" | grep '^vncssl://' > /dev/null; then
	orig=`echo "$orig" | sed -e 's,vncssl://,,'`
elif echo "$orig" | grep '^vnc+ssl://' > /dev/null; then
	orig=`echo "$orig" | sed -e 's,vnc.ssl://,,'`
elif echo "$orig" | grep '^vncssh://' > /dev/null; then
	orig=`echo "$orig" | sed -e 's,vncssh://,,'`
	use_ssh=1
elif echo "$orig" | grep '^vnc+ssh://' > /dev/null; then
	orig=`echo "$orig" | sed -e 's,vnc.ssh://,,'`
	use_ssh=1
fi

# (possibly) tell the vncviewer to only listen on lo: 
if [ "X$reverse" != "X" -a "X$direct_connect" = "X" ]; then
	VNCVIEWER_LISTEN_LOCALHOST=1
	export VNCVIEWER_LISTEN_LOCALHOST
fi

# rsh mode is an internal/secret thing only I use.
rsh=""
if echo "$orig" | grep '^rsh://' > /dev/null; then
	use_ssh=1
	rsh=1
	orig=`echo "$orig" | sed -e 's,rsh://,,'`
elif echo "$orig" | grep '^rsh:' > /dev/null; then
	use_ssh=1
	rsh=1
	orig=`echo "$orig" | sed -e 's,rsh:,,'`
fi

# play around with host:display port:
if echo "$orig" | grep ':' > /dev/null; then
	:
else
	# add or assume :0 if no ':'
	if [ "X$reverse" = "X" ]; then
		orig="$orig:0"
	elif [ "X$orig" = "X" ]; then
		orig=":0"
	fi
fi

# extract host and disp number:
host=`echo "$orig" | awk -F: '{print $1}'`
disp=`echo "$orig" | awk -F: '{print $2}'`
if [ "X$host" = "X" ]; then
	host=localhost
fi
if [ "X$disp" = "X" ]; then
	port=""	# probably -listen mode.
elif [ $disp -lt 0 ]; then
	# negative means use |n| without question:
	port=`expr 0 - $disp`
elif [ $disp -lt 200 ]; then
	# less than 200 means 5900+n
	if [ "X$reverse" = "X" ]; then
		port=`expr $disp + 5900`
	else
		port=`expr $disp + 5500`
	fi
else
	# otherwise use the number directly, e.g. 443, 2345
	port=$disp
fi

# try to find an open listening port via netstat(1):
inuse=""
if uname | grep Linux > /dev/null; then
	inuse=`netstat -ant | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*://'`
elif uname | grep SunOS > /dev/null; then
	inuse=`netstat -an -f inet -P tcp | grep LISTEN | awk '{print $1}' | sed 's/^.*\.//'`
elif uname | grep -i bsd > /dev/null; then
	inuse=`netstat -ant -f inet | grep LISTEN | awk '{print $4}' | sed 's/^.*\.//'`
# add others...
fi

# this is a crude attempt for unique ports tags, etc.
date_sec=`date +%S`

# these are special cases of no vnc, e.g. sleep or xmessage.
# these are for using ssvnc as a general port redirector.
if echo "$VNCVIEWERCMD" | grep '^sleep[ 	][ 	]*[0-9][0-9]*' > /dev/null; then
	if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then
		p=`echo "$VNCVIEWERCMD" | awk '{print $3}'`
		if [ "X$p" != "X" ]; then
			SS_VNCVIEWER_LISTEN_PORT=$p
		fi
	fi
	p2=`echo "$VNCVIEWERCMD" | awk '{print $2}'`
	VNCVIEWERCMD="eval sleep $p2; echo Local "
elif echo "$VNCVIEWERCMD" | grep '^xmessage[ 	][ 	]*[0-9][0-9]*' > /dev/null; then
	if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then
		p=`echo "$VNCVIEWERCMD" | awk '{print $2}'`
		SS_VNCVIEWER_LISTEN_PORT=$p
	fi
fi

# utility to find a free port to listen on.
findfree() {
	try0=$1
	try=$try0
	use0=""

	if [ "X$SS_VNCVIEWER_LISTEN_PORT" != "X" ]; then
		echo "$SS_VNCVIEWER_LISTEN_PORT"
		return	
	fi
	if [ $try -ge 6000 ]; then
		fmax=`expr $try + 1000`
	else
		fmax=6000
	fi

	while [ $try -lt $fmax ]
	do
		if [ "X$inuse" = "X" ]; then
			break
		fi
		if echo "$inuse" | grep -w $try > /dev/null; then
			:
		else
			use0=$try
			break
		fi
		try=`expr $try + 1`
	done
	if [ "X$use0" = "X" ]; then
		use0=`expr $date_sec + $try0`
	fi

	echo $use0
}

# utility for exiting; kills some helper processes,
# removes files, etc.
final() {
	echo ""
	if [ "X$SS_VNCVIEWER_RM" != "X" ]; then
		rm -f $SS_VNCVIEWER_RM 2>/dev/null
	fi
	if [ "X$tcert" != "X" ]; then
		rm -f $tcert
	fi
	if [ "X$pssh" != "X" ]; then
		echo "Terminating background ssh process"
		echo kill -TERM "$pssh"
		kill -TERM "$pssh" 2>/dev/null
		sleep 1
		kill -KILL "$pssh" 2>/dev/null
		pssh=""
	fi
	if [ "X$stunnel_pid" != "X" ]; then
		echo "Terminating background stunnel process"
		echo kill -TERM "$stunnel_pid"
		kill -TERM "$stunnel_pid" 2>/dev/null
		sleep 1
		kill -KILL "$stunnel_pid" 2>/dev/null
		stunnel_pid=""
	fi
	if [ "X$tail_pid" != "X" ]; then
		kill -TERM $tail_pid
	fi
}

if [ "X$reverse" = "X" ]; then
	# normal connections try 5930-5999:
	use=`findfree 5930`
	if [ $use -ge 5900 ]; then
		N=`expr $use - 5900`
	else
		N=$use
	fi
else
	# reverse connections:
	p2=`expr $port + 30`
	use=`findfree $p2`
	if [ $use -ge 5500 ]; then
		N=`expr $use - 5500`
	else
		N=$use
	fi
fi

# this is for my special use of ss_vncip -> vncip viewer.
if echo "$0" | grep vncip > /dev/null; then
	VNCVIEWERCMD="$VNCIPCMD"
fi

rchk() {
	# a kludge to set $RANDOM if we are not bash:
	if [ "X$BASH_VERSION" = "X" ]; then
		RANDOM=`date +%S``sh -c 'echo $$'``ps -elf 2>&1 | sum 2>&1 | awk '{print $1}'`
	fi
}
rchk

# a portable, but not absolutely safe, tmp file creator
mytmp() {
	tf=$1
	rm -rf "$tf" || exit 1
	if [ -d "$tf" ]; then
		echo "tmp file $tf still exists as a directory."
		exit 1
	elif [ -L "$tf" ]; then
		echo "tmp file $tf still exists as a symlink."
		exit 1
	elif [ -f "$tf" ]; then
		echo "tmp file $tf still exists."
		exit 1
	fi
	touch "$tf" || exit 1
	chmod 600 "$tf" || exit 1
	rchk
}

# trick for the undocumented rsh://host:port method.
rsh_setup() {
	if echo "$ssh_host" | grep '@' > /dev/null; then
		ul=`echo "$ssh_host" | awk -F@ '{print $1}'`
		ul="-l $ul"
		ssh_host=`echo "$ssh_host" | awk -F@ '{print $2}'`
	else
		ul=""
	fi
	ssh_cmd=`echo "$ssh_cmd" | sed -e 's/ -localhost/ /g'`
}

# trick for the undocumented rsh://host:port method.
rsh_viewer() {
	trap "final" 0 2 15
	if [ "X$PORT" = "X" ]; then
		exit 1
	elif [ $PORT -ge 5900 ]; then
		vdpy=`expr $PORT - 5900`
	else
		vdpy=":$PORT"
	fi
	stty sane
	echo "$VNCVIEWERCMD" "$@" $ssh_host:$vdpy
	echo ""
	$VNCVIEWERCMD "$@" $ssh_host:$vdpy
	if [ $? != 0 ]; then
		sleep 2
		$VNCVIEWERCMD "$@" $ssh_host:$vdpy
	fi
}

# this is the PPROXY tool.  used only here for now... 
pcode() {
	tf=$1
	PPROXY_PROXY=$proxy; export PPROXY_PROXY
	PPROXY_DEST="$host:$port"; export PPROXY_DEST
	cod='#!/usr/bin/perl

# A hack to glue stunnel to a Web proxy or SOCKS for client connections.

use IO::Socket::INET;

my ($first, $second, $third) = split(/,/, $ENV{PPROXY_PROXY}, 3);

if ($first =~ m,^socks4?://(\S*)$,i) {
	$ENV{PPROXY_SOCKS} = 1;
	$first = $1;
} elsif ($first =~ m,^socks5://(\S*)$,i) {
	$ENV{PPROXY_SOCKS} = 5;
	$first = $1;
} elsif ($first =~ m,^https?://(\S*)$,i) {
	$ENV{PPROXY_SOCKS} = "";
	$first = $1;
}

my ($proxy_host, $proxy_port) = split(/:/, $first);
my $connect = $ENV{PPROXY_DEST};

my $mode_2nd = "";
if ($second ne "") {
	if ($second =~ m,^socks4?://(\S*)$,i) {
		$mode_2nd = "socks4";
		$second = $1;
	} elsif ($second =~ m,^socks5://(\S*)$,i) {
		$mode_2nd = "socks5";
		$second = $1;
	} elsif ($second =~ m,^https?://(\S*)$,i) {
		$mode_2nd = "http";
		$second = $1;
	}
}

my $mode_3rd = "";
if ($third ne "") {
	if ($third =~ m,^socks4?://(\S*)$,i) {
		$mode_3rd = "socks4";
		$third = $1;
	} elsif ($third =~ m,^socks5://(\S*)$,i) {
		$mode_3rd = "socks5";
		$third = $1;
	} elsif ($third =~ m,^https?://(\S*)$,i) {
		$mode_3rd = "http";
		$third = $1;
	}
}

print STDERR "\n";
print STDERR "PPROXY v0.2: a tool for Web proxies and SOCKS connections.\n";
print STDERR "proxy_host:       $proxy_host\n";
print STDERR "proxy_port:       $proxy_port\n";
print STDERR "proxy_connect:    $connect\n";
print STDERR "pproxy_params:    $ENV{PPROXY_PROXY}\n";
print STDERR "pproxy_listen:    $ENV{PPROXY_LISTEN}\n";
print STDERR "\n";

my $listen_handle = "";
if ($ENV{PPROXY_LISTEN} != "") {
	my $listen_sock = IO::Socket::INET->new(
		Listen    => 2,
		LocalAddr => "localhost",
		LocalPort => $ENV{PPROXY_LISTEN},
		Proto     => "tcp"
	);
	if (! $listen_sock) {
		die "pproxy: $!\n";
	}
	my $ip;
	($listen_handle, $ip) = $listen_sock->accept();
	if (! $listen_handle) {
		die "pproxy: $!\n";
	}
}

my $sock = IO::Socket::INET->new(
	PeerAddr => $proxy_host,
	PeerPort => $proxy_port,
	Proto => "tcp"
);

if (! $sock) {
	my $err = $!;
	unlink($0) if $ENV{PPROXY_REMOVE};
	die "pproxy: $err\n";
}

sub connection {
	my ($CONNECT, $w) = @_;

	my $con = "";
	my $msg = "";

	if ($ENV{PPROXY_SOCKS} eq "5") {
		# SOCKS5
		my ($h, $p) = split(/:/, $CONNECT);
		$con .= pack("C", 0x05);
		$con .= pack("C", 0x01);
		$con .= pack("C", 0x00);

		$msg = "SOCKS5 via $cur_proxy to $h:$p\n\n";
		print STDERR "proxy_request$w: $msg";

		syswrite($sock, $con, length($con));

		my ($n1, $n2, $n3, $n4, $n5, $n6);
		my ($r1, $r2, $r3, $r4, $r5, $r6);
		my ($s1, $s2, $s3, $s4, $s5, $s6);

		$n1 = sysread($sock, $r1, 1);
		$n2 = sysread($sock, $r2, 1);

		$s1 = unpack("C", $r1);
		$s2 = unpack("C", $r2);
		if ($s1 != 0x05 || $s2 != 0x00) {
			print STDERR "SOCKS5 fail s1=$s1 s2=$s2 n1=$n1 n2=$n2\n";
			close $sock;
			exit(1);
		}

		$con = "";
		$con .= pack("C", 0x05);
		$con .= pack("C", 0x01);
		$con .= pack("C", 0x00);
		$con .= pack("C", 0x03);
		$con .= pack("C", length($h));
		$con .= $h;
		$con .= pack("C", $p >> 8);
		$con .= pack("C", $p & 0xff);

		syswrite($sock, $con, length($con));

		$n1 = sysread($sock, $r1, 1);
		$n2 = sysread($sock, $r2, 1);
		$n3 = sysread($sock, $r3, 1);
		$n4 = sysread($sock, $r4, 1);
		$s1 = unpack("C", $r1);
		$s2 = unpack("C", $r2);
		$s3 = unpack("C", $r3);
		$s4 = unpack("C", $r4);

		if ($s4 == 0x1) {
			sysread($sock, $r5, 4 + 2);
		} elsif ($s4 == 0x3) {
			sysread($sock, $r5, 1);
			$s5 = unpack("C", $r5);
			sysread($sock, $r6, $s5 + 2);
		} elsif ($s4 == 0x4) {
			sysread($sock, $r5, 16 + 2);
		}

		if ($s1 != 0x5 || $s2 != 0x0 || $s3 != 0x0) {
			print STDERR "SOCKS5 failed: s1=$s1 s2=$s2 s3=$s3 s4=$s4 n1=$n1 n2=$n2 n3=$n3 n4=$n4\n";
			close $sock;
			exit(1);
		}

	} elsif ($ENV{PPROXY_SOCKS} ne "") {
		# SOCKS4 SOCKS4a
		my ($h, $p) = split(/:/, $CONNECT);
		$con .= pack("C", 0x04);
		$con .= pack("C", 0x01);
		$con .= pack("n", $p);

		my $SOCKS_4a = 0;
		if ($h eq "localhost" || $h eq "127.0.0.1") {
			$con .= pack("C", 127);
			$con .= pack("C", 0);
			$con .= pack("C", 0);
			$con .= pack("C", 1);
		} elsif ($h =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
			$con .= pack("C", $1);
			$con .= pack("C", $2);
			$con .= pack("C", $3);
			$con .= pack("C", $4);
		} else {
			$con .= pack("C", 0);
			$con .= pack("C", 0);
			$con .= pack("C", 0);
			$con .= pack("C", 3);
			$SOCKS_4a = 1;
		}

		$con .= "nobody";
		$con .= pack("C", 0);

		$msg = "SOCKS4 via $cur_proxy to $h:$p\n\n";
		if ($SOCKS_4a) {
			$con .= $h;
			$con .= pack("C", 0);
			$msg =~ s/SOCKS4/SOCKS4a/;
		}
		print STDERR "proxy_request$w: $msg";
		syswrite($sock, $con, length($con));

		my $ok = 1;
		for (my $i = 0; $i < 8; $i++) {
			my $c;
			sysread($sock, $c, 1);
			my $s = unpack("C", $c);
			if ($i == 0) {
				$ok = 0 if $s != 0x0;
			} elsif ($i == 1) {
				$ok = 0 if $s != 0x5a;
			}
		}
		if (! $ok) {
			print STDERR "SOCKS4 failed.\n";
			close $sock;
			exit(1);
		}

	} else {
		# Web Proxy:
		$con = "CONNECT $CONNECT HTTP/1.1\r\n";
		$con   .= "Host: $CONNECT\r\n";
		$con   .= "Connection: close\r\n\r\n";
		$msg = $con;

		print STDERR "proxy_request$w: via $cur_proxy:\n$msg";
		syswrite($sock, $con, length($con));

		my $rep = "";
		my $n = 0;
		while ($rep !~ /\r\n\r\n/ && $n < 30000) {
			my $c;
			sysread($sock, $c, 1);
			print STDERR $c;
			$rep .= $c;
			$n++;
		}
		if ($rep !~ m,HTTP/.* 200,) {
			print STDERR "HTTP CONNECT failed.\n";
			close $sock;
			exit(1);
		}
	}
}

unlink($0) if $ENV{PPROXY_REMOVE};

$cur_proxy = $first;

if ($second ne "") {
	connection($second, 1);

	setmode($mode_2nd);
	$cur_proxy = $second;

	if ($third ne "") {
		connection($third, 2);
		setmode($mode_3rd);
		$cur_proxy = $third;
		connection($connect, 3);
	} else {
		connection($connect, 2);
	}
} else {
	connection($connect, 1);
}

$parent = $$;
$child = fork;
if (! defined $child) {
	exit 1;
}

if ($child) {
	print STDERR "pproxy parent\[$$]  STDIN -> socket\n";
	if ($listen_handle) {
		xfer($listen_handle, $sock);
	} else {
		xfer(STDIN, $sock);
	}
	select(undef, undef, undef, 0.25);
	if (kill 0, $child) {
		select(undef, undef, undef, 1.5);
		#print STDERR "pproxy\[$$]: kill TERM $child\n";
		kill "TERM", $child;
	}
} else {
	print STDERR "pproxy child \[$$]  socket -> STDOUT\n";
	if ($listen_handle) {
		xfer($sock, $listen_handle);
	} else {
		xfer($sock, STDOUT);
	}
	select(undef, undef, undef, 0.25);
	if (kill 0, $parent) {
		select(undef, undef, undef, 1.5);
		#print STDERR "pproxy\[$$]: kill TERM $parent\n";
		kill "TERM", $parent;
	}
}
exit;

sub setmode {
	my $mode = shift;
	if ($mode =~ /^socks/) {
		if ($mode =~ /^socks5/) {
			$ENV{PPROXY_SOCKS} = 5;
		} else {
			$ENV{PPROXY_SOCKS} = 1;
		}
	} else {
		$ENV{PPROXY_SOCKS} = "";
	}
}

sub xfer {
	my($in, $out) = @_;
	$RIN = $WIN = $EIN = "";
	$ROUT = "";
	vec($RIN, fileno($in), 1) = 1;
	vec($WIN, fileno($in), 1) = 1;
	$EIN = $RIN | $WIN;

	while (1) {
		my $nf = 0;
		while (! $nf) {
			$nf = select($ROUT=$RIN, undef, undef, undef);
		}
		my $len = sysread($in, $buf, 8192);
		if (! defined($len)) {
			next if $! =~ /^Interrupted/;
			print STDERR "pproxy\[$$]: $!\n";
			last;
		} elsif ($len == 0) {
			print STDERR "pproxy\[$$]: Input is EOF.\n";
			last;
		}
		my $offset = 0;
		my $quit = 0;
		while ($len) {
			my $written = syswrite($out, $buf, $len, $offset);
			if (! defined $written) {
				print STDERR "pproxy\[$$]: Output is EOF. $!\n";
				$quit = 1;
				last;
			}
			$len -= $written;
			$offset += $written;
		}
		last if $quit;
	}
	close($in);
	close($out);
}
'
	# xpg_echo will expand \n \r, etc.
	# try to unset and then test for it.
	shopt -u xpg_echo >/dev/null 2>&1
	v='print STDOUT "abc\n";'
	echo "$v" > $tf
	chmod 700 $tf

	lc=`wc -l $tf | awk '{print $1}'`
	if [ "X$lc" = "X1" ]; then
		echo "$cod" > $tf
	else
		printf "%s" "$cod" > $tf
		echo "" >> $tf
	fi
	# prime perl
	perl -e 'use IO::Socket::INET; select(undef, undef, undef, 0.01)' >/dev/null 2>&1
}

Kecho() {
	if [ "X$USER" = "Xrunge" ]; then
		echo "dbg: $*"
	fi
}

if [ "X$use_ssh" = "X1" ]; then
	#
	# USING SSH
	#
	ssh_port="22"
	ssh_host="$host"
	vnc_host="localhost"
	# let user override ssh via $SSH
	ssh=${SSH:-"ssh -x"}

	if echo "$proxy" | egrep '(http|https|socks|socks4|socks5)://' > /dev/null; then
		# Handle Web or SOCKS proxy(ies) for the initial connect.
Kecho host=$host
Kecho port=$port
		pproxy=""
		sproxy1=""
		sproxy_rest=""
		for part in `echo "$proxy" | tr ',' ' '`
		do
			Kecho proxy_part=$part
			if [ "X$part" = "X" ]; then
				continue
			elif echo "$part" | egrep -i '^(http|https|socks|socks4|socks5)://' > /dev/null; then
				pproxy="$pproxy,$part"
			else
				if [ "X$sproxy1" = "X" ]; then
					sproxy1="$part"
				else
					sproxy_rest="$sproxy_rest,$part"
				fi
			fi
		done
		pproxy=`echo "$pproxy" | sed -e 's/^,,*//' -e 's/,,*/,/g'`
		sproxy_rest=`echo "$sproxy_rest" | sed -e 's/^,,*//' -e 's/,,*/,/g'`
Kecho pproxy=$pproxy
Kecho sproxy1=$sproxy1
Kecho sproxy_rest=$sproxy_rest

		sproxy1_host=""
		sproxy1_port=""
		sproxy1_user=""

		if [ "X$sproxy1" != "X" ]; then
			sproxy1_host=`echo "$sproxy1" | awk -F: '{print $1}'`
			sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'`
			sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'`
			if [ "X$sproxy1_host" = "X" ]; then
				sproxy1_host=$sproxy1_user
				sproxy1_user=""
			else
				sproxy1_user="${sproxy1_user}@"
			fi
			sproxy1_port=`echo "$sproxy1" | awk -F: '{print $2}'`
			if [ "X$sproxy1_port" = "X" ]; then
				sproxy1_port="22"
			fi
		else
			sproxy1_host=`echo "$host" | awk -F: '{print $1}'`
			sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'`
			sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'`
			if [ "X$sproxy1_host" = "X" ]; then
				sproxy1_host=$sproxy1_user
				sproxy1_user=""
			else
				sproxy1_user="${sproxy1_user}@"
			fi
			sproxy1_port=`echo "$host" | awk -F: '{print $2}'`
			if [ "X$sproxy1_port" = "X" ]; then
				sproxy1_port="22"
			fi
		fi

Kecho sproxy1_host=$sproxy1_host
Kecho sproxy1_port=$sproxy1_port
Kecho sproxy1_user=$sproxy1_user

		ptmp="/tmp/ss_vncviewer${RANDOM}.$$.pl"
		mytmp "$ptmp"
		PPROXY_REMOVE=1; export PPROXY_REMOVE
		proxy=$pproxy
		port_save=$port
		host_save=$host
		if [ "X$sproxy1_host" != "X" ]; then
			host=$sproxy1_host
		fi
		if [ "X$sproxy1_port" != "X" ]; then
			port=$sproxy1_port
		fi
		host=`echo "$host" | sed -e 's/^.*@//'`
		port=`echo "$port" | sed -e 's/^.*://'`
		pcode "$ptmp"
		port=$port_save
		host=$host_save

		nd=`findfree 6700`
		PPROXY_LISTEN=$nd; export PPROXY_LISTEN
		$ptmp &
		sleep 2
		ssh_args="$ssh_args -o NoHostAuthenticationForLocalhost=yes"
		if [ "X$sproxy1" = "X" ]; then
			u=""
			if echo "$host" | grep '@' > /dev/null; then
				u=`echo "$host" | sed -e 's/@.*$/@/'`
			fi
			
			proxy="${u}localhost:$nd"
		else
			proxy="${sproxy1_user}localhost:$nd"
		fi
		if [ "X$sproxy_rest" != "X" ]; then
			proxy="$proxy,$sproxy_rest"
		fi
Kecho proxy=$proxy
	fi

	if echo "$proxy" | grep "," > /dev/null; then

		proxy1=`echo "$proxy" | awk -F, '{print $1}'`
		proxy2=`echo "$proxy" | awk -F, '{print $2}'`

		# user1@gw1.com:port1,user2@ws2:port2
		ssh_host1=`echo "$proxy1" | awk -F: '{print $1}'`
		ssh_port1=`echo "$proxy1" | awk -F: '{print $2}'`
		if [ "X$ssh_port1" != "X" ]; then
			ssh_port1="-p $ssh_port1"
		fi
		ssh_host2=`echo "$proxy2" | awk -F: '{print $1}'`
		ssh_user2=`echo "$ssh_host2" | awk -F@ '{print $1}'`
		ssh_host2=`echo "$ssh_host2" | awk -F@ '{print $2}'`
		if [ "X$ssh_host2" = "X" ]; then
			ssh_host2=$ssh_user2
			ssh_user2=""
		else
			ssh_user2="${ssh_user2}@"
		fi
		ssh_port2=`echo "$proxy2" | awk -F: '{print $2}'`
		if [ "X$ssh_port2" = "X" ]; then
			ssh_port2="22"
		fi
		proxport=`findfree 3500`
		echo
		echo "Running 1st ssh proxy:"
		echo "$ssh -f -x $ssh_port1 $targ -e none -o NoHostAuthenticationForLocalhost=yes -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 \"sleep 30\""
		echo ""
		      $ssh -f -x $ssh_port1 $targ -e none -o NoHostAuthenticationForLocalhost=yes -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 "sleep 30"
		ssh_args="$ssh_args -o NoHostAuthenticationForLocalhost=yes"
		sleep 1
		stty sane
		proxy="${ssh_user2}localhost:$proxport"
	fi

	if [ "X$proxy" != "X" ]; then
		ssh_port=`echo "$proxy" | awk -F: '{print $2}'`
		if [ "X$ssh_port" = "X" ]; then
			ssh_port="22"
		fi
		ssh_host=`echo "$proxy" | awk -F: '{print $1}'`
		vnc_host="$host"
	fi

	echo ""
	echo "Running ssh:"
	sz=`echo "$ssh_cmd" | wc -c`
	if [ "$sz" -gt 300 ]; then
		info="..."
	else
		info="$ssh_cmd"
	fi

	C=""
	if [ "X$SS_VNCVIEWER_USE_C" != "X" ]; then
		C="-C"
	fi

	getport=""
	teeport=""
	if echo "$ssh_cmd" | egrep "^(PORT=|P=)" > /dev/null; then
		getport=1
		if echo "$ssh_cmd" | egrep "^P=" > /dev/null; then
			teeport=1
		fi

		PORT=""
		ssh_cmd=`echo "$ssh_cmd" | sed -e 's/^PORT=[ 	]*//' -e 's/^P=//'`
		SSVNC_NO_ENC_WARN=1
		if [ "X$use_sshssl" = "X" ]; then
			direct_connect=1
		fi
	fi
	if [ "X$getport" != "X" ]; then
		ssh_redir="-D ${use}"
	elif [ "X$reverse" = "X" ]; then
		ssh_redir="-L ${use}:${vnc_host}:${port}"
	else
		ssh_redir="-R ${port}:${vnc_host}:${use}"
	fi
	pmark=`sh -c 'echo $$'`

	# the -t option actually speeds up typing response via VNC!!
	if [ "X$ssh_port" = "X22" ]; then
		ssh_port=""
	else
		ssh_port="-p $ssh_port"
	fi

	if [ "X$SS_VNCVIEWER_SSH_ONLY" != "X" ]; then
		echo "$ssh -x $ssh_port $targ $C $ssh_args $ssh_host \"$info\""
		echo ""
		$ssh -x $ssh_port $targ $C $ssh_args $ssh_host "$ssh_cmd"
		exit $?

	elif [ "X$SS_VNCVIEWER_NO_F" != "X" ]; then
		echo "$ssh -x $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\""
		echo ""
		$ssh -x $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd"
		rc=$?

	elif [ "X$getport" != "X" ]; then
		tport=/tmp/tport${RANDOM}.$$
		mytmp $tport

		if [ "X$rsh" != "X1" ]; then
			if echo "$ssh_cmd" | grep -w sudo > /dev/null; then
				echo ""
				echo "Initial ssh with 'sudo id' to prime sudo so hopefully the next one"
				echo "will require no password..."
				echo ""
				targ="-t"
				$ssh -x $ssh_port $targ $ssh_args $ssh_host "sudo id; tty"
				echo ""
			fi
			echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\""
			echo ""
			$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd" > $tport 
			if [ "X$teeport" = "X1" ]; then
				tail -f $tport 1>&2 &
				tail_pid=$!
			fi
			rc=$?
		else
			rsh_setup
			echo "rsh $ul $ssh_host \"$ssh_cmd\""
			echo ""
			rsh $ul $ssh_host "$ssh_cmd" > $tport &
			sleep 1
			rc=0
		fi

		if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
			sleep $SSVNC_EXTRA_SLEEP
		fi

		stty sane
		i=0
		if type perl > /dev/null 2>&1; then
			imax=50
			sleepit="perl -e 'select(undef, undef, undef, 0.20)'"
		else
			imax=10
			sleepit="sleep 1"
		fi
		while [ $i -lt $imax ]; do
			#echo $sleepit
			eval $sleepit
			PORT=`grep "^PORT=" $tport | head -n 1 | sed -e 's/PORT=//' -e 's/\r//g'`
			if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
				break
			fi
			vnss=`sed -e 's/\r//g' $tport | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1 | awk '{print $NF}'`
			if [ "X$vnss" != "X" ]; then
				PORT=`echo "$vnss" | awk -F: '{print $2}'`
				if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
					if [ $PORT -lt 100 ]; then
						PORT=`expr $PORT + 5900`
					fi
				fi
				if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
					break
				fi
			fi
			i=`expr $i + 1`
		done

		echo "PORT=$PORT" 1>&2
		rm -f $tport
		if [ "X$rsh" = "X1" ]; then
			rsh_viewer "$@"
			exit $?
		fi
		PPROXY_SOCKS=1
		if [ "X$SSVNC_SOCKS5" != "X" ]; then
			PPROXY_SOCKS=5
		fi
		export PPROXY_SOCKS
		host="localhost"
		port="$PORT"
		proxy="localhost:$use"

	else
		if [ "X$rsh" != "X1" ]; then
			echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\""
			echo ""
			$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd"
			rc=$?
		else
			rsh_setup
			echo "rsh $ul $ssh_host \"$ssh_cmd\""
			echo ""
			rsh $ul $ssh_host "$ssh_cmd" &
			sleep 1
			PORT=$port
			rsh_viewer "$@"
			exit $?
		fi
	fi

	if [ "$rc" != "0" ]; then
		echo ""
		echo "ssh to $ssh_host failed."
		exit 1
	fi
	stty sane

	c=0
	pssh=""
	while [ $c -lt 30 ]
	do
		p=`expr $pmark + $c`
		if ps -p "$p" 2>&1 | grep "$ssh" > /dev/null; then
			pssh=$p
			break
		fi
		c=`expr $c + 1`
	done
	if [ "X$getport" != "X" ]; then
		:
	elif [ "X$ssh_cmd" = "Xsleep $ssh_sleep" ] ; then
		#echo T sleep 1
		sleep 1
	elif echo "$ssh_cmd" | grep '^sleep ' >/dev/null; then
		#echo T sleep 2
		sleep 2
	else
		# let any command get started a bit.
		#echo T sleep 5
		sleep 5
	fi
	echo ""
	if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
		#echo T sleep $SSVNC_EXTRA_SLEEP
		sleep $SSVNC_EXTRA_SLEEP
	fi
	#reset
	stty sane
	#echo "pssh=\"$pssh\""
	if [ "X$use_sshssl" = "X" -a "X$getport" = "X" ]; then
		echo "Running viewer:"

		trap "final" 0 2 15
		if [ "X$reverse" = "X" ]; then
			echo "$VNCVIEWERCMD" "$@" localhost:$N
			echo ""
			$VNCVIEWERCMD "$@" localhost:$N
			if [ $? != 0 ]; then
				echo "vncviewer command failed: $?"
				if [ "X$secondtry" = "X1" ]; then
					sleep 2
					$VNCVIEWERCMD "$@" localhost:$N
				fi
			fi
		else
			echo ""
			echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode."
			echo ""
			echo "$VNCVIEWERCMD" "$@" -listen $N
			echo ""
			$VNCVIEWERCMD "$@" -listen $N
		fi

		exit $?
	else
		use2=`findfree 5960`
		host0=$host
		port0=$port
		host=localhost
		port=$use
		use=$use2
		N=`expr $use - 5900`
		if [ "X$getport" != "X" ]; then
			host="$host0"
			port="$port0"
		else
			proxy=""
		fi
	fi
fi

# create the stunnel config file:
if [ "X$verify" != "X" ]; then
	if [ -d $verify ]; then
		verify="CApath = $verify"
	else
		verify="CAfile = $verify"
	fi
	verify="$verify
verify = 2"
fi
if [ "X$mycert" != "X" ]; then
	cert="cert = $mycert"
fi

ptmp=""
if [ "X$proxy" != "X" ]; then
	ptmp="/tmp/ss_vncviewer${RANDOM}.$$.pl"
	mytmp "$ptmp"
	PPROXY_REMOVE=1; export PPROXY_REMOVE
	pcode "$ptmp"
	if [ "X$showcert" != "X1" -a "X$direct_connect" = "X" ]; then
		if uname | grep Darwin >/dev/null; then
			# on mac we need to listen on socket instead of stdio:
			nd=`findfree 6700`
			PPROXY_LISTEN=$nd
			export PPROXY_LISTEN
			$ptmp 2>/dev/null &
			#sleep 3
			sleep 2
			host="localhost"
			port="$nd"
			connect="connect = localhost:$nd"
		else
			# otherwise on unix we can exec it:
			connect="exec = $ptmp"
		fi
	else
		connect="exec = $ptmp"
	fi
else
	connect="connect = $host:$port"
fi

if [ "X$showcert" = "X1" ]; then
	if [ "X$proxy" != "X" ]; then
		PPROXY_LISTEN=$use
		export PPROXY_LISTEN
		$ptmp 2>/dev/null &
		sleep 1
		host="localhost"
		port="$use"
	fi
	openssl s_client -connect $host:$port 2>&1 < /dev/null
	exit $?
fi

if [ "X$direct_connect" != "X" ]; then
	if [ "X$getport" = "X" ]; then
		echo ""
		echo "Running viewer for direct connection:"
		echo ""
		echo "** NOTE: THERE WILL BE NO SSL OR SSH ENCRYPTION **"
		echo ""
	fi
	x=""
	if [ "X$SSVNC_NO_ENC_WARN" != "X" ]; then
		if [ "X$getport" = "X" ]; then
			sleep 1
		fi
	elif type printf > /dev/null 2>&1; then
		printf  "Are you sure you want to continue? [y]/n "
		read x
	else
		echo -n "Are you sure you want to continue? [y]/n "
		read x
	fi
	if [ "X$x" = "Xn" ]; then
		exit 1
	fi
	echo ""
	if [ "X$ptmp" != "X" ]; then
		PPROXY_LISTEN=$use
		export PPROXY_LISTEN
		$ptmp &
		if [ "X$reverse" = "X" ]; then
			#sleep 2
			#echo T sleep 1
			sleep 1
		fi
		host="localhost"
		disp="$N"
	fi
	if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
		#echo T sleep $SSVNC_EXTRA_SLEEP
		sleep $SSVNC_EXTRA_SLEEP
	fi
	if [ "X$reverse" = "X" ]; then
		echo "$VNCVIEWERCMD" "$@" $host:$disp
		trap "final" 0 2 15
		echo ""
		$VNCVIEWERCMD "$@" $host:$disp
		if [ $? != 0 ]; then
			echo "vncviewer command failed: $?"
			if [ "X$secondtry" = "X1" ]; then
				sleep 2
				$VNCVIEWERCMD "$@" $host:$disp
			fi
		fi
	else
		echo ""
		echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode."
		echo ""
		echo "$VNCVIEWERCMD" "$@" -listen $disp
		trap "final" 0 2 15
		echo ""
		$VNCVIEWERCMD "$@" -listen $disp
	fi
	exit $?
fi

tmp=/tmp/ss_vncviewer${RANDOM}.$$
mytmp "$tmp"

if [ "X$reverse" = "X" ]; then

	cat > "$tmp" <<END
foreground = yes
pid =
client = yes
debug = 6
$STUNNEL_EXTRA_OPTS
$verify
$cert

[vnc_stunnel]
accept = localhost:$use
$connect

END
else

	p2=`expr 5500 + $N`
	connect="connect = localhost:$p2"
	if [ "X$cert" = "X" ]; then
		tcert="/tmp/tcert${RANDOM}.$$"
		cat > $tcert <<END
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvkfXxb0wcxgrjV2ziFikjII+ze8iKcTBt47L0GM/c21efelN
+zZpJUUXLu4zz8Ryq8Q+sQgfNy7uTOpN9bUUaOk1TnD7gaDQnQWiNHmqbW2kL+DS
OKngJVPo9dETAS8hf7+D1e1DBZxjTc1a4RQqWJixwpYj99ixWzu8VC2m/xXsjvOs
jp4+DLBB490nbkwvstmhmiWm1CmI5O5xOkgioVNQqHvQMdVKOSz9PpbjvZiRX1Uo
qoMrk+2NOqwP90TB35yPASXb9zXKpO7DLhkube+yYGf+yk46aD707L07Eb7cosFP
S84vNZ9gX7rQ0UOwm5rYA/oZTBskgaqhtIzkLwIDAQABAoIBAD4ot/sXt5kRn0Ca
CIkU9AQWlC+v28grR2EQW9JiaZrqcoDNUzUqbCTJsi4ZkIFh2lf0TsqELbZYNW6Y
6AjJM7al4E0UqYSKJTv2WCuuRxdiRs2BMwthqyBmjeanev7bB6V0ybt7u3Y8xU/o
MrTuYnr4vrEjXPKdLirwk7AoDbKsRXHSIiHEIBOq1+dUQ32t36ukdnnza4wKDLZc
PKHiCdCk/wOGhuDlxD6RspqUAlRnJ8/aEhrgWxadFXw1hRhRsf/v1shtB0T3DmTe
Jchjwyiw9mryb9JZAcKxW+fUc4EVvj6VdQGqYInQJY5Yxm5JAlVQUJicuuJEvn6A
rj5osQECgYEA552CaHpUiFlB4HGkjaH00kL+f0+gRF4PANCPk6X3UPDVYzKnzmuu
yDvIdEETGFWBwoztUrOOKqVvPEQ+kBa2+DWWYaERZLtg2cI5byfDJxQ3ldzilS3J
1S3WgCojqcsG/hlxoQJ1dZFanUy/QhUZ0B+wlC+Zp1Q8AyuGQvhHp68CgYEA0lBI
eqq2GGCdJuNHMPFbi8Q0BnX55LW5C1hWjhuYiEkb3hOaIJuJrqvayBlhcQa2cGqp
uP34e9UCfoeLgmoCQ0b4KpL2NGov/mL4i8bMgog4hcoYuIi3qxN18vVR14VKEh4U
RLk0igAYPU+IK2QByaQlBo9OSaKkcfm7U1/pK4ECgYAxr6VpGk0GDvfF2Tsusv6d
GIgV8ZP09qSLTTJvvxvF/lQYeqZq7sjI5aJD5i3de4JhpO/IXQJzfZfWOuGc8XKA
3qYK/Y2IqXXGYRcHFGWV/Y1LFd55mCADHlk0l1WdOBOg8P5iRu/Br9PbiLpCx9oI
vrOXpnp03eod1/luZmqguwKBgQCWFRSj9Q7ddpSvG6HCG3ro0qsNsUMTI1tZ7UBX
SPogx4tLf1GN03D9ZUZLZVFUByZKMtPLX/Hi7K9K/A9ikaPrvsl6GEX6QYzeTGJx
3Pw0amFrmDzr8ySewNR6/PXahxPEuhJcuI31rPufRRI3ZLah3rFNbRbBFX+klkJH
zTnoAQKBgDbUK/aQFGduSy7WUT7LlM3UlGxJ2sA90TQh4JRQwzur0ACN5GdYZkqM
YBts4sBJVwwJoxD9OpbvKu3uKCt41BSj0/KyoBzjT44S2io2tj1syujtlVUsyyBy
/ca0A7WBB8lD1D7QMIhYUm2O9kYtSCLlUTHt5leqGaRG38DqlX36
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDzDCCArQCCQDSzxzxqhyqLzANBgkqhkiG9w0BAQQFADCBpzELMAkGA1UEBhMC
VVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxDzANBgNVBAcTBkJvc3RvbjETMBEG
A1UEChMKTXkgQ29tcGFueTEcMBoGA1UECxMTUHJvZHVjdCBEZXZlbG9wbWVudDEZ
MBcGA1UEAxMQd3d3Lm5vd2hlcmUubm9uZTEhMB8GCSqGSIb3DQEJARYSYWRtaW5A
bm93aGVyZS5ub25lMB4XDTA3MDMyMzE4MDc0NVoXDTI2MDUyMjE4MDc0NVowgacx
CzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNodXNldHRzMQ8wDQYDVQQHEwZC
b3N0b24xEzARBgNVBAoTCk15IENvbXBhbnkxHDAaBgNVBAsTE1Byb2R1Y3QgRGV2
ZWxvcG1lbnQxGTAXBgNVBAMTEHd3dy5ub3doZXJlLm5vbmUxITAfBgkqhkiG9w0B
CQEWEmFkbWluQG5vd2hlcmUubm9uZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAL5H18W9MHMYK41ds4hYpIyCPs3vIinEwbeOy9BjP3NtXn3pTfs2aSVF
Fy7uM8/EcqvEPrEIHzcu7kzqTfW1FGjpNU5w+4Gg0J0FojR5qm1tpC/g0jip4CVT
6PXREwEvIX+/g9XtQwWcY03NWuEUKliYscKWI/fYsVs7vFQtpv8V7I7zrI6ePgyw
QePdJ25ML7LZoZolptQpiOTucTpIIqFTUKh70DHVSjks/T6W472YkV9VKKqDK5Pt
jTqsD/dEwd+cjwEl2/c1yqTuwy4ZLm3vsmBn/spOOmg+9Oy9OxG+3KLBT0vOLzWf
YF+60NFDsJua2AP6GUwbJIGqobSM5C8CAwEAATANBgkqhkiG9w0BAQQFAAOCAQEA
vGomHEp6TVU83X2EBUgnbOhzKJ9u3fOI/Uf5L7p//Vxqow7OR1cguzh/YEzmXOIL
ilMVnzX9nj/bvcLAuqEP7MR1A8f4+E807p/L/Sf49BiCcwQq5I966sGKYXjkve+T
2GTBNwMSq+5kLSf6QY8VZI+qnrAudEQMeJByQhTZZ0dH8Njeq8EGl9KUio+VWaiW
CQK6xJuAvAHqa06OjLmwu1fYD4GLGSrOIiRVkSXV8qLIUmzxdJaIRznkFWsrCEKR
wAH966SAOvd2s6yOHMvyDRIL7WHxfESB6rDHsdIW/yny1fBePjv473KrxyXtbz7I
dMw1yW09l+eEo4A7GzwOdw==
-----END CERTIFICATE-----
END
		chmod 600 $tcert
		cert="cert = $tcert"
	fi

	STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'`

	hloc=""
	if [ "X$use_ssh" = "X1" ]; then
		hloc="localhost:"
	fi
	cat > "$tmp" <<END
foreground = yes
pid =
client = no
debug = 6
$STUNNEL_EXTRA_OPTS
$verify
$cert

[vnc_stunnel]
accept = $hloc$port
$connect

END

fi

echo ""
echo "Using this stunnel configuration:"
echo ""
cat "$tmp" | uniq
echo ""
sleep 1

echo ""
echo "Running stunnel:"
echo "$STUNNEL $tmp"
st=`echo "$STUNNEL" | awk '{print $1}'`
$st -help > /dev/null 2>&1
$STUNNEL "$tmp" < /dev/tty > /dev/tty &
stunnel_pid=$!
echo ""

# pause here to let the user supply a possible passphrase for the
# mycert key:
if [ "X$mycert" != "X" ]; then
	sleep 1
	echo ""
	echo "(pausing for possible certificate passphrase dialog)"
	echo ""
	sleep 4
fi
#echo T sleep 1
sleep 1
rm -f "$tmp"

echo ""
if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
	sleep $SSVNC_EXTRA_SLEEP
fi
echo "Running viewer:"
if [ "X$reverse" = "X" ]; then
	echo "$VNCVIEWERCMD" "$@" localhost:$N
	trap "final" 0 2 15
	echo ""
	$VNCVIEWERCMD "$@" localhost:$N
	if [ $? != 0 ]; then
		echo "vncviewer command failed: $?"
		if [ "X$secondtry" = "X1" ]; then
			sleep 2
			$VNCVIEWERCMD "$@" localhost:$N
		fi
	fi
else
	echo ""
	echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode."
	echo ""
	echo "$VNCVIEWERCMD" "$@" -listen $N
	trap "final" 0 2 15
	echo ""
	$VNCVIEWERCMD "$@" -listen $N
fi

sleep 1