xref: /plan9/sys/src/cmd/vnc/vncv.c (revision 5e4924093ecb86f7174bf23023955abc83fb6962)
1 #include "vnc.h"
2 #include "vncv.h"
3 #include <libsec.h>
4 
5 char*	encodings = "copyrect hextile corre rre raw mousewarp";
6 int		bpp12;
7 int		shared;
8 int		verbose;
9 Vnc*		vnc;
10 int		mousefd;
11 int		tls;
12 
13 static int	vncstart(Vnc*, int);
14 
15 enum
16 {
17 	NProcs	= 4
18 };
19 
20 static int pids[NProcs];
21 static char killkin[] = "die vnc kin";
22 
23 /*
24  * called by any proc when exiting to tear everything down.
25  */
26 static void
shutdown(void)27 shutdown(void)
28 {
29 	int i, pid;
30 
31 	hangup(vnc->ctlfd);
32 	close(vnc->ctlfd);
33 	vnc->ctlfd = -1;
34 	close(vnc->datafd);
35 	vnc->datafd = -1;
36 
37 	pid = getpid();
38 	for(i = 0; i < NProcs; i++)
39 		if(pids[i] != pid)
40 			postnote(PNPROC, pids[i], killkin);
41 }
42 
43 char*
netmkvncaddr(char * inserver)44 netmkvncaddr(char *inserver)
45 {
46 	char *p, portstr[NETPATHLEN], *server;
47 	int port;
48 
49 	server = strdup(inserver);
50 	assert(server != nil);
51 
52 	port = 5900;
53 	if(tls)
54 		port = 35729;
55 	if(p = strchr(server, ':')) {
56 		*p++ = '\0';
57 		port += atoi(p);
58 	}
59 
60 	snprint(portstr, sizeof portstr, "%d", port);
61 	p = netmkaddr(server, "tcp", portstr);
62 	free(server);
63 	return p;
64 }
65 
66 void
vnchungup(Vnc *)67 vnchungup(Vnc*)
68 {
69 	sysfatal("connection closed");
70 }
71 
72 void
usage(void)73 usage(void)
74 {
75 	fprint(2, "usage: vncv [-e encodings] [-k keypattern] [-csv] host[:n]\n");
76 	exits("usage");
77 }
78 
79 void
main(int argc,char ** argv)80 main(int argc, char **argv)
81 {
82 	int p, fd, dfd, cfd, shared;
83 	char *keypattern, *addr;
84 	Point d;
85 	TLSconn conn;
86 
87 	keypattern = nil;
88 	shared = 0;
89 	ARGBEGIN{
90 	case 'c':
91 		bpp12 = 1;
92 		break;
93 	case 'e':
94 		encodings = EARGF(usage());
95 		break;
96 	case 's':
97 		shared = 1;
98 		break;
99 	case 't':
100 		tls = 1;
101 		break;
102 	case 'v':
103 		verbose = 1;
104 		break;
105 	case 'k':
106 		keypattern = EARGF(usage());
107 		break;
108 	default:
109 		usage();
110 	}ARGEND;
111 
112 	if(argc != 1)
113 		usage();
114 
115 	addr = netmkvncaddr(argv[0]);
116 	serveraddr = argv[0];
117 	dfd = dial(addr, nil, nil, &cfd);
118 	if(dfd < 0)
119 		sysfatal("cannot dial %s: %r", addr);
120 	if(tls){
121 		dfd = tlsClient(dfd, &conn);
122 		if(dfd < 0)
123 			sysfatal("tlsClient: %r");
124 		/* XXX check thumbprint */
125 	}
126 	vnc = vncinit(dfd, cfd, nil);
127 
128 	if(vnchandshake(vnc) < 0)
129 		sysfatal("handshake failure: %r");
130 	if(vncauth(vnc, keypattern) < 0)
131 		sysfatal("authentication failure: %r");
132 	if(vncstart(vnc, shared) < 0)
133 		sysfatal("init failure: %r");
134 
135 	initdraw(0, 0, "vncv");
136 	display->locking = 1;
137 	unlockdisplay(display);
138 
139 	d = addpt(vnc->dim, Pt(2*Borderwidth, 2*Borderwidth));
140 	if(verbose)
141 		fprint(2, "screen size %P, desktop size %P\n", display->image->r.max, d);
142 
143 	choosecolor(vnc);
144 	sendencodings(vnc);
145 	initmouse();
146 
147 	rfork(RFREND);
148 	atexit(shutdown);
149 	pids[0] = getpid();
150 
151 	switch(p = rfork(RFPROC|RFMEM)){
152 	case -1:
153 		sysfatal("rfork: %r");
154 	default:
155 		break;
156 	case 0:
157 		atexit(shutdown);
158 		readfromserver(vnc);
159 		exits(nil);
160 	}
161 	pids[1] = p;
162 
163 	switch(p = rfork(RFPROC|RFMEM)){
164 	case -1:
165 		sysfatal("rfork: %r");
166 	default:
167 		break;
168 	case 0:
169 		atexit(shutdown);
170 		checksnarf(vnc);
171 		exits(nil);
172 	}
173 	pids[2] = p;
174 
175 	fd = open("/dev/label", OWRITE);
176 	if(fd >= 0){
177 		fprint(fd, "vnc %s", serveraddr);
178 		close(fd);
179 	}
180 	if(access("/dev/snarf", AEXIST) >= 0){
181 		switch(p = rfork(RFPROC|RFMEM)){
182 		case -1:
183 			sysfatal("rfork: %r");
184 		default:
185 			break;
186 		case 0:
187 			atexit(shutdown);
188 			readkbd(vnc);
189 			exits(nil);
190 		}
191 	}
192 	pids[3] = p;
193 
194 	readmouse(vnc);
195 	exits(nil);
196 }
197 
198 static int
vncstart(Vnc * v,int shared)199 vncstart(Vnc *v, int shared)
200 {
201 	vncwrchar(v, shared);
202 	vncflush(v);
203 	v->dim = vncrdpoint(v);
204 	v->Pixfmt = vncrdpixfmt(v);
205 	v->name = vncrdstring(v);
206 	return 0;
207 }
208