#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> typedef struct Dev Dev; enum { Qdir = 0, Qmouse, Qctl, Qmax, Ndevs = 64, Nevs = 128, Stack = 16 * 1024, Mevlen = 1+12*4, // see mouse(3). Stdxmax = 1280, Stdymax = 1024, }; struct Dev { char name; // char to stampt events char addr[50]; // IP for the machine servicing this int con; // to/from peer. int cfd; // ctl fd for con (for hanging up) Channel*evs; // of char*; got from peer Channel*out; // of char*; sent to peer int sender; // true if senderproc alive int receiver; // true if receiverproc alive}; static int newpeer(char* addr); 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[2];static int debug; static int outm; // output devicestatic int inm; // input device static char* kbdctl = "/dev/kbdctl";static char* localaddr;static int doauth = 1;static char* vname;static char* addr;static Ref readers;static int mousefd = -1; #define dprint if(debug)fprint#define Dprint if(debug>1)fprint static int xmin, xmax, ymin, ymax; static Cursor whitearrow = { {0, 0}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }, {0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C, 0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C, 0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }}; static voidchangecursor(int w){ static char curs[2*4+2*2*16]; static int cfd = -1; static int dummy; static int last = -1; if (w == last) return; if (cfd < 0){ Cursor* c = &whitearrow; cfd = open("/dev/cursor", OWRITE); BPLONG(curs+0*4, c->offset.x); BPLONG(curs+1*4, c->offset.y); memmove(curs+2*4, c->clr, 2*2*16); } if (cfd >=0){ if (w) // restore to default. write(cfd, curs, sizeof curs); else write(cfd, &dummy, sizeof(dummy)); } last = w;} static intalarmed(void *, char *s){ if(strcmp(s, "alarm") == 0) return 1; return 0;} static voidgetsizes(void){ int fd; char buf[80]; int n; char* p; char* e; fd = open("/dev/wctl", OREAD); if (fd < 0){ p = getenv("vgasize"); if (p == nil) p = strdup("1024x768x8"); strcpy(buf, p); free(p); p = strchr(buf, 'x'); *p++ = 0; xmax = strtol(buf, 0, 0); e = strchr(p, 'x'); *e = 0; ymax = strtol(p, 0, 0); xmin = ymin = 0; } else { n = read(fd, buf, sizeof(buf)-1); close(fd); buf[n] = 0; p = buf; xmin = strtol(p, &p, 0); ymin = strtol(p, &p, 0); xmax = strtol(p, &p, 0); ymax = strtol(p, &p, 0); } Dprint(2, "wsize: %d %d %d %d\n", xmin, ymin, xmax, ymax);} static intisreclaim(char* ev){ char buf[60]; int x, y, b; char* p; strecpy(buf, buf+sizeof(buf), ev); x = strtol(buf+2, &p, 0); y = strtol(p, &p, 0); b = strtol(p, &p, 0); return ( x - xmin < 10 && y - ymin < 10 && b == 1);} static inthtonmouse(char* ev){ char buf[60]; int x, y, b; ulong m; double xscale, yscale; char* p; int isnop; strecpy(buf, buf+sizeof(buf), ev); x = strtol(buf+2, &p, 0); y = strtol(p, &p, 0); b = strtol(p, &p, 0); m = strtoul(p, &p, 0); isnop = (x == 0 && y == 0 && b == 0); x -= xmin; y -= ymin; xscale = (double)Stdxmax / (double)(xmax - xmin); yscale = (double)Stdymax / (double)(ymax - ymin); x = (int)(xscale * (double)x); y = (int)(yscale * (double)y); seprint(buf+2, buf+sizeof(buf), "%10d %11d %11d %11lud ", x, y, b, m); strcpy(ev, buf); return !isnop;} static voidntohmouse(char* ev){ char buf[60]; int x, y, b; ulong m; double xscale, yscale; char* p; Dprint(2, "n m: %s\n", ev); strecpy(buf, buf+sizeof(buf), ev); x = strtol(buf+2, &p, 0); y = strtol(p, &p, 0); b = strtol(p, &p, 0); m = strtoul(p, &p, 0); xscale = (double)(xmax - xmin) / Stdxmax; yscale = (double)(ymax - ymin) / Stdymax; x = (int)(xscale * (double)x); y = (int)(yscale * (double)y); x += xmin; y += ymin; seprint(buf+2, buf+sizeof(buf), "%10d %11d %11d %11lud ", x, y, b, m); strcpy(ev, buf); Dprint(2, "h m: %s\n", ev);} static voidfstohmouse(char* ev){ char buf[60]; int x, y; char* p; strecpy(buf, buf+sizeof(buf), ev); x = strtol(buf+1, &p, 0); y = strtol(p, &p, 0); seprint(buf, buf+sizeof(buf), "m%11d %11d %11d %11lud ", x, y, 0, 0UL); strcpy(ev, buf);} static char*csquery(char *addr){ static char buf[128]; char* p; int fd, n; if (localaddr != nil) 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", "11000"); 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++; if (strchr(p, '!')) return smprint("tcp!%s", p); else { addr = smprint("tcp!%s!%s", sysname(), p); return csquery(addr); }} static intislocal(char* a){ char* la; if (!a || !strcmp(a, "local")) return 1; if (!strcmp(a, sysname()) || !strcmp(a, localaddr)) return 1; la = csquery(addr); if (la){ if (!strcmp(a, la)){ free(la); return 1; } free(la); } return 0;} static voidkbdsetdest(char* addr){ static char* last = nil; char* c; int fd, port; char kaddr[50]; fd = open(kbdctl, OWRITE); if (fd < 0){ fprint(2, "mousefs: can't redirect kbd: %r\n"); return; } if (last && !islocal(last)){ dprint(2, "mousefs: kbd: close %s\n", last); fprint(fd, "close %s\n", last); } free(last); last = nil; strecpy(kaddr, kaddr+sizeof(kaddr), addr); c = strrchr(kaddr, '!'); if (c){ *c = 0; port = atoi(c+1) + 1; seprint(c, kaddr+sizeof(kaddr), "!%d", port); } dprint(2, "mousefs: kbd: call %s\n", kaddr); if (fprint(fd, "call %s\n", kaddr) < 0) dprint(2, "mousefs: kbd call failed: %r\n"); last = strdup(kaddr); close(fd);} static voidlocal(void){ dprint(2, "local\n"); changecursor(0); inm = outm = 0; kbdsetdest("local");} static voidreclaim(void){ if (inm == 1 || outm == 1) sendp(devs[1].out, "bye"); local(); while(devs[1].sender || devs[1].receiver){ sleep(500); yield(); }} static voidoutgoing(void){ dprint(2, "outgoing\n"); changecursor(1); inm = 0; outm= 1; kbdsetdest(devs[1].addr);} static voidincoming(void){ dprint(2, "incoming\n"); changecursor(0); inm = 1; outm= 0; kbdsetdest("local");} static voidsendproc(void* a){ Dev* d = a; char* e; threadsetname("sendproc"); dprint(2, "sendproc %p starting\n", d); while(e = recvp(d->out)){ if (strncmp(e, "bye", 3) == 0){ dprint(2, "sendproc %p: bye\n", d); write(d->con, "bye", 3); continue; } if (strncmp(e, "call ", 5) == 0){ write(d->con, e, strlen(e)); free(e); continue; } if (strlen(e) != Mevlen){ dprint(2, "sendproc %p: bad event: %s\n", d, e); } else if (e[0] == 'm'){ e[1] = ' '; if (d != &devs[0]) htonmouse(e); Dprint(2, "sent to %p %s\n", d, e); if (write(d->con, e, Mevlen) != Mevlen){ fprint(2, "%s: write: %r\n", argv0); free(e); write(d->con, "bye", 3); break; } } free(e); } write(d->con, "bye", 3); write(d->cfd, "hangup", 6); close(d->cfd); d->cfd = -1; d->addr[0] = 0; d->sender = 0; dprint(2, "sendproc %p exiting\n", d); threadexits(nil);} static voidrecvproc(void* a){ char buf[Mevlen+1]; Dev* d; int n; char* caddr; d = a; threadsetname("recvproc"); dprint(2, "recvproc %p starting\n", d); caddr = nil; for(;;){ n = read(d->con, buf, Mevlen); if (n == 0){ dprint(2, "recvproc %p: eof\n", d); break; } if (n < 0){ dprint(2, "%s: recvproc %p: %r\n", argv0, d); break; } buf[n] = 0; Dprint(2, "msread: %s\t%p i=%p o=%p\n", buf, d, &devs[inm], &devs[outm]); if (!strncmp(buf, "bye", 3)){ dprint(2, "recvproc %p: bye\n", d); break; } if (!strncmp(buf, "call ", 5)){ dprint(2, "recvproc %p: call\n", d); caddr = buf + 5; break; } if (d == &devs[0]){ if (buf[0] == 'r'){ getsizes(); } if (isreclaim(buf)){ dprint(2, "mousefs: reclaim\n"); reclaim(); continue; } Dprint(2, "mouse %p send: %s\n", d, buf); buf[1] = d->name; if (outm == 0){ if (readers.ref > 0) sendp(devs[outm].evs, estrdup9p(buf)); } else if (buf[0] == 'm') sendp(devs[outm].out, estrdup9p(buf)); } else { ntohmouse(buf); Dprint(2, "mouse %p deliver: %s\n", d, buf); buf[1] = d->name; sendp(devs[0].out, estrdup9p(buf)); if (readers.ref > 0) sendp(devs[0].evs, estrdup9p(buf)); } } sendp(d->out, nil); write(d->con, "bye", 3); write(d->cfd, "hangup", 6); close(d->cfd); close(d->con); d->con = -1; dprint(2, "recvproc %p exiting\n", d); local(); d->receiver = 0; if (caddr != nil && 0){ // not safe. Still too easy to make loops reclaim(); if (newpeer(caddr)) outgoing(); } threadexits(nil);} static voidinitdev(Dev* dev, char name, char* addr){ dev->evs = chancreate(sizeof(char*), Nevs);Lines 1–500 of 1070. 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> typedef struct Dev Dev; enum { Qdir = 0, Qmouse, Qctl, Qmax, Ndevs = 64, Nevs = 128, Stack = 16 * 1024, Mevlen = 1+12*4, // see mouse(3). Stdxmax = 1280, Stdymax = 1024, }; struct Dev { char name; // char to stampt events char addr[50]; // IP for the machine servicing this int con; // to/from peer. int cfd; // ctl fd for con (for hanging up) Channel*evs; // of char*; got from peer Channel*out; // of char*; sent to peer int sender; // true if senderproc alive int receiver; // true if receiverproc alive }; static int newpeer(char* addr); 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[2]; static int debug; static int outm; // output device static int inm; // input device static char* kbdctl = "/dev/kbdctl"; static char* localaddr; static int doauth = 1; static char* vname; static char* addr; static Ref readers; static int mousefd = -1; #define dprint if(debug)fprint #define Dprint if(debug>1)fprint static int xmin, xmax, ymin, ymax; static Cursor whitearrow = { {0, 0}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }, {0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C, 0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C, 0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, } }; static void changecursor(int w) { static char curs[2*4+2*2*16]; static int cfd = -1; static int dummy; static int last = -1; if (w == last) return; if (cfd < 0){ Cursor* c = &whitearrow; cfd = open("/dev/cursor", OWRITE); BPLONG(curs+0*4, c->offset.x); BPLONG(curs+1*4, c->offset.y); memmove(curs+2*4, c->clr, 2*2*16); } if (cfd >=0){ if (w) // restore to default. write(cfd, curs, sizeof curs); else write(cfd, &dummy, sizeof(dummy)); } last = w; } static int alarmed(void *, char *s) { if(strcmp(s, "alarm") == 0) return 1; return 0; } static void getsizes(void) { int fd; char buf[80]; int n; char* p; char* e; fd = open("/dev/wctl", OREAD); if (fd < 0){ p = getenv("vgasize"); if (p == nil) p = strdup("1024x768x8"); strcpy(buf, p); free(p); p = strchr(buf, 'x'); *p++ = 0; xmax = strtol(buf, 0, 0); e = strchr(p, 'x'); *e = 0; ymax = strtol(p, 0, 0); xmin = ymin = 0; } else { n = read(fd, buf, sizeof(buf)-1); close(fd); buf[n] = 0; p = buf; xmin = strtol(p, &p, 0); ymin = strtol(p, &p, 0); xmax = strtol(p, &p, 0); ymax = strtol(p, &p, 0); } Dprint(2, "wsize: %d %d %d %d\n", xmin, ymin, xmax, ymax); } static int isreclaim(char* ev) { char buf[60]; int x, y, b; char* p; strecpy(buf, buf+sizeof(buf), ev); x = strtol(buf+2, &p, 0); y = strtol(p, &p, 0); b = strtol(p, &p, 0); return ( x - xmin < 10 && y - ymin < 10 && b == 1); } static int htonmouse(char* ev) { char buf[60]; int x, y, b; ulong m; double xscale, yscale; char* p; int isnop; strecpy(buf, buf+sizeof(buf), ev); x = strtol(buf+2, &p, 0); y = strtol(p, &p, 0); b = strtol(p, &p, 0); m = strtoul(p, &p, 0); isnop = (x == 0 && y == 0 && b == 0); x -= xmin; y -= ymin; xscale = (double)Stdxmax / (double)(xmax - xmin); yscale = (double)Stdymax / (double)(ymax - ymin); x = (int)(xscale * (double)x); y = (int)(yscale * (double)y); seprint(buf+2, buf+sizeof(buf), "%10d %11d %11d %11lud ", x, y, b, m); strcpy(ev, buf); return !isnop; } static void ntohmouse(char* ev) { char buf[60]; int x, y, b; ulong m; double xscale, yscale; char* p; Dprint(2, "n m: %s\n", ev); strecpy(buf, buf+sizeof(buf), ev); x = strtol(buf+2, &p, 0); y = strtol(p, &p, 0); b = strtol(p, &p, 0); m = strtoul(p, &p, 0); xscale = (double)(xmax - xmin) / Stdxmax; yscale = (double)(ymax - ymin) / Stdymax; x = (int)(xscale * (double)x); y = (int)(yscale * (double)y); x += xmin; y += ymin; seprint(buf+2, buf+sizeof(buf), "%10d %11d %11d %11lud ", x, y, b, m); strcpy(ev, buf); Dprint(2, "h m: %s\n", ev); } static void fstohmouse(char* ev) { char buf[60]; int x, y; char* p; strecpy(buf, buf+sizeof(buf), ev); x = strtol(buf+1, &p, 0); y = strtol(p, &p, 0); seprint(buf, buf+sizeof(buf), "m%11d %11d %11d %11lud ", x, y, 0, 0UL); strcpy(ev, buf); } static char* csquery(char *addr) { static char buf[128]; char* p; int fd, n; if (localaddr != nil) 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", "11000"); 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++; if (strchr(p, '!')) return smprint("tcp!%s", p); else { addr = smprint("tcp!%s!%s", sysname(), p); return csquery(addr); } } static int islocal(char* a) { char* la; if (!a || !strcmp(a, "local")) return 1; if (!strcmp(a, sysname()) || !strcmp(a, localaddr)) return 1; la = csquery(addr); if (la){ if (!strcmp(a, la)){ free(la); return 1; } free(la); } return 0; } static void kbdsetdest(char* addr) { static char* last = nil; char* c; int fd, port; char kaddr[50]; fd = open(kbdctl, OWRITE); if (fd < 0){ fprint(2, "mousefs: can't redirect kbd: %r\n"); return; } if (last && !islocal(last)){ dprint(2, "mousefs: kbd: close %s\n", last); fprint(fd, "close %s\n", last); } free(last); last = nil; strecpy(kaddr, kaddr+sizeof(kaddr), addr); c = strrchr(kaddr, '!'); if (c){ *c = 0; port = atoi(c+1) + 1; seprint(c, kaddr+sizeof(kaddr), "!%d", port); } dprint(2, "mousefs: kbd: call %s\n", kaddr); if (fprint(fd, "call %s\n", kaddr) < 0) dprint(2, "mousefs: kbd call failed: %r\n"); last = strdup(kaddr); close(fd); } static void local(void) { dprint(2, "local\n"); changecursor(0); inm = outm = 0; kbdsetdest("local"); } static void reclaim(void) { if (inm == 1 || outm == 1) sendp(devs[1].out, "bye"); local(); while(devs[1].sender || devs[1].receiver){ sleep(500); yield(); } } static void outgoing(void) { dprint(2, "outgoing\n"); changecursor(1); inm = 0; outm= 1; kbdsetdest(devs[1].addr); } static void incoming(void) { dprint(2, "incoming\n"); changecursor(0); inm = 1; outm= 0; kbdsetdest("local"); } static void sendproc(void* a) { Dev* d = a; char* e; threadsetname("sendproc"); dprint(2, "sendproc %p starting\n", d); while(e = recvp(d->out)){ if (strncmp(e, "bye", 3) == 0){ dprint(2, "sendproc %p: bye\n", d); write(d->con, "bye", 3); continue; } if (strncmp(e, "call ", 5) == 0){ write(d->con, e, strlen(e)); free(e); continue; } if (strlen(e) != Mevlen){ dprint(2, "sendproc %p: bad event: %s\n", d, e); } else if (e[0] == 'm'){ e[1] = ' '; if (d != &devs[0]) htonmouse(e); Dprint(2, "sent to %p %s\n", d, e); if (write(d->con, e, Mevlen) != Mevlen){ fprint(2, "%s: write: %r\n", argv0); free(e); write(d->con, "bye", 3); break; } } free(e); } write(d->con, "bye", 3); write(d->cfd, "hangup", 6); close(d->cfd); d->cfd = -1; d->addr[0] = 0; d->sender = 0; dprint(2, "sendproc %p exiting\n", d); threadexits(nil); } static void recvproc(void* a) { char buf[Mevlen+1]; Dev* d; int n; char* caddr; d = a; threadsetname("recvproc"); dprint(2, "recvproc %p starting\n", d); caddr = nil; for(;;){ n = read(d->con, buf, Mevlen); if (n == 0){ dprint(2, "recvproc %p: eof\n", d); break; } if (n < 0){ dprint(2, "%s: recvproc %p: %r\n", argv0, d); break; } buf[n] = 0; Dprint(2, "msread: %s\t%p i=%p o=%p\n", buf, d, &devs[inm], &devs[outm]); if (!strncmp(buf, "bye", 3)){ dprint(2, "recvproc %p: bye\n", d); break; } if (!strncmp(buf, "call ", 5)){ dprint(2, "recvproc %p: call\n", d); caddr = buf + 5; break; } if (d == &devs[0]){ if (buf[0] == 'r'){ getsizes(); } if (isreclaim(buf)){ dprint(2, "mousefs: reclaim\n"); reclaim(); continue; } Dprint(2, "mouse %p send: %s\n", d, buf); buf[1] = d->name; if (outm == 0){ if (readers.ref > 0) sendp(devs[outm].evs, estrdup9p(buf)); } else if (buf[0] == 'm') sendp(devs[outm].out, estrdup9p(buf)); } else { ntohmouse(buf); Dprint(2, "mouse %p deliver: %s\n", d, buf); buf[1] = d->name; sendp(devs[0].out, estrdup9p(buf)); if (readers.ref > 0) sendp(devs[0].evs, estrdup9p(buf)); } } sendp(d->out, nil); write(d->con, "bye", 3); write(d->cfd, "hangup", 6); close(d->cfd); close(d->con); d->con = -1; dprint(2, "recvproc %p exiting\n", d); local(); d->receiver = 0; if (caddr != nil && 0){ // not safe. Still too easy to make loops reclaim(); if (newpeer(caddr)) outgoing(); } threadexits(nil); } static void initdev(Dev* dev, char name, char* addr) { dev->evs = chancreate(sizeof(char*), Nevs);