diff --git a/sys/man/1/vnc b/sys/man/1/vnc index 41f7ffd2f..49cbe0eb5 100644 --- a/sys/man/1/vnc +++ b/sys/man/1/vnc @@ -51,6 +51,10 @@ vncs, vncv \- remote frame buffer server and viewer for Virtual Network Computin .I encodings ] [ +.B -l +.I charset +] +[ .B -k .I keypattern ] @@ -167,6 +171,12 @@ The default (and full) set is The encodings should be given as a single space-separated argument (quoted when using the shell). .TP +.B -l \fIcharset +sets the character set (see +.IR tcs (1)) +used by the server to encode clipboard text. The default is +.B utf-8. +.TP .B -k \fIkeypattern add .I keypattern diff --git a/sys/src/cmd/vnc/vncv.c b/sys/src/cmd/vnc/vncv.c index 3108bbae3..8d44813c9 100644 --- a/sys/src/cmd/vnc/vncv.c +++ b/sys/src/cmd/vnc/vncv.c @@ -2,7 +2,8 @@ #include "vncv.h" #include -char* encodings = "copyrect hextile corre rre raw mousewarp"; +char* charset = "utf-8"; +char* encodings = "copyrect hextile corre rre raw mousewarp"; int bpp12; int shared; int verbose; @@ -10,6 +11,7 @@ Vnc* vnc; int mousefd; int tls; + static int vncstart(Vnc*, int); enum @@ -36,7 +38,7 @@ shutdown(void) pid = getpid(); for(i = 0; i < NProcs; i++) - if(pids[i] != pid) + if(pids[i] != 0 && pids[i] != pid) postnote(PNPROC, pids[i], killkin); } @@ -72,15 +74,15 @@ vnchungup(Vnc*) void usage(void) { - fprint(2, "usage: vncv [-e encodings] [-k keypattern] [-csv] host[:n]\n"); + fprint(2, "usage: vncv [-e encodings] [-k keypattern] [-l charset] [-csv] host[:n]\n"); exits("usage"); } void main(int argc, char **argv) { - int p, fd, dfd, cfd, shared; - char *keypattern, *addr; + int p, dfd, cfd, shared; + char *keypattern, *addr, *label; Point d; TLSconn conn; @@ -105,6 +107,9 @@ main(int argc, char **argv) case 'k': keypattern = EARGF(usage()); break; + case 'l': + charset = EARGF(usage()); + break; default: usage(); }ARGEND; @@ -132,7 +137,8 @@ main(int argc, char **argv) if(vncstart(vnc, shared) < 0) sysfatal("init failure: %r"); - if(initdraw(0, 0, "vncv") < 0) + label = smprint("vnc %s", serveraddr); + if(initdraw(0, 0, label) < 0) sysfatal("initdraw: %r"); display->locking = 1; unlockdisplay(display); @@ -173,22 +179,15 @@ main(int argc, char **argv) } 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); - } + switch(p = rfork(RFPROC|RFMEM)){ + case -1: + sysfatal("rfork: %r"); + default: + break; + case 0: + atexit(shutdown); + readkbd(vnc); + exits(nil); } pids[3] = p; diff --git a/sys/src/cmd/vnc/vncv.h b/sys/src/cmd/vnc/vncv.h index 7b213d0df..c4f9bcbe3 100644 --- a/sys/src/cmd/vnc/vncv.h +++ b/sys/src/cmd/vnc/vncv.h @@ -11,6 +11,7 @@ extern void readfromserver(Vnc*); extern uchar zero[]; /* vncv.c */ +extern char *charset; extern char *encodings; extern int bpp12; extern Vnc* vnc; diff --git a/sys/src/cmd/vnc/wsys.c b/sys/src/cmd/vnc/wsys.c index bc088782c..ea4be5f4b 100644 --- a/sys/src/cmd/vnc/wsys.c +++ b/sys/src/cmd/vnc/wsys.c @@ -169,6 +169,42 @@ readmouse(Vnc *v) } } +static int +tcs(int fd0, int fd1) +{ + int pfd[2]; + + if(strcmp(charset, "utf-8") == 0) + goto Dup; + if(pipe(pfd) < 0) + goto Dup; + switch(rfork(RFPROC|RFFDG|RFMEM)){ + case -1: + close(pfd[0]); + close(pfd[1]); + goto Dup; + case 0: + if(fd0 < 0){ + dup(pfd[0], 0); + dup(fd1, 1); + close(fd1); + } else { + dup(pfd[0], 1); + dup(fd0, 0); + close(fd0); + } + close(pfd[0]); + close(pfd[1]); + execl("/bin/tcs", "tcs", fd0 < 0 ? "-f" : "-t", charset, 0); + execl("/bin/cat", "cat", 0); + _exits(0); + } + close(pfd[0]); + return pfd[1]; +Dup: + return dup(fd0 < 0 ? fd1 : fd0, -1); +} + static int snarffd = -1; static ulong snarfvers; @@ -176,46 +212,56 @@ void writesnarf(Vnc *v, long n) { uchar buf[8192]; + int fd, sfd; long m; - Biobuf *b; - if((b = Bopen("/dev/snarf", OWRITE)) == nil){ + vnclock(v); + if((sfd = create("/dev/snarf", OWRITE, 0666)) < 0) + fd = -1; + else { + fd = tcs(-1, sfd); + close(sfd); + } + if(fd < 0){ + vncunlock(v); vncgobble(v, n); return; } - while(n > 0){ m = n; if(m > sizeof(buf)) m = sizeof(buf); vncrdbytes(v, buf, m); n -= m; - - Bwrite(b, buf, m); + write(fd, buf, m); } - Bterm(b); + close(fd); snarfvers++; + vncunlock(v); } char * getsnarf(int *sz) { char *snarf, *p; - int n, c; + int fd, n, c; *sz =0; n = 8192; p = snarf = malloc(n); seek(snarffd, 0, 0); - while ((c = read(snarffd, p, n)) > 0){ - p += c; - n -= c; - *sz += c; - if (n == 0){ - snarf = realloc(snarf, *sz + 8192); - n = 8192; + if((fd = tcs(snarffd, -1)) >= 0){ + while((c = read(fd, p, n)) > 0){ + p += c; + n -= c; + *sz += c; + if (n == 0){ + snarf = realloc(snarf, *sz + 8192); + n = 8192; + } } + close(fd); } return snarf; } @@ -236,24 +282,22 @@ checksnarf(Vnc *v) for(;;){ sleep(1000); - dir = dirstat("/dev/snarf"); - if(dir == nil) /* this happens under old drawterm */ - continue; - if(dir->qid.vers > snarfvers){ + vnclock(v); + dir = dirfstat(snarffd); + if(dir != nil && dir->qid.vers != snarfvers){ + snarfvers = dir->qid.vers; + snarf = getsnarf(&len); - vnclock(v); vncwrchar(v, MCCut); vncwrbytes(v, "pad", 3); vncwrlong(v, len); vncwrbytes(v, snarf, len); vncflush(v); - vncunlock(v); free(snarf); - - snarfvers = dir->qid.vers; } free(dir); + vncunlock(v); } }