1*219b2ee8SDavid du Colombier #define _BSDTIME_EXTENSION 2*219b2ee8SDavid du Colombier #define _LOCK_EXTENSION 33e12c5d1SDavid du Colombier #include "lib.h" 43e12c5d1SDavid du Colombier #include <stdlib.h> 53e12c5d1SDavid du Colombier #include <errno.h> 63e12c5d1SDavid du Colombier #include <unistd.h> 73e12c5d1SDavid du Colombier #include <signal.h> 83e12c5d1SDavid du Colombier #include <string.h> 93e12c5d1SDavid du Colombier #include <stdio.h> 10*219b2ee8SDavid du Colombier #include <lock.h> 11*219b2ee8SDavid du Colombier #include <sys/time.h> 12*219b2ee8SDavid du Colombier #include <select.h> 133e12c5d1SDavid du Colombier #include "sys9.h" 143e12c5d1SDavid du Colombier 15*219b2ee8SDavid du Colombier typedef struct Muxseg { 16*219b2ee8SDavid du Colombier Lock lock; /* for mutual exclusion access to buffer variables */ 17*219b2ee8SDavid du Colombier int curfds; /* number of fds currently buffered */ 18*219b2ee8SDavid du Colombier int selwait; /* true if selecting process is waiting */ 19*219b2ee8SDavid du Colombier int waittime; /* time for timer process to wait */ 20*219b2ee8SDavid du Colombier fd_set rwant; /* fd's that select wants to read */ 21*219b2ee8SDavid du Colombier fd_set ewant; /* fd's that select wants to know eof info on */ 22*219b2ee8SDavid du Colombier Muxbuf bufs[INITBUFS]; /* can grow, via segbrk() */ 23*219b2ee8SDavid du Colombier } Muxseg; 24*219b2ee8SDavid du Colombier 25*219b2ee8SDavid du Colombier #define MUXADDR ((void*)0x6000000) 26*219b2ee8SDavid du Colombier static Muxseg *mux = 0; /* shared memory segment */ 27*219b2ee8SDavid du Colombier 28*219b2ee8SDavid du Colombier /* _muxsid and _killmuxsid are known in libbsd's listen.c */ 29*219b2ee8SDavid du Colombier int _muxsid = -1; /* group id of copy processes */ 30*219b2ee8SDavid du Colombier static int _mainpid = -1; 31*219b2ee8SDavid du Colombier static int timerpid = -1; /* pid of a timer process */ 32*219b2ee8SDavid du Colombier 33*219b2ee8SDavid du Colombier void _killmuxsid(void); 34*219b2ee8SDavid du Colombier static void _copyproc(int, Muxbuf*); 35*219b2ee8SDavid du Colombier static void _timerproc(void); 36*219b2ee8SDavid du Colombier static void _resettimer(void); 37*219b2ee8SDavid du Colombier 38*219b2ee8SDavid du Colombier static int copynotehandler(void *, char *); 39*219b2ee8SDavid du Colombier 40*219b2ee8SDavid du Colombier /* assume FD_SETSIZE is 96 */ 41*219b2ee8SDavid du Colombier #define FD_ANYSET(p) ((p)->fds_bits[0] || (p)->fds_bits[1] || (p)->fds_bits[2]) 423e12c5d1SDavid du Colombier 433e12c5d1SDavid du Colombier 443e12c5d1SDavid du Colombier /* 45*219b2ee8SDavid du Colombier * Start making fd read-buffered: make the shared segment, if necessary, 46*219b2ee8SDavid du Colombier * allocate a slot (index into mux->bufs), and fork a child to read the fd 47*219b2ee8SDavid du Colombier * and write into the slot-indexed buffer. 483e12c5d1SDavid du Colombier * Return -1 if we can't do it. 493e12c5d1SDavid du Colombier */ 503e12c5d1SDavid du Colombier int 513e12c5d1SDavid du Colombier _startbuf(int fd) 523e12c5d1SDavid du Colombier { 53*219b2ee8SDavid du Colombier long i, n, slot; 54*219b2ee8SDavid du Colombier int pid, sid; 553e12c5d1SDavid du Colombier Fdinfo *f; 56*219b2ee8SDavid du Colombier Muxbuf *b; 573e12c5d1SDavid du Colombier 58*219b2ee8SDavid du Colombier if(mux == 0){ 59*219b2ee8SDavid du Colombier _RFORK(RFREND); 60*219b2ee8SDavid du Colombier mux = (Muxseg*)_SEGATTACH(0, "shared", MUXADDR, sizeof(Muxseg)); 61*219b2ee8SDavid du Colombier if((long)mux == -1){ 62*219b2ee8SDavid du Colombier _syserrno(); 633e12c5d1SDavid du Colombier return -1; 643e12c5d1SDavid du Colombier } 65*219b2ee8SDavid du Colombier /* segattach has returned zeroed memory */ 66*219b2ee8SDavid du Colombier lockinit(); 67*219b2ee8SDavid du Colombier atexit(_killmuxsid); 683e12c5d1SDavid du Colombier } 69*219b2ee8SDavid du Colombier 70*219b2ee8SDavid du Colombier slot = mux->curfds++; 71*219b2ee8SDavid du Colombier if(mux->curfds > INITBUFS) { 72*219b2ee8SDavid du Colombier if(_SEGBRK(mux, mux->bufs+mux->curfds) < 0){ 73*219b2ee8SDavid du Colombier _syserrno(); 74*219b2ee8SDavid du Colombier return -1; 75*219b2ee8SDavid du Colombier } 76*219b2ee8SDavid du Colombier } 77*219b2ee8SDavid du Colombier 783e12c5d1SDavid du Colombier f = &_fdinfo[fd]; 79*219b2ee8SDavid du Colombier b = &mux->bufs[slot]; 80*219b2ee8SDavid du Colombier b->n = 0; 81*219b2ee8SDavid du Colombier b->putnext = b->data; 82*219b2ee8SDavid du Colombier b->getnext = b->data; 83*219b2ee8SDavid du Colombier b->eof = 0; 84*219b2ee8SDavid du Colombier b->fd = fd; 85*219b2ee8SDavid du Colombier if(_mainpid == -1) 86*219b2ee8SDavid du Colombier _mainpid = getpid(); 87*219b2ee8SDavid du Colombier if((pid = _RFORK(RFFDG|RFPROC|RFNOWAIT)) == 0){ 88*219b2ee8SDavid du Colombier /* copy process ... */ 89*219b2ee8SDavid du Colombier if(_muxsid == -1) { 90*219b2ee8SDavid du Colombier _RFORK(RFNOTEG); 91*219b2ee8SDavid du Colombier _muxsid = getpgrp(); 92*219b2ee8SDavid du Colombier } else 93*219b2ee8SDavid du Colombier setpgid(getpid(), _muxsid); 94*219b2ee8SDavid du Colombier _NOTIFY(copynotehandler); 953e12c5d1SDavid du Colombier for(i=0; i<OPEN_MAX; i++) 96*219b2ee8SDavid du Colombier if(i!=fd && (_fdinfo[i].flags&FD_ISOPEN)) 973e12c5d1SDavid du Colombier _CLOSE(i); 98*219b2ee8SDavid du Colombier _RENDEZVOUS(0, _muxsid); 99*219b2ee8SDavid du Colombier _copyproc(fd, b); 1003e12c5d1SDavid du Colombier } 101*219b2ee8SDavid du Colombier 102*219b2ee8SDavid du Colombier /* parent process continues ... */ 103*219b2ee8SDavid du Colombier b->copypid = pid; 104*219b2ee8SDavid du Colombier f->buf = b; 1053e12c5d1SDavid du Colombier f->flags |= FD_BUFFERED; 106*219b2ee8SDavid du Colombier _muxsid = _RENDEZVOUS(0, 0); 107*219b2ee8SDavid du Colombier /* leave fd open in parent so system doesn't reuse it */ 1083e12c5d1SDavid du Colombier return 0; 1093e12c5d1SDavid du Colombier } 1103e12c5d1SDavid du Colombier 1113e12c5d1SDavid du Colombier /* 112*219b2ee8SDavid du Colombier * The given buffered fd is being closed. 113*219b2ee8SDavid du Colombier * Set the fd field in the shared buffer to -1 to tell copyproc 114*219b2ee8SDavid du Colombier * to exit, and kill the copyproc. 1153e12c5d1SDavid du Colombier */ 116*219b2ee8SDavid du Colombier void 117*219b2ee8SDavid du Colombier _closebuf(int fd) 1183e12c5d1SDavid du Colombier { 119*219b2ee8SDavid du Colombier Muxbuf *b; 1203e12c5d1SDavid du Colombier 121*219b2ee8SDavid du Colombier b = _fdinfo[fd].buf; 122*219b2ee8SDavid du Colombier if(!b) 123*219b2ee8SDavid du Colombier return; 124*219b2ee8SDavid du Colombier lock(&mux->lock); 125*219b2ee8SDavid du Colombier b->fd = -1; 126*219b2ee8SDavid du Colombier unlock(&mux->lock); 127*219b2ee8SDavid du Colombier kill(b->copypid, SIGKILL); 128*219b2ee8SDavid du Colombier } 129*219b2ee8SDavid du Colombier 130*219b2ee8SDavid du Colombier /* child copy procs execute this until eof */ 131*219b2ee8SDavid du Colombier static void 132*219b2ee8SDavid du Colombier _copyproc(int fd, Muxbuf *b) 133*219b2ee8SDavid du Colombier { 134*219b2ee8SDavid du Colombier unsigned char *e; 135*219b2ee8SDavid du Colombier int n; 136*219b2ee8SDavid du Colombier int nzeros; 137*219b2ee8SDavid du Colombier 138*219b2ee8SDavid du Colombier e = &b->data[PERFDMAX]; 1393e12c5d1SDavid du Colombier for(;;) { 140*219b2ee8SDavid du Colombier /* make sure there's room */ 141*219b2ee8SDavid du Colombier lock(&mux->lock); 142*219b2ee8SDavid du Colombier if(e - b->putnext < READMAX) { 143*219b2ee8SDavid du Colombier if(b->getnext == b->putnext) { 144*219b2ee8SDavid du Colombier b->getnext = b->putnext = b->data; 145*219b2ee8SDavid du Colombier unlock(&mux->lock); 146*219b2ee8SDavid du Colombier } else { 147*219b2ee8SDavid du Colombier /* sleep until there's room */ 148*219b2ee8SDavid du Colombier b->roomwait = 1; 149*219b2ee8SDavid du Colombier unlock(&mux->lock); 150*219b2ee8SDavid du Colombier _RENDEZVOUS((unsigned long)&b->roomwait, 0); 151*219b2ee8SDavid du Colombier } 152*219b2ee8SDavid du Colombier } else 153*219b2ee8SDavid du Colombier unlock(&mux->lock); 1543e12c5d1SDavid du Colombier /* 155*219b2ee8SDavid du Colombier * A Zero-length _READ might mean a zero-length write 156*219b2ee8SDavid du Colombier * happened, or it might mean eof; try several times to 157*219b2ee8SDavid du Colombier * disambiguate (posix read() discards 0-length messages) 1583e12c5d1SDavid du Colombier */ 159*219b2ee8SDavid du Colombier nzeros = 0; 160*219b2ee8SDavid du Colombier do { 161*219b2ee8SDavid du Colombier n = _READ(fd, b->putnext, READMAX); 162*219b2ee8SDavid du Colombier if(b->fd == -1) { 163*219b2ee8SDavid du Colombier _exit(0); /* we've been closed */ 164*219b2ee8SDavid du Colombier } 165*219b2ee8SDavid du Colombier } while(n == 0 && ++nzeros < 3); 166*219b2ee8SDavid du Colombier lock(&mux->lock); 167*219b2ee8SDavid du Colombier if(n <= 0) { 168*219b2ee8SDavid du Colombier b->eof = 1; 169*219b2ee8SDavid du Colombier if(mux->selwait && FD_ISSET(fd, &mux->ewant)) { 170*219b2ee8SDavid du Colombier mux->selwait = 0; 171*219b2ee8SDavid du Colombier unlock(&mux->lock); 172*219b2ee8SDavid du Colombier _RENDEZVOUS((unsigned long)&mux->selwait, fd); 173*219b2ee8SDavid du Colombier } else if(b->datawait) { 174*219b2ee8SDavid du Colombier b->datawait = 0; 175*219b2ee8SDavid du Colombier unlock(&mux->lock); 176*219b2ee8SDavid du Colombier _RENDEZVOUS((unsigned long)&b->datawait, 0); 177*219b2ee8SDavid du Colombier } else if(mux->selwait && FD_ISSET(fd, &mux->rwant)) { 178*219b2ee8SDavid du Colombier mux->selwait = 0; 179*219b2ee8SDavid du Colombier unlock(&mux->lock); 180*219b2ee8SDavid du Colombier _RENDEZVOUS((unsigned long)&mux->selwait, fd); 181*219b2ee8SDavid du Colombier } else 182*219b2ee8SDavid du Colombier unlock(&mux->lock); 183*219b2ee8SDavid du Colombier _exit(0); 184*219b2ee8SDavid du Colombier } else { 185*219b2ee8SDavid du Colombier b->putnext += n; 186*219b2ee8SDavid du Colombier b->n += n; 187*219b2ee8SDavid du Colombier if(b->n > 0) { 188*219b2ee8SDavid du Colombier /* parent process cannot be both in datawait and selwait */ 189*219b2ee8SDavid du Colombier if(b->datawait) { 190*219b2ee8SDavid du Colombier b->datawait = 0; 191*219b2ee8SDavid du Colombier unlock(&mux->lock); 192*219b2ee8SDavid du Colombier /* wake up _bufreading process */ 193*219b2ee8SDavid du Colombier _RENDEZVOUS((unsigned long)&b->datawait, 0); 194*219b2ee8SDavid du Colombier } else if(mux->selwait && FD_ISSET(fd, &mux->rwant)) { 195*219b2ee8SDavid du Colombier mux->selwait = 0; 196*219b2ee8SDavid du Colombier unlock(&mux->lock); 197*219b2ee8SDavid du Colombier /* wake up selecting process */ 198*219b2ee8SDavid du Colombier _RENDEZVOUS((unsigned long)&mux->selwait, fd); 199*219b2ee8SDavid du Colombier } else 200*219b2ee8SDavid du Colombier unlock(&mux->lock); 201*219b2ee8SDavid du Colombier } else 202*219b2ee8SDavid du Colombier unlock(&mux->lock); 203*219b2ee8SDavid du Colombier } 204*219b2ee8SDavid du Colombier } 205*219b2ee8SDavid du Colombier } 206*219b2ee8SDavid du Colombier 207*219b2ee8SDavid du Colombier /* like read(), for a buffered fd; extra arg noblock says don't wait for data if true */ 208*219b2ee8SDavid du Colombier int 209*219b2ee8SDavid du Colombier _readbuf(int fd, void *addr, int nwant, int noblock) 210*219b2ee8SDavid du Colombier { 211*219b2ee8SDavid du Colombier Muxbuf *b; 212*219b2ee8SDavid du Colombier int ngot; 213*219b2ee8SDavid du Colombier 214*219b2ee8SDavid du Colombier b = _fdinfo[fd].buf; 215*219b2ee8SDavid du Colombier if(b->eof && b->n == 0) { 216*219b2ee8SDavid du Colombier goteof: 217*219b2ee8SDavid du Colombier return 0; 218*219b2ee8SDavid du Colombier } 219*219b2ee8SDavid du Colombier if(b->n == 0 && noblock) { 220*219b2ee8SDavid du Colombier errno = EAGAIN; 2213e12c5d1SDavid du Colombier return -1; 2223e12c5d1SDavid du Colombier } 223*219b2ee8SDavid du Colombier /* make sure there's data */ 224*219b2ee8SDavid du Colombier lock(&mux->lock); 225*219b2ee8SDavid du Colombier ngot = b->putnext - b->getnext; 226*219b2ee8SDavid du Colombier if(ngot == 0) { 227*219b2ee8SDavid du Colombier /* maybe EOF just happened */ 228*219b2ee8SDavid du Colombier if(b->eof) { 229*219b2ee8SDavid du Colombier unlock(&mux->lock); 230*219b2ee8SDavid du Colombier goto goteof; 2313e12c5d1SDavid du Colombier } 232*219b2ee8SDavid du Colombier /* sleep until there's data */ 233*219b2ee8SDavid du Colombier b->datawait = 1; 234*219b2ee8SDavid du Colombier unlock(&mux->lock); 235*219b2ee8SDavid du Colombier _RENDEZVOUS((unsigned long)&b->datawait, 0); 236*219b2ee8SDavid du Colombier lock(&mux->lock); 237*219b2ee8SDavid du Colombier ngot = b->putnext - b->getnext; 238*219b2ee8SDavid du Colombier } 239*219b2ee8SDavid du Colombier if(ngot == 0) { 240*219b2ee8SDavid du Colombier unlock(&mux->lock); 241*219b2ee8SDavid du Colombier goto goteof; 242*219b2ee8SDavid du Colombier } 243*219b2ee8SDavid du Colombier if(ngot > nwant) 244*219b2ee8SDavid du Colombier ngot = nwant; 245*219b2ee8SDavid du Colombier memcpy(addr, b->getnext, ngot); 246*219b2ee8SDavid du Colombier b->getnext += ngot; 247*219b2ee8SDavid du Colombier b->n -= ngot; 248*219b2ee8SDavid du Colombier if(b->getnext == b->putnext && b->roomwait) { 249*219b2ee8SDavid du Colombier b->getnext = b->putnext = b->data; 250*219b2ee8SDavid du Colombier b->roomwait = 0; 251*219b2ee8SDavid du Colombier unlock(&mux->lock); 252*219b2ee8SDavid du Colombier /* wake up copy process */ 253*219b2ee8SDavid du Colombier _RENDEZVOUS((unsigned long)&b->roomwait, 0); 254*219b2ee8SDavid du Colombier } else 255*219b2ee8SDavid du Colombier unlock(&mux->lock); 256*219b2ee8SDavid du Colombier return ngot; 257*219b2ee8SDavid du Colombier } 2583e12c5d1SDavid du Colombier 259*219b2ee8SDavid du Colombier int 260*219b2ee8SDavid du Colombier select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 261*219b2ee8SDavid du Colombier { 262*219b2ee8SDavid du Colombier int n, i, tmp, t, slots, fd; 263*219b2ee8SDavid du Colombier Fdinfo *f; 264*219b2ee8SDavid du Colombier Muxbuf *b; 2653e12c5d1SDavid du Colombier 266*219b2ee8SDavid du Colombier if(timeout) 267*219b2ee8SDavid du Colombier t = timeout->tv_sec*1000 + (timeout->tv_usec+999)/1000; 268*219b2ee8SDavid du Colombier else 269*219b2ee8SDavid du Colombier t = -1; 270*219b2ee8SDavid du Colombier if(!((rfds && FD_ANYSET(rfds)) || (wfds && FD_ANYSET(wfds)) 271*219b2ee8SDavid du Colombier || (efds && FD_ANYSET(efds)))) { 272*219b2ee8SDavid du Colombier /* no requested fds */ 273*219b2ee8SDavid du Colombier if(t > 0) 274*219b2ee8SDavid du Colombier _SLEEP(t); 275*219b2ee8SDavid du Colombier return 0; 276*219b2ee8SDavid du Colombier } 277*219b2ee8SDavid du Colombier 278*219b2ee8SDavid du Colombier /* make sure all requested rfds and efds are buffered */ 279*219b2ee8SDavid du Colombier if(nfds >= OPEN_MAX) 280*219b2ee8SDavid du Colombier nfds = OPEN_MAX-1; 281*219b2ee8SDavid du Colombier for(i = 0; i<= nfds; i++) 282*219b2ee8SDavid du Colombier if((rfds && FD_ISSET(i, rfds)) || (efds && FD_ISSET(i, efds))){ 283*219b2ee8SDavid du Colombier f = &_fdinfo[i]; 284*219b2ee8SDavid du Colombier if(!(f->flags&FD_BUFFERED)) 285*219b2ee8SDavid du Colombier if(_startbuf(i) != 0) { 2863e12c5d1SDavid du Colombier return -1; 2873e12c5d1SDavid du Colombier } 288*219b2ee8SDavid du Colombier b = f->buf; 289*219b2ee8SDavid du Colombier if(rfds && FD_ISSET(i,rfds) && b->eof && b->n == 0) { 290*219b2ee8SDavid du Colombier errno = EBADF; /* how X tells a client is gone */ 291*219b2ee8SDavid du Colombier return -1; 292*219b2ee8SDavid du Colombier } 293*219b2ee8SDavid du Colombier } 294*219b2ee8SDavid du Colombier 295*219b2ee8SDavid du Colombier /* check wfds; for now, we'll say they are all ready */ 296*219b2ee8SDavid du Colombier n = 0; 297*219b2ee8SDavid du Colombier if(wfds && FD_ANYSET(wfds)){ 298*219b2ee8SDavid du Colombier for(i = 0; i<nfds; i++) 299*219b2ee8SDavid du Colombier if(FD_ISSET(i, wfds)) { 300*219b2ee8SDavid du Colombier n++; 301*219b2ee8SDavid du Colombier } 302*219b2ee8SDavid du Colombier } 303*219b2ee8SDavid du Colombier 304*219b2ee8SDavid du Colombier lock(&mux->lock); 305*219b2ee8SDavid du Colombier 306*219b2ee8SDavid du Colombier slots = mux->curfds; 307*219b2ee8SDavid du Colombier FD_ZERO(&mux->rwant); 308*219b2ee8SDavid du Colombier FD_ZERO(&mux->ewant); 309*219b2ee8SDavid du Colombier 310*219b2ee8SDavid du Colombier for(i = 0; i<slots; i++) { 311*219b2ee8SDavid du Colombier b = &mux->bufs[i]; 312*219b2ee8SDavid du Colombier fd = b->fd; 313*219b2ee8SDavid du Colombier if(fd == -1) 314*219b2ee8SDavid du Colombier continue; 315*219b2ee8SDavid du Colombier if(rfds && FD_ISSET(fd, rfds)) { 316*219b2ee8SDavid du Colombier if(b->n > 0 || b->eof) 317*219b2ee8SDavid du Colombier n++; 3183e12c5d1SDavid du Colombier else{ 319*219b2ee8SDavid du Colombier FD_CLR(fd, rfds); 320*219b2ee8SDavid du Colombier FD_SET(fd, &mux->rwant); 3213e12c5d1SDavid du Colombier } 3223e12c5d1SDavid du Colombier } 323*219b2ee8SDavid du Colombier if(efds && FD_ISSET(fd, efds)) { 324*219b2ee8SDavid du Colombier if(b->eof && b->n == 0) 325*219b2ee8SDavid du Colombier n++; 326*219b2ee8SDavid du Colombier else{ 327*219b2ee8SDavid du Colombier FD_CLR(fd, efds); 328*219b2ee8SDavid du Colombier FD_SET(fd, &mux->ewant); 3293e12c5d1SDavid du Colombier } 3303e12c5d1SDavid du Colombier } 331*219b2ee8SDavid du Colombier } 332*219b2ee8SDavid du Colombier if(n || !(FD_ANYSET(&mux->rwant) || FD_ANYSET(&mux->ewant)) || t == 0) { 333*219b2ee8SDavid du Colombier FD_ZERO(&mux->rwant); 334*219b2ee8SDavid du Colombier FD_ZERO(&mux->ewant); 335*219b2ee8SDavid du Colombier unlock(&mux->lock); 336*219b2ee8SDavid du Colombier return n; 337*219b2ee8SDavid du Colombier } 338*219b2ee8SDavid du Colombier 339*219b2ee8SDavid du Colombier if(timeout) { 340*219b2ee8SDavid du Colombier mux->waittime = t; 341*219b2ee8SDavid du Colombier if(timerpid == -1) 342*219b2ee8SDavid du Colombier _timerproc(); 343*219b2ee8SDavid du Colombier else 344*219b2ee8SDavid du Colombier _resettimer(); 345*219b2ee8SDavid du Colombier } 346*219b2ee8SDavid du Colombier mux->selwait = 1; 347*219b2ee8SDavid du Colombier unlock(&mux->lock); 348*219b2ee8SDavid du Colombier fd = _RENDEZVOUS((unsigned long)&mux->selwait, 0); 349*219b2ee8SDavid du Colombier if(fd >= 0) { 350*219b2ee8SDavid du Colombier b = _fdinfo[fd].buf; 351*219b2ee8SDavid du Colombier if(FD_ISSET(fd, &mux->rwant)) { 352*219b2ee8SDavid du Colombier FD_SET(fd, rfds); 353*219b2ee8SDavid du Colombier n = 1; 354*219b2ee8SDavid du Colombier } else if(FD_ISSET(fd, &mux->ewant) && b->eof && b->n == 0) { 355*219b2ee8SDavid du Colombier FD_SET(fd, efds); 356*219b2ee8SDavid du Colombier n = 1; 357*219b2ee8SDavid du Colombier } 358*219b2ee8SDavid du Colombier } 359*219b2ee8SDavid du Colombier FD_ZERO(&mux->rwant); 360*219b2ee8SDavid du Colombier FD_ZERO(&mux->ewant); 361*219b2ee8SDavid du Colombier return n; 362*219b2ee8SDavid du Colombier } 363*219b2ee8SDavid du Colombier 364*219b2ee8SDavid du Colombier static int timerreset; 365*219b2ee8SDavid du Colombier 366*219b2ee8SDavid du Colombier static void 367*219b2ee8SDavid du Colombier alarmed(int v) 368*219b2ee8SDavid du Colombier { 369*219b2ee8SDavid du Colombier timerreset = 1; 370*219b2ee8SDavid du Colombier } 371*219b2ee8SDavid du Colombier 372*219b2ee8SDavid du Colombier /* a little over an hour */ 373*219b2ee8SDavid du Colombier #define LONGWAIT 4000001 374*219b2ee8SDavid du Colombier 375*219b2ee8SDavid du Colombier static void 376*219b2ee8SDavid du Colombier _timerproc(void) 377*219b2ee8SDavid du Colombier { 378*219b2ee8SDavid du Colombier int i; 379*219b2ee8SDavid du Colombier 380*219b2ee8SDavid du Colombier if((timerpid = _RFORK(RFFDG|RFPROC|RFNOWAIT)) == 0){ 381*219b2ee8SDavid du Colombier /* timer process */ 382*219b2ee8SDavid du Colombier setpgid(getpid(), _muxsid); 383*219b2ee8SDavid du Colombier signal(SIGALRM, alarmed); 384*219b2ee8SDavid du Colombier for(i=0; i<OPEN_MAX; i++) 385*219b2ee8SDavid du Colombier _CLOSE(i); 386*219b2ee8SDavid du Colombier _RENDEZVOUS(1, 0); 387*219b2ee8SDavid du Colombier for(;;) { 388*219b2ee8SDavid du Colombier _SLEEP(mux->waittime); 389*219b2ee8SDavid du Colombier if(timerreset) { 390*219b2ee8SDavid du Colombier timerreset = 0; 391*219b2ee8SDavid du Colombier } else { 392*219b2ee8SDavid du Colombier lock(&mux->lock); 393*219b2ee8SDavid du Colombier if(mux->selwait && mux->waittime != LONGWAIT) { 394*219b2ee8SDavid du Colombier mux->selwait = 0; 395*219b2ee8SDavid du Colombier mux->waittime = LONGWAIT; 396*219b2ee8SDavid du Colombier unlock(&mux->lock); 397*219b2ee8SDavid du Colombier _RENDEZVOUS((unsigned long)&mux->selwait, -2); 398*219b2ee8SDavid du Colombier } else { 399*219b2ee8SDavid du Colombier mux->waittime = LONGWAIT; 400*219b2ee8SDavid du Colombier unlock(&mux->lock); 401*219b2ee8SDavid du Colombier } 402*219b2ee8SDavid du Colombier } 403*219b2ee8SDavid du Colombier } 404*219b2ee8SDavid du Colombier } 405*219b2ee8SDavid du Colombier /* parent process continues */ 406*219b2ee8SDavid du Colombier _RENDEZVOUS(1, 0); 407*219b2ee8SDavid du Colombier } 408*219b2ee8SDavid du Colombier 409*219b2ee8SDavid du Colombier static void 410*219b2ee8SDavid du Colombier _resettimer(void) 411*219b2ee8SDavid du Colombier { 412*219b2ee8SDavid du Colombier kill(timerpid, SIGALRM); 413*219b2ee8SDavid du Colombier } 414*219b2ee8SDavid du Colombier 415*219b2ee8SDavid du Colombier void 416*219b2ee8SDavid du Colombier _killmuxsid(void) 417*219b2ee8SDavid du Colombier { 418*219b2ee8SDavid du Colombier if(_muxsid != -1 && (_mainpid == getpid() || _mainpid == -1)) 419*219b2ee8SDavid du Colombier kill(-_muxsid,SIGTERM); 420*219b2ee8SDavid du Colombier } 421*219b2ee8SDavid du Colombier 422*219b2ee8SDavid du Colombier /* call this on fork(), because reading a BUFFERED fd won't work in child */ 423*219b2ee8SDavid du Colombier void 424*219b2ee8SDavid du Colombier _detachbuf(void) 425*219b2ee8SDavid du Colombier { 426*219b2ee8SDavid du Colombier int i; 427*219b2ee8SDavid du Colombier Fdinfo *f; 428*219b2ee8SDavid du Colombier 429*219b2ee8SDavid du Colombier if(mux == 0) 430*219b2ee8SDavid du Colombier return; 431*219b2ee8SDavid du Colombier _SEGDETACH(mux); 432*219b2ee8SDavid du Colombier for(i = 0; i < OPEN_MAX; i++){ 433*219b2ee8SDavid du Colombier f = &_fdinfo[i]; 434*219b2ee8SDavid du Colombier if(f->flags&FD_BUFFERED) 435*219b2ee8SDavid du Colombier f->flags = (f->flags&~FD_BUFFERED) | FD_BUFFEREDX; 436*219b2ee8SDavid du Colombier /* mark 'poisoned' */ 437*219b2ee8SDavid du Colombier } 438*219b2ee8SDavid du Colombier mux = 0; 439*219b2ee8SDavid du Colombier _muxsid = -1; 440*219b2ee8SDavid du Colombier _mainpid = -1; 441*219b2ee8SDavid du Colombier timerpid = -1; 442*219b2ee8SDavid du Colombier } 443*219b2ee8SDavid du Colombier 444*219b2ee8SDavid du Colombier static int 445*219b2ee8SDavid du Colombier copynotehandler(void *u, char *msg) 446*219b2ee8SDavid du Colombier { 447*219b2ee8SDavid du Colombier int i; 448*219b2ee8SDavid du Colombier void(*f)(int); 449*219b2ee8SDavid du Colombier 450*219b2ee8SDavid du Colombier if(_finishing) 451*219b2ee8SDavid du Colombier _finish(0, 0); 452*219b2ee8SDavid du Colombier _NOTED(1); 453*219b2ee8SDavid du Colombier } 454