#include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" #define STACK 8192 Rdp conn = { .fd = -1, .depth = 16, .windom = "", .passwd = "", .shell = "", .rwd = "", }; Mousectl *mousectl; Keyboardctl *keyboardctl; char Eshort[]= "short data"; char Esmall[]= "buffer too small"; char Ebignum[]= "number too big"; void sendmouse(Rdp* c, Mouse m); static void keyboardthread(void*); static void mousethread(void*); static void snarfthread(void*); 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"); threadexitsall("usage"); } void threadmain(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"); mousectl = initmouse(nil, screen); if(mousectl == nil){ fprint(2, "rd: can't initialize mouse: %r\n"); threadexitsall("mouse"); } keyboardctl = initkeyboard(nil); if(keyboardctl == nil){ fprint(2, "rd: can't initialize keyboard: %r\n"); threadexitsall("keyboard"); } proccreate(keyboardthread, c, STACK); proccreate(mousethread, c, STACK); proccreate(snarfthread, c, STACK); threadsetname("mainthread"); readnet(c); x224hangup(c); if(!c->active) threadexitsall(nil); if(c->hupreason) sysfatal("disconnect reason code %d", c->hupreason); sysfatal("hangup"); } static void keyboardthread(void* v) { Rune r; Rdp* c; c = v; threadsetname("keyboardthread"); for(;;){ recv(keyboardctl->c, &r); sendkbd(c, r); } } static void mousethread(void* v) { Rdp* c; enum { MResize, MMouse, NMALT }; static Alt alts[NMALT+1]; Mouse m; c = v; threadsetname("mousethread"); alts[MResize].c = mousectl->resizec; alts[MResize].v = nil; alts[MResize].op = CHANRCV; alts[MMouse].c = mousectl->c; alts[MMouse].v = &m; alts[MMouse].op = CHANRCV; for(;;){ switch(alt(alts)){ case MResize: eresized(c, 1); break; case MMouse: sendmouse(c, m); break; } } } void warpmouse(int x, int y) { moveto(mousectl, Pt(x, y)); } static void snarfthread(void* v) { Rdp* c; c = v; threadsetname("snarfthread"); initsnarf(); pollsnarf(c); threadexits("snarf eof"); } void readnet(Rdp* c) { Msg r; for(;;){ if(readmsg(c, &r) <= 0) break; apply(c, &r); } }