ref: c0bcff65ed63e42976a699e01a63eecb7682fe1c
dir: /rd.c/
#include <u.h> #include <libc.h> #include <auth.h> #include <draw.h> #include <mouse.h> #include "dat.h" #include "fns.h" Rdp conn = { .depth = 16, .windom = "", .passwd = "", .shell = "", .rwd = "", }; char Eshort[]= "short data"; char Esmall[]= "buffer too small"; char Ebignum[]= "number too big"; void sendmouse(Rdp* c, Mouse m); static void usage(void) { fprint(2, "usage: rd [-0A] [-T title] [-a depth] [-c wdir] [-d dom] [-k keyspec] [-n term] [-s shell] [net!]server[!port]\n"); exits("usage"); } static int startmouseproc(Rdp* c) { int mpid; switch(mpid = rfork(RFPROC|RFMEM)){ case -1: sysfatal("rfork: %r"); case 0: break; default: return mpid; } atexit(atexitkiller); readdevmouse(c); exits("mouse eof"); return 0; } static int startkbdproc(Rdp* c) { int pid; switch(pid = rfork(RFPROC|RFMEM)){ case -1: sysfatal("rfork: %r"); case 0: break; default: return pid; } atexit(atexitkiller); readkbd(c); exits("kbd eof"); return 0; } static int startsnarfproc(Rdp* c) { int pid; switch(pid = rfork(RFPROC|RFMEM)){ case -1: sysfatal("rfork: %r"); case 0: break; default: return pid; } atexit(atexitkiller); initsnarf(); pollsnarf(c); exits("snarf eof"); return 0; } static int killpid[32]; static int nkillpid; void atexitkiller(void) { int i, pid; pid = getpid(); for(i=0; i<nkillpid; i++) if(pid != killpid[i]) postnote(PNPROC, killpid[i], "kill"); } void atexitkill(int pid) { killpid[nkillpid++] = pid; } void main(int argc, char *argv[]) { int doauth; char *server, *addr, *keyspec; UserPasswd *creds; Rdp* c; c = &conn; keyspec = ""; doauth = 1; ARGBEGIN{ case 'A': doauth = 0; break; case 'k': keyspec = EARGF(usage()); break; case 'T': c->label = strdup(EARGF(usage())); break; case 'd': c->windom = strdup(EARGF(usage())); break; case 's': c->shell = strdup(EARGF(usage())); break; case 'c': c->rwd = strdup(EARGF(usage())); break; case 'a': c->depth = atol(EARGF(usage())); break; case '0': c->wantconsole = 1; break; default: usage(); }ARGEND if (argc != 1) usage(); server = argv[0]; c->local = getenv("sysname"); c->user = getenv("user"); if(c->local == nil) sysfatal("set $sysname\n"); if(c->user == nil) sysfatal("set $user"); if(doauth){ creds = auth_getuserpasswd(auth_getkey, "proto=pass service=rdp %s", keyspec); if(creds == nil) fprint(2, "factotum: %r\n"); else { c->user = creds->user; c->passwd = creds->passwd; } }else c->user = ""; if(c->label == nil) c->label = smprint("rd %s", server); initvc(c); addr = netmkaddr(server, "tcp", "3389"); c->fd = dial(addr, nil, nil, nil); if(c->fd < 0) sysfatal("dial %s: %r", addr); if(x224handshake(c) < 0) sysfatal("X.224 handshake: %r"); initscreen(c); if(rdphandshake(c) < 0) sysfatal("handshake: %r"); atexit(atexitkiller); atexitkill(getpid()); atexitkill(startmouseproc(c)); atexitkill(startkbdproc(c)); atexitkill(startsnarfproc(c)); readnet(c); x224hangup(c); if(!c->active) exits(nil); if(c->hupreason) sysfatal("disconnect reason code %d", c->hupreason); sysfatal("hangup"); } void readnet(Rdp* c) { Msg r; for(;;){ if(readmsg(c, &r) <= 0) break; apply(c, &r); } } void readkbd(Rdp* c) { char buf[256], k[10]; int ctlfd, fd, kr, kn, w; Rune r; if((fd = open("/dev/cons", OREAD)) < 0) sysfatal("open %s: %r", buf); if((ctlfd = open("/dev/consctl", OWRITE)) < 0) sysfatal("open %s: %r", buf); write(ctlfd, "rawon", 5); kn = 0; for(;;){ while(!fullrune(k, kn)){ kr = read(fd, k+kn, sizeof k - kn); if(kr <= 0) sysfatal("bad read from kbd"); kn += kr; } w = chartorune(&r, k); kn -= w; memmove(k, &k[w], kn); sendkbd(c, r); } } static int mfd = -1; void readdevmouse(Rdp* c) { Mouse m; char ev[1+4*12]; if((mfd = open("/dev/mouse", ORDWR)) < 0) sysfatal("open /dev/mouse: %r"); for(;;){ if(read(mfd, ev, sizeof ev) != sizeof ev) sysfatal("mouse eof"); if(*ev == 'm'){ m.xy.x = atoi(ev+1+0*12); m.xy.y = atoi(ev+1+1*12); m.buttons = atoi(ev+1+2*12) & 0x1F; m.msec = atoi(ev+1+3*12); sendmouse(c, m); }else eresized(c, 1); } } void warpmouse(int x, int y) { if(mfd < 0) return; fprint(mfd, "m%d %d", x, y); }