#include <u.h>#include <libc.h>#include <ctype.h>#include <bio.h>#include <thread.h>#include <fcall.h>#include <auth.h>#include <draw.h>#include <mouse.h>#include <cursor.h>#include <9p.h>#include <b.h> /* Pending: * 1. Needs a rewrite, along the lines of mousefs.c * 2. Should not send runes in the clear. */ typedef struct Dev Dev; enum { Qdir = 0, Qcons, Qctl, Qmax, Ndevs = 64, Nevs = 32, Stack = 16 * 1024, Rreclaim = L'' // rune to reclaim kbd (F1)}; struct Dev { char name; // char to stampt events char* addr; // IP for the machine servicing this int gone; int con; // to peer. Channel*evs; // of char*; sent to peer.}; int mainstacksize = Stack; static char Ebad[] = "something bad happened";static char Eperm[] = "permission denied";static char Enotexist[] = "file not found";static char Eattach[] = "unknown specifier in attach";static char Ebadctl[] = "bad control request";static Lock devslock;static Dev* devs[Ndevs];static int ndevs;static int debug;static Channel* kbdc; // devs[i].evs: where to send our events.static char* addr;static char* vname; static char* usr;static char* localaddr;static int doauth = 1; #define dprint if(debug)fprint#define Dprint if(debug>1)fprint static intalarmed(void *, char *s){ if(strcmp(s, "alarm") == 0) return 1; return 0;} static char*csquery(char *addr){ static char buf[128]; char* p; char* e; int fd, n; if (!addr || !strcmp(addr, "local")) return estrdup9p(localaddr); fd = open("/net/cs", ORDWR); if(fd < 0){ fprint(2, "cannot open /net/cs: %r"); return nil; } addr = netmkaddr(addr, "tcp", "11001"); if(write(fd, addr, strlen(addr)) <= 0){ fprint(2, "translating %s: %r\n", addr); close(fd); return nil; } seek(fd, 0, 0); buf[0] = 0; n = read(fd, buf, sizeof(buf)-1); close(fd); if (n < 0){ fprint(2, "cannot read /net/cs: %r"); return nil; } buf[n] = 0; p = strchr(buf, ' '); if (!p) return nil; p++; e = strchr(p, '!'); if (e){ // If it's the std service (port kbd), take just // the machine name. // For kbdfs's started at ports other than kbd, // take all the address, including the port. if (!strncmp(e+1, "11001", 5)) *e = 0; else return p ? smprint("tcp!%s", p) : nil; } return p ? estrdup9p(p) : nil;} static intislocal(char* addr){ if (!addr || !strcmp(addr, "local")) return 1; if (!strcmp(addr, sysname()) || !strcmp(addr, localaddr)) return 1; return 0;} static int_setdest(char* addr){ int i; if (islocal(addr)){ i = 0; } else { for (i = 1; i < ndevs; i++) if (devs[i]->addr != nil && !strcmp(addr, devs[i]->addr)) break; if (i == ndevs) return 0; } kbdc = devs[i]->evs; // send our events to it. dprint(2, "kbdfs: setdest %s\n", addr); return 1;} static intsetdest(char* addr){ int r; lock(&devslock); r = _setdest(addr); unlock(&devslock); return r;} static voidsendproc(void* a){ Dev* dev; Rune r; char s[UTFmax]; dev = a; threadsetname("sendproc"); while(recv(dev->evs, &r)>= 0 && r && !dev->gone){ Dprint(2, "kbd sent: %C\n", r); runetochar(s, &r); if (write(dev->con, s, UTFmax) != UTFmax) break; } lock(&devslock); dprint(2, "kbdfs: %s sendproc exiting\n", dev->addr); free(dev->addr); dev->addr = nil; unlock(&devslock); r = 0; runetochar(s, &r); write(dev->con, s, UTFmax); close(dev->con); dev->con = -1; if (dev->evs == kbdc) setdest("local"); threadexits(nil);} static voidhangupdev(Dev* d){ Rune z; if (d == devs[0]) // local never goes return; d->gone = 1; z = 0; send(d->evs, &z);} static Dev*outgoing(void){ int i; lock(&devslock); for (i = 1; i < ndevs; i++) if (devs[i]->addr != nil && kbdc == devs[i]->evs){ unlock(&devslock); return devs[i]; } unlock(&devslock); return nil;} static intgone(char* addr){ int i; /* We skip devs[0]. Local is never gone */ lock(&devslock); for (i = 1; i < ndevs; i++) if (devs[i]->addr != nil && strstr(devs[i]->addr, addr)){ if (kbdc == devs[i]->evs){ dprint(2, "kbdfs: current gone\n"); _setdest("local"); } hangupdev(devs[i]); break; } unlock(&devslock); return i < ndevs;} static voidrecvproc(void* a){ char buf[UTFmax]; Rune r; Dev* d; int fd; int n; Dev* outd; d = a; threadsetname("recvproc"); fd = d->con; for(;;){ n = read(d->con, buf, UTFmax); if (n < 0 || d->gone){ dprint(2, "kbdfs: %s gone %d %d\n", d->addr, n, d->gone); break; } if (n == 0) continue; chartorune(&r, buf); if (!r){ if (d == devs[0]){ outd = outgoing(); setdest("local"); if (outd) hangupdev(outd); continue; } else { dprint(2, "kbdfs: %s end\n", d->addr); break; } } buf[n] = 0; Dprint(2, "kbd read: %C\n", r); if (d != devs[0]){ if (kbdc == d->evs){ // Got events from there. // cannot use d as the current output. gone(d->addr); } } if (kbdc != nil){ buf[1] = d->name; send(kbdc, &r); } else fprint(2, "kbdfs: no kbdc\n"); } dprint(2, "kbdfs: %s recvproc exiting\n", d->addr); if (d->evs == kbdc) setdest("local"); r = 0; if (d != devs[0]) send(d->evs, &r); d->con = -1; runetochar(buf, &r); write(fd, buf, UTFmax); close(fd); threadexits(nil); } static Dev*newdev(char* addr, int fd){ Dev* dev; int i; Rune r; if (0 && strchr(addr, '!')){ // that's ok with more than one kbdfs per machine. fprint(2, "kbdfs: newdev: bad address %s\n", addr); return nil; } if (islocal(addr)) addr = localaddr; dprint(2, "kbdfs: newdev %s\n", addr); lock(&devslock); dev = nil; for (i = 0; i < ndevs; i++){ if (devs[i]->addr == nil){ dev = devs[i]; while(nbrecv(devs[i]->evs, &r) > 0) ; break; } } if (dev == nil){ dev = emalloc9p(sizeof(Dev)); dev->evs = chancreate(sizeof(Rune), Nevs); assert(ndevs < Ndevs); devs[ndevs++] = dev; } dev->gone = 0; dev->addr = estrdup9p(addr); dev->con = fd; unlock(&devslock); return dev;} static voidfsattach(Req *r){ char *spec; spec = r->ifcall.aname; if(spec != nil && spec[0] != 0){ respond(r, Eattach); return; } r->ofcall.qid = (Qid){Qdir, 0, QTDIR}; r->fid->qid = r->ofcall.qid; respond(r, nil);} static voidfsopen(Req *r){ int p; r->ifcall.mode &= 3; if (r->fid->qid.type == QTAUTH || r->ifcall.mode == OREAD){ r->fid->omode = r->ifcall.mode; } else { p = r->fid->qid.path; switch(p){ case Qdir: respond(r, Eperm); return; case Qcons: case Qctl: r->fid->omode = r->ifcall.mode; break; default: respond(r, Ebad); return; } } respond(r, nil);} static intdirgen(int i, Dir *d, void*){ if(i > 1) return -1; memset(d, 0, sizeof *d); d->uid = estrdup9p("sys"); d->gid = estrdup9p("sys"); d->length = 0; switch(i){ case -1: d->qid.type = QTDIR; d->qid.path = Qdir; d->mode = 0555|DMDIR; d->name = estrdup9p("/"); break; case 0: d->mode = 0660; d->qid.path = Qcons; d->name = estrdup9p("cons"); break; case 1: d->mode = 0220; d->qid.path = Qctl; d->name = estrdup9p("kbdctl"); break; default: return -1; } return 0;} voidkreadproc(void* a){ static char locked = 0; Rune ev; Req* r; Channel* kreadreq = a; char s[UTFmax+1]; int n; threadsetname("kreadproc"); for(;;){ r = recvp(kreadreq); if (recv(devs[0]->evs, &ev) < 0){ fprint(2, "kbdfs: nil event?"); break; } n = runetochar(s, &ev); r->ofcall.count = n; if (r->ifcall.count < r->ofcall.count) r->ofcall.count = r->ifcall.count; memmove(r->ofcall.data, s, r->ofcall.count); Dprint(2, "fsread: %s\n", s); respond(r, nil); }} static voidfsread(Req *r){ static Channel* kreadreqc = nil; static char locked = 0; char m[200]; char* e; char* c; int p; int i; p = r->fid->qid.path; switch(p){ case Qdir: dirread9p(r, dirgen, nil); break; case Qcons: if (kreadreqc == nil){ kreadreqc = chancreate(sizeof(Req*), Nevs); proccreate(kreadproc, kreadreqc, Stack); } sendp(kreadreqc, r); return; case Qctl: e = m; lock(&devslock); for (i = 0; i < ndevs; i++) if (devs[i]->addr){ c = (kbdc == devs[i]->evs) ? "*" : ""; e = seprint(e, m+sizeof(m), "%s %s\n", devs[i]->addr, c); } unlock(&devslock); readstr(r, m); break; default: respond(r, Ebad); return; } respond(r, nil);} static intauthfd(int fd, char* role){ AuthInfo*i; i = nil; alarm(5*1000); USED(i); i = auth_proxy(fd, nil, "proto=p9any user=%s role=%s", usr, role); alarm(0); if (i == nil) return 0; auth_freeAI(i); return 1;}Lines 1–500 of 815. Load more
#include <u.h> #include <libc.h> #include <ctype.h> #include <bio.h> #include <thread.h> #include <fcall.h> #include <auth.h> #include <draw.h> #include <mouse.h> #include <cursor.h> #include <9p.h> #include <b.h> /* Pending: * 1. Needs a rewrite, along the lines of mousefs.c * 2. Should not send runes in the clear. */ typedef struct Dev Dev; enum { Qdir = 0, Qcons, Qctl, Qmax, Ndevs = 64, Nevs = 32, Stack = 16 * 1024, Rreclaim = L'' // rune to reclaim kbd (F1) }; struct Dev { char name; // char to stampt events char* addr; // IP for the machine servicing this int gone; int con; // to peer. Channel*evs; // of char*; sent to peer. }; int mainstacksize = Stack; static char Ebad[] = "something bad happened"; static char Eperm[] = "permission denied"; static char Enotexist[] = "file not found"; static char Eattach[] = "unknown specifier in attach"; static char Ebadctl[] = "bad control request"; static Lock devslock; static Dev* devs[Ndevs]; static int ndevs; static int debug; static Channel* kbdc; // devs[i].evs: where to send our events. static char* addr; static char* vname; static char* usr; static char* localaddr; static int doauth = 1; #define dprint if(debug)fprint #define Dprint if(debug>1)fprint static int alarmed(void *, char *s) { if(strcmp(s, "alarm") == 0) return 1; return 0; } static char* csquery(char *addr) { static char buf[128]; char* p; char* e; int fd, n; if (!addr || !strcmp(addr, "local")) return estrdup9p(localaddr); fd = open("/net/cs", ORDWR); if(fd < 0){ fprint(2, "cannot open /net/cs: %r"); return nil; } addr = netmkaddr(addr, "tcp", "11001"); if(write(fd, addr, strlen(addr)) <= 0){ fprint(2, "translating %s: %r\n", addr); close(fd); return nil; } seek(fd, 0, 0); buf[0] = 0; n = read(fd, buf, sizeof(buf)-1); close(fd); if (n < 0){ fprint(2, "cannot read /net/cs: %r"); return nil; } buf[n] = 0; p = strchr(buf, ' '); if (!p) return nil; p++; e = strchr(p, '!'); if (e){ // If it's the std service (port kbd), take just // the machine name. // For kbdfs's started at ports other than kbd, // take all the address, including the port. if (!strncmp(e+1, "11001", 5)) *e = 0; else return p ? smprint("tcp!%s", p) : nil; } return p ? estrdup9p(p) : nil; } static int islocal(char* addr) { if (!addr || !strcmp(addr, "local")) return 1; if (!strcmp(addr, sysname()) || !strcmp(addr, localaddr)) return 1; return 0; } static int _setdest(char* addr) { int i; if (islocal(addr)){ i = 0; } else { for (i = 1; i < ndevs; i++) if (devs[i]->addr != nil && !strcmp(addr, devs[i]->addr)) break; if (i == ndevs) return 0; } kbdc = devs[i]->evs; // send our events to it. dprint(2, "kbdfs: setdest %s\n", addr); return 1; } static int setdest(char* addr) { int r; lock(&devslock); r = _setdest(addr); unlock(&devslock); return r; } static void sendproc(void* a) { Dev* dev; Rune r; char s[UTFmax]; dev = a; threadsetname("sendproc"); while(recv(dev->evs, &r)>= 0 && r && !dev->gone){ Dprint(2, "kbd sent: %C\n", r); runetochar(s, &r); if (write(dev->con, s, UTFmax) != UTFmax) break; } lock(&devslock); dprint(2, "kbdfs: %s sendproc exiting\n", dev->addr); free(dev->addr); dev->addr = nil; unlock(&devslock); r = 0; runetochar(s, &r); write(dev->con, s, UTFmax); close(dev->con); dev->con = -1; if (dev->evs == kbdc) setdest("local"); threadexits(nil); } static void hangupdev(Dev* d) { Rune z; if (d == devs[0]) // local never goes return; d->gone = 1; z = 0; send(d->evs, &z); } static Dev* outgoing(void) { int i; lock(&devslock); for (i = 1; i < ndevs; i++) if (devs[i]->addr != nil && kbdc == devs[i]->evs){ unlock(&devslock); return devs[i]; } unlock(&devslock); return nil; } static int gone(char* addr) { int i; /* We skip devs[0]. Local is never gone */ lock(&devslock); for (i = 1; i < ndevs; i++) if (devs[i]->addr != nil && strstr(devs[i]->addr, addr)){ if (kbdc == devs[i]->evs){ dprint(2, "kbdfs: current gone\n"); _setdest("local"); } hangupdev(devs[i]); break; } unlock(&devslock); return i < ndevs; } static void recvproc(void* a) { char buf[UTFmax]; Rune r; Dev* d; int fd; int n; Dev* outd; d = a; threadsetname("recvproc"); fd = d->con; for(;;){ n = read(d->con, buf, UTFmax); if (n < 0 || d->gone){ dprint(2, "kbdfs: %s gone %d %d\n", d->addr, n, d->gone); break; } if (n == 0) continue; chartorune(&r, buf); if (!r){ if (d == devs[0]){ outd = outgoing(); setdest("local"); if (outd) hangupdev(outd); continue; } else { dprint(2, "kbdfs: %s end\n", d->addr); break; } } buf[n] = 0; Dprint(2, "kbd read: %C\n", r); if (d != devs[0]){ if (kbdc == d->evs){ // Got events from there. // cannot use d as the current output. gone(d->addr); } } if (kbdc != nil){ buf[1] = d->name; send(kbdc, &r); } else fprint(2, "kbdfs: no kbdc\n"); } dprint(2, "kbdfs: %s recvproc exiting\n", d->addr); if (d->evs == kbdc) setdest("local"); r = 0; if (d != devs[0]) send(d->evs, &r); d->con = -1; runetochar(buf, &r); write(fd, buf, UTFmax); close(fd); threadexits(nil); } static Dev* newdev(char* addr, int fd) { Dev* dev; int i; Rune r; if (0 && strchr(addr, '!')){ // that's ok with more than one kbdfs per machine. fprint(2, "kbdfs: newdev: bad address %s\n", addr); return nil; } if (islocal(addr)) addr = localaddr; dprint(2, "kbdfs: newdev %s\n", addr); lock(&devslock); dev = nil; for (i = 0; i < ndevs; i++){ if (devs[i]->addr == nil){ dev = devs[i]; while(nbrecv(devs[i]->evs, &r) > 0) ; break; } } if (dev == nil){ dev = emalloc9p(sizeof(Dev)); dev->evs = chancreate(sizeof(Rune), Nevs); assert(ndevs < Ndevs); devs[ndevs++] = dev; } dev->gone = 0; dev->addr = estrdup9p(addr); dev->con = fd; unlock(&devslock); return dev; } static void fsattach(Req *r) { char *spec; spec = r->ifcall.aname; if(spec != nil && spec[0] != 0){ respond(r, Eattach); return; } r->ofcall.qid = (Qid){Qdir, 0, QTDIR}; r->fid->qid = r->ofcall.qid; respond(r, nil); } static void fsopen(Req *r) { int p; r->ifcall.mode &= 3; if (r->fid->qid.type == QTAUTH || r->ifcall.mode == OREAD){ r->fid->omode = r->ifcall.mode; } else { p = r->fid->qid.path; switch(p){ case Qdir: respond(r, Eperm); return; case Qcons: case Qctl: r->fid->omode = r->ifcall.mode; break; default: respond(r, Ebad); return; } } respond(r, nil); } static int dirgen(int i, Dir *d, void*) { if(i > 1) return -1; memset(d, 0, sizeof *d); d->uid = estrdup9p("sys"); d->gid = estrdup9p("sys"); d->length = 0; switch(i){ case -1: d->qid.type = QTDIR; d->qid.path = Qdir; d->mode = 0555|DMDIR; d->name = estrdup9p("/"); break; case 0: d->mode = 0660; d->qid.path = Qcons; d->name = estrdup9p("cons"); break; case 1: d->mode = 0220; d->qid.path = Qctl; d->name = estrdup9p("kbdctl"); break; default: return -1; } return 0; } void kreadproc(void* a) { static char locked = 0; Rune ev; Req* r; Channel* kreadreq = a; char s[UTFmax+1]; int n; threadsetname("kreadproc"); for(;;){ r = recvp(kreadreq); if (recv(devs[0]->evs, &ev) < 0){ fprint(2, "kbdfs: nil event?"); break; } n = runetochar(s, &ev); r->ofcall.count = n; if (r->ifcall.count < r->ofcall.count) r->ofcall.count = r->ifcall.count; memmove(r->ofcall.data, s, r->ofcall.count); Dprint(2, "fsread: %s\n", s); respond(r, nil); } } static void fsread(Req *r) { static Channel* kreadreqc = nil; static char locked = 0; char m[200]; char* e; char* c; int p; int i; p = r->fid->qid.path; switch(p){ case Qdir: dirread9p(r, dirgen, nil); break; case Qcons: if (kreadreqc == nil){ kreadreqc = chancreate(sizeof(Req*), Nevs); proccreate(kreadproc, kreadreqc, Stack); } sendp(kreadreqc, r); return; case Qctl: e = m; lock(&devslock); for (i = 0; i < ndevs; i++) if (devs[i]->addr){ c = (kbdc == devs[i]->evs) ? "*" : ""; e = seprint(e, m+sizeof(m), "%s %s\n", devs[i]->addr, c); } unlock(&devslock); readstr(r, m); break; default: respond(r, Ebad); return; } respond(r, nil); } static int authfd(int fd, char* role) { AuthInfo*i; i = nil; alarm(5*1000); USED(i); i = auth_proxy(fd, nil, "proto=p9any user=%s role=%s", usr, role); alarm(0); if (i == nil) return 0; auth_freeAI(i); return 1; }