#include #include #include #include #include #include #include #include #include enum{ MAXSLAVE = 32 }; typedef struct Slave Slave; typedef struct Ebuf Ebuf; struct Slave{ int pid; int ack; /* fd for sending flow-control ack to slave */ int count; /* bytes received but not acked */ Ebuf *head; /* queue of messages for this descriptor */ Ebuf *tail; }; struct Ebuf{ Ebuf *next; int n; /* number of bytes in buf */ unsigned char buf[EMAXMSG]; }; static Slave eslave[MAXSLAVE]; static int nslave; static int isslave = 0; static int Smouse = -1; static int Skeyboard = -1; static int Stimer = -1; static int epipe[2]; static Ebuf *ebread(Slave*); static int eforkslave(unsigned long); static void extract(void); static void eerror(char*); static void ekill(void); static void enote(int); Mouse emouse(void) { Mouse m; Ebuf *eb; if(Smouse < 0) eerror("mouse not initialzed"); eb = ebread(&eslave[Smouse]); m.buttons = eb->buf[1] & 7; m.xy.x = BGLONG(eb->buf+2); m.xy.y = BGLONG(eb->buf+6); free(eb); return m; } int ekbd(void) { Ebuf *eb; int c; if(Skeyboard < 0) eerror("keyboard not initialzed"); eb = ebread(&eslave[Skeyboard]); c = eb->buf[0]; free(eb); return c; } unsigned long event(Event *e) { return eread(~0UL, e); } unsigned long eread(unsigned long keys, Event *e) { Ebuf *eb; int i; if(keys == 0) return 0; for(;;){ for(i=0; imouse = emouse(); else if(i == Skeyboard) e->kbdc = ekbd(); else if(i == Stimer) eslave[i].head = 0; else{ eb = ebread(&eslave[i]); e->n = eb->n; memmove(e->data, eb->buf, e->n); free(eb); } return 1< EMAXMSG) n = EMAXMSG; if(pipe(ack) < 0) eerror("estart pipe"); i = eforkslave(key); if(i < MAXSLAVE){ eslave[i].ack = ack[1]; close(ack[0]); return 1<0 && write(epipe[1], buf, r+1)==r+1){ count += r; if(count > EMAXMSG){ read(ack[0], buf+1, 1); count -= EMAXMSG; } } buf[0] = MAXSLAVE; write(epipe[1], buf, 1); _exit(0); } unsigned long etimer(unsigned long key, int n) { char t[2]; extern void _nap(unsigned int); if(Stimer != -1) eerror("timer started twice\n"); Stimer = eforkslave(key); if(Stimer < MAXSLAVE) return 1<head == 0) extract(); eb = s->head; s->head = s->head->next; if(s->head == 0) s->tail = 0; s->count += eb->n; if(s->count > EMAXMSG){ write(s->ack, "a", 1); s->count -= EMAXMSG; } return eb; } static void extract(void) { Slave *s; Ebuf *eb; int i, n; unsigned char ebuf[EMAXMSG+1]; bflush(); if((n=read(epipe[0], (char *)ebuf, EMAXMSG+1)) <= 0 || ebuf[0] >= MAXSLAVE) exit(1); i = ebuf[0]; if(i >= nslave || n <= 1) eerror("protocol error"); s = &eslave[i]; if(i == Stimer){ s->head = (Ebuf *)1; return; } if(i == Skeyboard && n != 2) eerror("protocol error"); if(i == Smouse){ if(n!=1+10 || ebuf[1]!='m') eerror("protocol error"); if(ebuf[2] & 0x80) ereshaped(bscreenrect()); /* squash extraneous mouse events */ if(s->head) free(ebread(s)); } /* try to save space by only alloacting as much buffer as we need */ eb = malloc(sizeof(*eb) - sizeof(eb->buf) + n - 1); if(eb == 0) eerror("protocol error"); eb->n = n - 1; memmove(eb->buf, &ebuf[1], n - 1); eb->next = 0; if(s->head) s->tail = s->tail->next = eb; else s->head = s->tail = eb; } static int eforkslave(unsigned long key) { int i; for(i=0; i 0){ write(fd, "die", 3); close(fd); } } } static void ekill(void) { enote(SIGTERM); }