#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);
}
|