ref: baf602582a840a0253900d41a2f1cce7156dd770
dir: /rd.c/
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <draw.h>
#include "dat.h"
#include "fns.h"
Rdp rd = {
.fd = -1,
.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 [-0A] [-T title] [-a depth] [-c wdir] [-d dom] [-k keyspec] [-n term] [-s shell] [net!]server[!port]\n");
exits("usage");
}
long
writen(int fd, void* buf, long nbytes)
{
long n, sofar;
sofar = 0;
while(sofar < nbytes){
n = write(fd, buf, nbytes-sofar);
if(n <= 0)
break;
sofar += n;
}
return sofar;
}
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;
}
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, 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 'a':
rd.depth = atol(EARGF(usage()));
switch(rd.depth){
case 8:
rd.chan = CMAP8;
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.wantconsole = 1;
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);
rd.fd = fd;
if(x224connect(fd) < 0)
sysfatal("initial handshake failed: %r");
if(initdraw(drawerror, nil, rd.label) < 0)
sysfatal("initdraw: %r");
display->locking = 1;
unlockdisplay(display);
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());
initsnarf();
atexitkill(startsnarfproc());
readnet(rd.fd);
x224disconnect(rd.fd);
close(rd.fd);
lockdisplay(display);
closedisplay(display);
if(!rd.active)
exits(nil);
if(rd.hupreason)
sysfatal("hangup: %d", rd.hupreason);
sysfatal("hangup");
}
void*
emalloc(ulong n)
{
void *b;
b = mallocz(n, 1);
if(b == nil)
sysfatal("out of memory allocating %lud: %r", n);
setmalloctag(b, getcallerpc(&n));
return b;
}
void*
erealloc(void *a, ulong n)
{
void *b;
b = realloc(a, n);
if(b == nil)
sysfatal("out of memory re-allocating %lud: %r", n);
setrealloctag(b, getcallerpc(&a));
return b;
}
char*
estrdup(const char *s)
{
char *b;
b = strdup(s);
if(b == nil)
sysfatal("strdup: %r");
setmalloctag(b, getcallerpc(&s));
return b;
}