#include #include #include #include #include "ksrv.h" #include #include "keycodes.h" int mainstacksize = 15*1024; int verbose = 0; int debug = 0; int doauth; char *addr; enum{ Rreclaim = 0xef80810a // rune to reclaim kbd (F1) }; static void usage(void) { fprint(2, "usage: kbdsrv [-A] [-d] [-v] [-s] address \n"); threadexits("usage"); } static Key * decode(char *msg) { Key *k; Rune r; k = malloc(sizeof(Key)); memset(k, 0, sizeof(Key)); memcpy(k->orig, msg, sizeof(int)); chartorune(&r,msg); k->rune = r; return(k); } static int authfd(int fd, char *role) { AuthInfo *i; i = nil; alarm(5*100); //BUG this just dies. USED(i); i = auth_proxy(fd, nil, "proto=p9any user=%s role=%s", getuser(), role); alarm(0); if(i == nil) return 0; auth_freeAI(i); return 1; } static int alarmed(void *v, char *s) { USED(v); if(strcmp(s, "alarm") == 0){ fprint(2, "timeout sending event\n"); return 1; } return 0; } Channel *senderc; static void sender(void *v) { Key *rkey; int res; USED(v); while(rkey = (Key *)recvp(senderc)){ alarm(5*1000); res = sendkey(rkey); if(!res){ fprint(2, "error sending movement %r\n"); alarm(5*1000); closedisplay(); //buggy, race condition, but last chance. alarm(0); alarm(5*1000); if(initdisplay() < 0) sysfatal("problem reopening display"); sendkey(rkey); } alarm(0); if(verbose) fprint(2, "key: [%C] 0x%x, keycode: 0x%x %d %d %d\n", rkey->rune, rkey->rune, rkey->keycode, rkey->isshift, rkey->iscontrol, rkey->isaltgr); free(rkey); } } static void attend(void *v) { int rd, dfd; char msg[50]; Key *rkey; dfd=(int)v; threadnotify(alarmed, 1); for(;;){ rd=read(dfd,msg,sizeof(msg)-1); if(rd<0){ if(verbose) fprint(2, "ksrv: error reading %r\n"); sysfatal("Error reading %r"); } if(rd==0){ if(verbose) fprint(2, "ksrv: closed connection\n"); break; } msg[rd] = '\0'; rkey=decode(msg); if(!rkey){ //on error, close connection fprint(2, "ksrv: error decoding, n=%d, %x, [%s]\n", rd, msg[0], msg); break; } if(!rkey->rune){ if(verbose) fprint(2, "0 rune received, closing\n"); break; } sendp(senderc, (void *)rkey); } close(dfd); if(verbose) print("Exiting\n"); threadexits(nil); } static void mainproc(void *v) { int lfd, dfd; char adir[40]; char ldir[40]; USED(v); if(initdisplay() < 0) sysfatal("ksrv: error initializing display"); if(announce(addr, adir)< 0) sysfatal("announce %s: %r", addr); for(;;){ lfd = listen(adir, ldir); if (lfd < 0) sysfatal("can't listen: %r"); dfd = accept(lfd, ldir); close(lfd); if(verbose) fprint(2, "ksrv: accepted connection\n"); if(doauth && !authfd(dfd, "server")){ fprint(2, "ksrv: auth failed"); close(dfd); } else proccreate(attend, (void *)dfd, mainstacksize); } closedisplay(); } extern int _threaddebuglevel; void threadmain(int argc, char **argv) { doauth = 1; addr=nil; ARGBEGIN{ default: usage(); case 'v': verbose++; break; case 'd': debug++; break; case 'A': doauth=0; break; case 's': close(0); addr = EARGF(usage()); break; }ARGEND if(!addr) addr=strdup("tcp!*!11001"); if(verbose) fprint(2, "ksrv: running\n"); if(verbose) fprint(2, "ksrv: forking\n"); senderc = chancreate(sizeof(Key *), 0); if(!senderc) sysfatal("creating chan"); proccreate(sender,nil,mainstacksize); proccreate(mainproc,nil,mainstacksize); if(verbose) fprint(2, "ksrv: exiting\n"); threadexits(nil); } //BUG: X dependant, should probably go in its own file void translate(Key *k) { int i; i = 0; while(ktab[i].r){ if(ktab[i].r == k->rune){ if(verbose) print("ksrv: translated\n"); k->keysym = ktab[i].keysym; k->isshift = ktab[i].isshift; k->iscontrol = ktab[i].iscontrol; xtranslate(k); return; } i++; } k->keysym = 0xFF&*(uint *)k->orig; //heuristical translation k->isshift = isupperrune(k->rune); xtranslate(k); return; }