#include "vnc.h"
#include "vncv.h"
#include <libsec.h>
char* encodings = "copyrect hextile corre rre raw mousewarp";
int bpp12;
int shared;
int verbose;
Vnc* vnc;
int mousefd;
int tls;
static int vncstart(Vnc*, int);
enum
{
NProcs = 4
};
static int pids[NProcs];
static char killkin[] = "die vnc kin";
/*
* called by any proc when exiting to tear everything down.
*/
static void
shutdown(void)
{
int i, pid;
hangup(vnc->ctlfd);
close(vnc->ctlfd);
vnc->ctlfd = -1;
close(vnc->datafd);
vnc->datafd = -1;
pid = getpid();
for(i = 0; i < NProcs; i++)
if(pids[i] != pid)
postnote(PNPROC, pids[i], killkin);
}
char*
netmkvncaddr(char *inserver)
{
char *p, portstr[NETPATHLEN], *server;
int port;
server = strdup(inserver);
assert(server != nil);
port = 5900;
if(tls)
port = 35729;
if(p = strchr(server, ':')) {
*p++ = '\0';
port += atoi(p);
}
snprint(portstr, sizeof portstr, "%d", port);
p = netmkaddr(server, "tcp", portstr);
free(server);
return p;
}
void
vnchungup(Vnc*)
{
sysfatal("connection closed");
}
void
usage(void)
{
fprint(2, "usage: vncv [-e encodings] [-k keypattern] [-csv] host[:n]\n");
exits("usage");
}
void
main(int argc, char **argv)
{
int p, fd, dfd, cfd, shared;
char *keypattern, *addr;
Point d;
TLSconn conn;
keypattern = nil;
shared = 0;
ARGBEGIN{
case 'c':
bpp12 = 1;
break;
case 'e':
encodings = EARGF(usage());
break;
case 's':
shared = 1;
break;
case 't':
tls = 1;
break;
case 'v':
verbose = 1;
break;
case 'k':
keypattern = EARGF(usage());
break;
default:
usage();
}ARGEND;
if(argc != 1)
usage();
addr = netmkvncaddr(argv[0]);
serveraddr = argv[0];
dfd = dial(addr, nil, nil, &cfd);
if(dfd < 0)
sysfatal("cannot dial %s: %r", addr);
if(tls){
dfd = tlsClient(dfd, &conn);
if(dfd < 0)
sysfatal("tlsClient: %r");
/* XXX check thumbprint */
}
vnc = vncinit(dfd, cfd, nil);
if(vnchandshake(vnc) < 0)
sysfatal("handshake failure: %r");
if(vncauth(vnc, keypattern) < 0)
sysfatal("authentication failure: %r");
if(vncstart(vnc, shared) < 0)
sysfatal("init failure: %r");
initdraw(0, 0, "vncv");
display->locking = 1;
unlockdisplay(display);
d = addpt(vnc->dim, Pt(2*Borderwidth, 2*Borderwidth));
if(verbose)
fprint(2, "screen size %P, desktop size %P\n", display->image->r.max, d);
choosecolor(vnc);
sendencodings(vnc);
initmouse();
rfork(RFREND);
atexit(shutdown);
pids[0] = getpid();
switch(p = rfork(RFPROC|RFMEM)){
case -1:
sysfatal("rfork: %r");
default:
break;
case 0:
atexit(shutdown);
readfromserver(vnc);
exits(nil);
}
pids[1] = p;
switch(p = rfork(RFPROC|RFMEM)){
case -1:
sysfatal("rfork: %r");
default:
break;
case 0:
atexit(shutdown);
checksnarf(vnc);
exits(nil);
}
pids[2] = p;
fd = open("/dev/label", OWRITE);
if(fd >= 0){
fprint(fd, "vnc %s", serveraddr);
close(fd);
}
if(access("/dev/snarf", AEXIST) >= 0){
switch(p = rfork(RFPROC|RFMEM)){
case -1:
sysfatal("rfork: %r");
default:
break;
case 0:
atexit(shutdown);
readkbd(vnc);
exits(nil);
}
}
pids[3] = p;
readmouse(vnc);
exits(nil);
}
static int
vncstart(Vnc *v, int shared)
{
vncwrchar(v, shared);
vncflush(v);
v->dim = vncrdpoint(v);
v->Pixfmt = vncrdpixfmt(v);
v->name = vncrdstring(v);
return 0;
}
|