19a747e4fSDavid du Colombier #include "vnc.h"
29a747e4fSDavid du Colombier #include "vncv.h"
3f8e525acSDavid du Colombier #include <libsec.h>
49a747e4fSDavid du Colombier
59a747e4fSDavid du Colombier char* encodings = "copyrect hextile corre rre raw mousewarp";
69a747e4fSDavid du Colombier int bpp12;
79a747e4fSDavid du Colombier int shared;
89a747e4fSDavid du Colombier int verbose;
99a747e4fSDavid du Colombier Vnc* vnc;
109a747e4fSDavid du Colombier int mousefd;
11f8e525acSDavid du Colombier int tls;
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier static int vncstart(Vnc*, int);
14f8e525acSDavid du Colombier
159a747e4fSDavid du Colombier enum
169a747e4fSDavid du Colombier {
179a747e4fSDavid du Colombier NProcs = 4
189a747e4fSDavid du Colombier };
199a747e4fSDavid du Colombier
209a747e4fSDavid du Colombier static int pids[NProcs];
219a747e4fSDavid du Colombier static char killkin[] = "die vnc kin";
229a747e4fSDavid du Colombier
239a747e4fSDavid du Colombier /*
249a747e4fSDavid du Colombier * called by any proc when exiting to tear everything down.
259a747e4fSDavid du Colombier */
269a747e4fSDavid du Colombier static void
shutdown(void)279a747e4fSDavid du Colombier shutdown(void)
289a747e4fSDavid du Colombier {
299a747e4fSDavid du Colombier int i, pid;
309a747e4fSDavid du Colombier
319a747e4fSDavid du Colombier hangup(vnc->ctlfd);
329a747e4fSDavid du Colombier close(vnc->ctlfd);
339a747e4fSDavid du Colombier vnc->ctlfd = -1;
349a747e4fSDavid du Colombier close(vnc->datafd);
359a747e4fSDavid du Colombier vnc->datafd = -1;
369a747e4fSDavid du Colombier
379a747e4fSDavid du Colombier pid = getpid();
389a747e4fSDavid du Colombier for(i = 0; i < NProcs; i++)
399a747e4fSDavid du Colombier if(pids[i] != pid)
409a747e4fSDavid du Colombier postnote(PNPROC, pids[i], killkin);
419a747e4fSDavid du Colombier }
429a747e4fSDavid du Colombier
439a747e4fSDavid du Colombier char*
netmkvncaddr(char * inserver)449a747e4fSDavid du Colombier netmkvncaddr(char *inserver)
459a747e4fSDavid du Colombier {
469a747e4fSDavid du Colombier char *p, portstr[NETPATHLEN], *server;
479a747e4fSDavid du Colombier int port;
489a747e4fSDavid du Colombier
499a747e4fSDavid du Colombier server = strdup(inserver);
509a747e4fSDavid du Colombier assert(server != nil);
519a747e4fSDavid du Colombier
529a747e4fSDavid du Colombier port = 5900;
53f8e525acSDavid du Colombier if(tls)
54f8e525acSDavid du Colombier port = 35729;
559a747e4fSDavid du Colombier if(p = strchr(server, ':')) {
569a747e4fSDavid du Colombier *p++ = '\0';
579a747e4fSDavid du Colombier port += atoi(p);
589a747e4fSDavid du Colombier }
599a747e4fSDavid du Colombier
609a747e4fSDavid du Colombier snprint(portstr, sizeof portstr, "%d", port);
61b7b24591SDavid du Colombier p = netmkaddr(server, "tcp", portstr);
629a747e4fSDavid du Colombier free(server);
639a747e4fSDavid du Colombier return p;
649a747e4fSDavid du Colombier }
659a747e4fSDavid du Colombier
669a747e4fSDavid du Colombier void
vnchungup(Vnc *)679a747e4fSDavid du Colombier vnchungup(Vnc*)
689a747e4fSDavid du Colombier {
699a747e4fSDavid du Colombier sysfatal("connection closed");
709a747e4fSDavid du Colombier }
719a747e4fSDavid du Colombier
729a747e4fSDavid du Colombier void
usage(void)739a747e4fSDavid du Colombier usage(void)
749a747e4fSDavid du Colombier {
75*5e492409SDavid du Colombier fprint(2, "usage: vncv [-e encodings] [-k keypattern] [-csv] host[:n]\n");
769a747e4fSDavid du Colombier exits("usage");
779a747e4fSDavid du Colombier }
789a747e4fSDavid du Colombier
799a747e4fSDavid du Colombier void
main(int argc,char ** argv)809a747e4fSDavid du Colombier main(int argc, char **argv)
819a747e4fSDavid du Colombier {
82ebe1d0a8SDavid du Colombier int p, fd, dfd, cfd, shared;
83*5e492409SDavid du Colombier char *keypattern, *addr;
849a747e4fSDavid du Colombier Point d;
85f8e525acSDavid du Colombier TLSconn conn;
869a747e4fSDavid du Colombier
87*5e492409SDavid du Colombier keypattern = nil;
889a747e4fSDavid du Colombier shared = 0;
899a747e4fSDavid du Colombier ARGBEGIN{
909a747e4fSDavid du Colombier case 'c':
919a747e4fSDavid du Colombier bpp12 = 1;
929a747e4fSDavid du Colombier break;
939a747e4fSDavid du Colombier case 'e':
94*5e492409SDavid du Colombier encodings = EARGF(usage());
959a747e4fSDavid du Colombier break;
969a747e4fSDavid du Colombier case 's':
979a747e4fSDavid du Colombier shared = 1;
989a747e4fSDavid du Colombier break;
99f8e525acSDavid du Colombier case 't':
100f8e525acSDavid du Colombier tls = 1;
101f8e525acSDavid du Colombier break;
1029a747e4fSDavid du Colombier case 'v':
1039a747e4fSDavid du Colombier verbose = 1;
1049a747e4fSDavid du Colombier break;
105*5e492409SDavid du Colombier case 'k':
106*5e492409SDavid du Colombier keypattern = EARGF(usage());
107*5e492409SDavid du Colombier break;
1089a747e4fSDavid du Colombier default:
1099a747e4fSDavid du Colombier usage();
1109a747e4fSDavid du Colombier }ARGEND;
1119a747e4fSDavid du Colombier
1129a747e4fSDavid du Colombier if(argc != 1)
1139a747e4fSDavid du Colombier usage();
1149a747e4fSDavid du Colombier
1159a747e4fSDavid du Colombier addr = netmkvncaddr(argv[0]);
116b7b24591SDavid du Colombier serveraddr = argv[0];
1179a747e4fSDavid du Colombier dfd = dial(addr, nil, nil, &cfd);
1189a747e4fSDavid du Colombier if(dfd < 0)
1199a747e4fSDavid du Colombier sysfatal("cannot dial %s: %r", addr);
120f8e525acSDavid du Colombier if(tls){
121f8e525acSDavid du Colombier dfd = tlsClient(dfd, &conn);
122f8e525acSDavid du Colombier if(dfd < 0)
123f8e525acSDavid du Colombier sysfatal("tlsClient: %r");
124f8e525acSDavid du Colombier /* XXX check thumbprint */
125f8e525acSDavid du Colombier }
1269a747e4fSDavid du Colombier vnc = vncinit(dfd, cfd, nil);
1279a747e4fSDavid du Colombier
1289a747e4fSDavid du Colombier if(vnchandshake(vnc) < 0)
1299a747e4fSDavid du Colombier sysfatal("handshake failure: %r");
130*5e492409SDavid du Colombier if(vncauth(vnc, keypattern) < 0)
1319a747e4fSDavid du Colombier sysfatal("authentication failure: %r");
1329a747e4fSDavid du Colombier if(vncstart(vnc, shared) < 0)
1339a747e4fSDavid du Colombier sysfatal("init failure: %r");
1349a747e4fSDavid du Colombier
1359a747e4fSDavid du Colombier initdraw(0, 0, "vncv");
1369a747e4fSDavid du Colombier display->locking = 1;
1379a747e4fSDavid du Colombier unlockdisplay(display);
1389a747e4fSDavid du Colombier
1399a747e4fSDavid du Colombier d = addpt(vnc->dim, Pt(2*Borderwidth, 2*Borderwidth));
1409a747e4fSDavid du Colombier if(verbose)
1419a747e4fSDavid du Colombier fprint(2, "screen size %P, desktop size %P\n", display->image->r.max, d);
1429a747e4fSDavid du Colombier
1439a747e4fSDavid du Colombier choosecolor(vnc);
1449a747e4fSDavid du Colombier sendencodings(vnc);
1459a747e4fSDavid du Colombier initmouse();
1469a747e4fSDavid du Colombier
1479a747e4fSDavid du Colombier rfork(RFREND);
1489a747e4fSDavid du Colombier atexit(shutdown);
1499a747e4fSDavid du Colombier pids[0] = getpid();
1509a747e4fSDavid du Colombier
1519a747e4fSDavid du Colombier switch(p = rfork(RFPROC|RFMEM)){
1529a747e4fSDavid du Colombier case -1:
1539a747e4fSDavid du Colombier sysfatal("rfork: %r");
1549a747e4fSDavid du Colombier default:
1559a747e4fSDavid du Colombier break;
1569a747e4fSDavid du Colombier case 0:
1579a747e4fSDavid du Colombier atexit(shutdown);
1589a747e4fSDavid du Colombier readfromserver(vnc);
1599a747e4fSDavid du Colombier exits(nil);
1609a747e4fSDavid du Colombier }
1619a747e4fSDavid du Colombier pids[1] = p;
1629a747e4fSDavid du Colombier
1639a747e4fSDavid du Colombier switch(p = rfork(RFPROC|RFMEM)){
1649a747e4fSDavid du Colombier case -1:
1659a747e4fSDavid du Colombier sysfatal("rfork: %r");
1669a747e4fSDavid du Colombier default:
1679a747e4fSDavid du Colombier break;
1689a747e4fSDavid du Colombier case 0:
1699a747e4fSDavid du Colombier atexit(shutdown);
1709a747e4fSDavid du Colombier checksnarf(vnc);
1719a747e4fSDavid du Colombier exits(nil);
1729a747e4fSDavid du Colombier }
1739a747e4fSDavid du Colombier pids[2] = p;
1749a747e4fSDavid du Colombier
175ebe1d0a8SDavid du Colombier fd = open("/dev/label", OWRITE);
176ebe1d0a8SDavid du Colombier if(fd >= 0){
177ebe1d0a8SDavid du Colombier fprint(fd, "vnc %s", serveraddr);
178ebe1d0a8SDavid du Colombier close(fd);
179ebe1d0a8SDavid du Colombier }
180f8e525acSDavid du Colombier if(access("/dev/snarf", AEXIST) >= 0){
1819a747e4fSDavid du Colombier switch(p = rfork(RFPROC|RFMEM)){
1829a747e4fSDavid du Colombier case -1:
1839a747e4fSDavid du Colombier sysfatal("rfork: %r");
1849a747e4fSDavid du Colombier default:
1859a747e4fSDavid du Colombier break;
1869a747e4fSDavid du Colombier case 0:
1879a747e4fSDavid du Colombier atexit(shutdown);
1889a747e4fSDavid du Colombier readkbd(vnc);
1899a747e4fSDavid du Colombier exits(nil);
1909a747e4fSDavid du Colombier }
1919a747e4fSDavid du Colombier }
1929a747e4fSDavid du Colombier pids[3] = p;
1939a747e4fSDavid du Colombier
1949a747e4fSDavid du Colombier readmouse(vnc);
1959a747e4fSDavid du Colombier exits(nil);
1969a747e4fSDavid du Colombier }
1979a747e4fSDavid du Colombier
1989a747e4fSDavid du Colombier static int
vncstart(Vnc * v,int shared)1999a747e4fSDavid du Colombier vncstart(Vnc *v, int shared)
2009a747e4fSDavid du Colombier {
2019a747e4fSDavid du Colombier vncwrchar(v, shared);
2029a747e4fSDavid du Colombier vncflush(v);
2039a747e4fSDavid du Colombier v->dim = vncrdpoint(v);
2049a747e4fSDavid du Colombier v->Pixfmt = vncrdpixfmt(v);
2059a747e4fSDavid du Colombier v->name = vncrdstring(v);
2069a747e4fSDavid du Colombier return 0;
2079a747e4fSDavid du Colombier }
208