#include #include #include #include #include "dat.h" #include "fns.h" Rdp rd = { .fd = -1, .opt = OVersion5 | OEncrypt | OSnarf, .chan = RGB16, .depth = 16, .dim = {800, 600}, .windom = "", .passwd = "", .shell = "", .rwd = "", }; char Eshort[]= "short data"; char Esmall[]= "buffer too small"; char Ebignum[]= "number too big"; static void usage(void) { fprint(2, "usage: rd [-04Ae] [-T title] [-a depth] [-c wdir] [-d dom] [-k keyspec] [-n clname] [-s shell] [net!]server[!port]\n"); exits("usage"); } static int startmouseproc(void) { int mpid; switch(mpid = rfork(RFPROC|RFMEM)){ case -1: sysfatal("rfork: %r"); case 0: break; default: return mpid; } atexit(atexitkiller); readdevmouse(); exits("mouse eof"); return 0; } static int startkbdproc(void) { int pid; switch(pid = rfork(RFPROC|RFMEM)){ case -1: sysfatal("rfork: %r"); case 0: break; default: return pid; } atexit(atexitkiller); readkbd(); exits("kbd eof"); return 0; } static int startsnarfproc(void) { int pid; switch(pid = rfork(RFPROC|RFMEM)){ case -1: sysfatal("rfork: %r"); case 0: break; default: return pid; } atexit(atexitkiller); pollsnarf(); exits("snarf eof"); return 0; } void main(int argc, char *argv[]) { int doauth, fd; char *server, *addr, *keyspec; UserPasswd *creds; rd.local = getenv("sysname"); rd.user = getenv("user"); keyspec = ""; doauth = 1; ARGBEGIN { case 'A': doauth = 0; break; case 'k': keyspec = EARGF(usage()); break; case 'T': rd.label = strdup(EARGF(usage())); break; case 'd': rd.windom = strdup(EARGF(usage())); break; case 's': rd.shell = strdup(EARGF(usage())); break; case 'c': rd.rwd = strdup(EARGF(usage())); break; case 'n': rd.local = estrdup(EARGF(usage())); break; case 'e': rd.opt &= ~OEncrypt; break; case 'a': rd.depth = atol(EARGF(usage())); switch(rd.depth){ case 8: rd.chan = CMAP8; /* broken */ break; case 15: rd.chan = RGB15; break; case 16: rd.chan = RGB16; break; case 24: rd.chan = RGB24; break; case 32: rd.chan = XRGB32; break; default: sysfatal("bad color depth"); } break; case '0': rd.opt |= OConsole; break; case '4': rd.opt &= ~(OVersion5|OSnarf); break; case 'x': case 'z': case 'P': case 'E': case 'm': case 'C': case 'K': case 'f': case 'B': case '5': break; default: usage(); } ARGEND if (argc != 1) usage(); server = argv[0]; if(rd.local == nil) sysfatal("set $sysname or use -n\n"); if(rd.user == nil) sysfatal("set $user"); if (rd.label == nil) rd.label = smprint("rd %s", server); if(doauth){ creds = auth_getuserpasswd(auth_getkey, "proto=pass service=rdp %s", keyspec); if(creds == nil) fprint(2, "factotum: %r\n"); else { rd.user = creds->user; rd.passwd = creds->passwd; rd.autologon = 1; } } addr = netmkaddr(server, "tcp", "3389"); fd = dial(addr, nil, nil, nil); if(fd < 0) sysfatal("dial %s: %r", addr); if(initdraw(drawerror, nil, rd.label) < 0) sysfatal("initdraw: %r"); display->locking = 1; unlockdisplay(display); rd.fd = fd; rd.dim.y = Dy(screen->r); rd.dim.x = Dx(screen->r); rd.dim.x = (rd.dim.x + 3) & ~3; /* ensure width divides by 4 */ if(rdphandshake(fd) < 0) sysfatal("handshake failed: %r"); atexit(atexitkiller); atexitkill(getpid()); atexitkill(startmouseproc()); atexitkill(startkbdproc()); if(rd.opt&OSnarf){ initsnarf(); atexitkill(startsnarfproc()); } readnet(fd); x224disconnect(fd); close(fd); lockdisplay(display); closedisplay(display); if(!rd.active) exits(nil); if(rd.hupreason) sysfatal("hangup: %d", rd.hupreason); sysfatal("hangup"); }