#include "vnc.h" #include "vncv.h" #include char* charset = "utf-8"; char* encodings = "copyrect hextile corre rre raw mousewarp desktopsize xdesktopsize"; 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] != 0 && pids[i] != pid) postnote(PNPROC, pids[i], killkin); } char* netmkvncaddr(char *server) { char *p, portstr[NETPATHLEN]; int port; port = 5900; if(tls) port = 35729; if((p = strchr(server, ']')) == nil) p = server; if((p = strchr(p, ':')) != nil) { *p++ = '\0'; port += atoi(p); } snprint(portstr, sizeof portstr, "%d", port); return netmkaddr(server, "tcp", portstr); } void vnchungup(Vnc*) { sysfatal("connection closed"); } void usage(void) { fprint(2, "usage: vncv [-e encodings] [-k keypattern] [-l charset] [-csv] host[:n]\n"); exits("usage"); } void main(int argc, char **argv) { int p, dfd, cfd, shared; char *keypattern, *label; 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; case 'l': charset = EARGF(usage()); break; default: usage(); }ARGEND; if(argc != 1) usage(); serveraddr = strdup(argv[0]); dfd = dial(netmkvncaddr(serveraddr), nil, nil, &cfd); if(dfd < 0) sysfatal("cannot dial %s: %r", serveraddr); if(tls){ TLSconn conn; memset(&conn, 0, sizeof(conn)); if((dfd = tlsClient(dfd, &conn)) < 0) sysfatal("tlsClient: %r"); /* XXX check thumbprint */ free(conn.cert); free(conn.sessionID); } 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"); label = smprint("vnc %s", argv[0]); if(initdraw(0, 0, label) < 0) sysfatal("initdraw: %r"); free(label); display->locking = 1; unlockdisplay(display); 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; 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 = Rpt(ZP, vncrdpoint(v)); v->Pixfmt = vncrdpixfmt(v); v->name = vncrdstring(v); return 0; }