void threadmain(int argc, char **argv) { uchar buf[4], *mbuf; int nmbuf, n, nn; Wsysmsg m; /* * Move the protocol off stdin/stdout so that * any inadvertent prints don't screw things up. */ dup(0, 3); dup(1, 4); close(0); close(1); open("/dev/null", OREAD); open("/dev/null", OWRITE); //trace = 1; fmtinstall('W', drawfcallfmt); ARGBEGIN{ case 'D': chatty++; break; default: usage(); }ARGEND /* * Ignore arguments. They're only for good ps -a listings. */ notify(bell); mbuf = nil; nmbuf = 0; while((n = read(3, buf, 4)) == 4){ GET(buf, n); if(n > nmbuf){ free(mbuf); mbuf = malloc(4+n); if(mbuf == nil) sysfatal("malloc: %r"); nmbuf = n; } memmove(mbuf, buf, 4); nn = readn(3, mbuf+4, n-4); if(nn != n-4) sysfatal("eof during message"); /* pick off messages one by one */ if(convM2W(mbuf, nn+4, &m) <= 0) sysfatal("cannot convert message"); if(trace) fprint(2, "<- %W\n", &m); runmsg(&m); } threadexitsall(0); }
static int finishrpc(Muxrpc *r, Wsysmsg *w) { uchar *p; void *v; int n; if(!muxrpccanfinish(r, &v)) return 0; p = v; if(p == nil) /* eof on connection */ exit(0); GET(p, n); convM2W(p, n, w); free(p); return 1; }
void main(int argc, char **argv) { int n, top, firstx; fd_set rd, wr, xx; Wsysmsg m; XEvent event; /* * Move the protocol off stdin/stdout so that * any inadvertent prints don't screw things up. */ dup(0, 3); dup(1, 4); close(0); close(1); open("/dev/null", OREAD); open("/dev/null", OWRITE); /* reopens stdout if debugging */ runxevent(0); fmtinstall('W', drawfcallfmt); ARGBEGIN{ case 'D': chatty++; break; default: usage(); }ARGEND /* * Ignore arguments. They're only for good ps -a listings. */ notify(bell); fdin.rp = fdin.wp = fdin.buf; fdin.ep = fdin.buf+sizeof fdin.buf; fdout.rp = fdout.wp = fdout.buf; fdout.ep = fdout.buf+sizeof fdout.buf; fdnoblock(3); fdnoblock(4); firstx = 1; _x.fd = -1; for(;;){ /* set up file descriptors */ FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&xx); /* * Don't read unless there's room *and* we haven't * already filled the output buffer too much. */ if(fdout.wp < fdout.buf+MAXWMSG && fdin.wp < fdin.ep) FD_SET(3, &rd); if(fdout.wp > fdout.rp) FD_SET(4, &wr); FD_SET(3, &xx); FD_SET(4, &xx); top = 4; if(_x.fd >= 0){ if(firstx){ firstx = 0; XSelectInput(_x.display, _x.drawable, Mask); } FD_SET(_x.fd, &rd); FD_SET(_x.fd, &xx); XFlush(_x.display); if(_x.fd > top) top = _x.fd; } if(chatty) fprint(2, "select %d...\n", top+1); /* wait for something to happen */ again: if(select(top+1, &rd, &wr, &xx, NULL) < 0){ if(errno == EINTR) goto again; if(chatty) fprint(2, "select failure\n"); exits(0); } if(chatty) fprint(2, "got select...\n"); { /* read what we can */ n = 1; while(fdin.wp < fdin.ep && (n = read(3, fdin.wp, fdin.ep-fdin.wp)) > 0) fdin.wp += n; if(n == 0){ if(chatty) fprint(2, "eof\n"); exits(0); } if(n < 0 && errno != EAGAIN) sysfatal("reading wsys msg: %r"); /* pick off messages one by one */ while((n = convM2W(fdin.rp, fdin.wp-fdin.rp, &m)) > 0){ /* fprint(2, "<- %W\n", &m); */ runmsg(&m); fdin.rp += n; } /* slide data to beginning of buf */ fdslide(&fdin); } { /* write what we can */ n = 1; while(fdout.rp < fdout.wp && (n = write(4, fdout.rp, fdout.wp-fdout.rp)) > 0) fdout.rp += n; if(n == 0) sysfatal("short write writing wsys"); if(n < 0 && errno != EAGAIN) sysfatal("writing wsys msg: %r"); /* slide data to beginning of buf */ fdslide(&fdout); } { /* * Read an X message if we can. * (XPending actually calls select to make sure * the display's fd is readable and then reads * in any waiting data before declaring whether * there are events on the queue.) */ while(XPending(_x.display)){ XNextEvent(_x.display, &event); runxevent(&event); } } } }