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