123384Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423384Smckusick * 544444Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*45914Smckusick * @(#)sys_generic.c 7.25 (Berkeley) 01/10/91 823384Smckusick */ 97423Sroot 1017094Sbloom #include "param.h" 1117094Sbloom #include "systm.h" 1244405Skarels #include "user.h" 13*45914Smckusick #include "filedesc.h" 1417094Sbloom #include "ioctl.h" 1517094Sbloom #include "file.h" 1617094Sbloom #include "proc.h" 1717094Sbloom #include "uio.h" 1817094Sbloom #include "kernel.h" 1917094Sbloom #include "stat.h" 2031653Smckusick #include "malloc.h" 2137127Skarels #ifdef KTRACE 2237127Skarels #include "ktrace.h" 2337127Skarels #endif 247423Sroot 257423Sroot /* 267423Sroot * Read system call. 277423Sroot */ 2845122Sbostic /* ARGSUSED */ 2942922Smckusick read(p, uap, retval) 3042922Smckusick struct proc *p; 3142922Smckusick register struct args { 327423Sroot int fdes; 337423Sroot char *cbuf; 347423Sroot unsigned count; 3542922Smckusick } *uap; 3642922Smckusick int *retval; 3742922Smckusick { 3837728Smckusick register struct file *fp; 39*45914Smckusick register struct filedesc *fdp = p->p_fd; 407746Sroot struct uio auio; 417746Sroot struct iovec aiov; 4237728Smckusick long cnt, error = 0; 4337728Smckusick #ifdef KTRACE 4437728Smckusick struct iovec ktriov; 4537728Smckusick #endif 467423Sroot 47*45914Smckusick if (((unsigned)uap->fdes) >= fdp->fd_maxfiles || 48*45914Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL || 4937728Smckusick (fp->f_flag & FREAD) == 0) 5044405Skarels return (EBADF); 517820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 527820Sroot aiov.iov_len = uap->count; 537820Sroot auio.uio_iov = &aiov; 547820Sroot auio.uio_iovcnt = 1; 5537728Smckusick auio.uio_resid = uap->count; 5637728Smckusick auio.uio_rw = UIO_READ; 5737728Smckusick auio.uio_segflg = UIO_USERSPACE; 5837728Smckusick #ifdef KTRACE 5937728Smckusick /* 6037728Smckusick * if tracing, save a copy of iovec 6137728Smckusick */ 6242922Smckusick if (KTRPOINT(p, KTR_GENIO)) 6337728Smckusick ktriov = aiov; 6437728Smckusick #endif 6537728Smckusick cnt = uap->count; 6640703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 6740703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 6840703Skarels error == EINTR || error == EWOULDBLOCK)) 6940703Skarels error = 0; 7037728Smckusick cnt -= auio.uio_resid; 7137728Smckusick #ifdef KTRACE 7242922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 7343448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error); 7437728Smckusick #endif 7542922Smckusick *retval = cnt; 7644405Skarels return (error); 777820Sroot } 787820Sroot 7942922Smckusick /* 8042922Smckusick * Scatter read system call. 8142922Smckusick */ 8245122Sbostic /* ARGSUSED */ 8342922Smckusick readv(p, uap, retval) 8442922Smckusick struct proc *p; 8542922Smckusick register struct args { 867820Sroot int fdes; 877820Sroot struct iovec *iovp; 8826474Skarels unsigned iovcnt; 8942922Smckusick } *uap; 9042922Smckusick int *retval; 9142922Smckusick { 9237728Smckusick register struct file *fp; 93*45914Smckusick register struct filedesc *fdp = p->p_fd; 947820Sroot struct uio auio; 9537728Smckusick register struct iovec *iov; 9644939Skarels struct iovec *saveiov; 9737728Smckusick struct iovec aiov[UIO_SMALLIOV]; 9837728Smckusick long i, cnt, error = 0; 9944939Skarels unsigned iovlen; 10037728Smckusick #ifdef KTRACE 10137728Smckusick struct iovec *ktriov = NULL; 10237728Smckusick #endif 1037820Sroot 104*45914Smckusick if (((unsigned)uap->fdes) >= fdp->fd_maxfiles || 105*45914Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL || 10637728Smckusick (fp->f_flag & FREAD) == 0) 10744405Skarels return (EBADF); 10844939Skarels /* note: can't use iovlen until iovcnt is validated */ 10944939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 11037127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 11137728Smckusick if (uap->iovcnt > UIO_MAXIOV) 11244405Skarels return (EINVAL); 11344939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 11444939Skarels saveiov = iov; 11537127Skarels } else 11637127Skarels iov = aiov; 11737127Skarels auio.uio_iov = iov; 1187820Sroot auio.uio_iovcnt = uap->iovcnt; 11937728Smckusick auio.uio_rw = UIO_READ; 12037728Smckusick auio.uio_segflg = UIO_USERSPACE; 12144939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 12237127Skarels goto done; 12337728Smckusick auio.uio_resid = 0; 12437728Smckusick for (i = 0; i < uap->iovcnt; i++) { 12537728Smckusick if (iov->iov_len < 0) { 12637728Smckusick error = EINVAL; 12737728Smckusick goto done; 12837728Smckusick } 12937728Smckusick auio.uio_resid += iov->iov_len; 13037728Smckusick if (auio.uio_resid < 0) { 13137728Smckusick error = EINVAL; 13237728Smckusick goto done; 13337728Smckusick } 13437728Smckusick iov++; 13537728Smckusick } 13637728Smckusick #ifdef KTRACE 13737728Smckusick /* 13837728Smckusick * if tracing, save a copy of iovec 13937728Smckusick */ 14042922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 14137728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 14237728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 14337728Smckusick } 14437728Smckusick #endif 14537728Smckusick cnt = auio.uio_resid; 14640703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 14740703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 14840703Skarels error == EINTR || error == EWOULDBLOCK)) 14940703Skarels error = 0; 15037728Smckusick cnt -= auio.uio_resid; 15137728Smckusick #ifdef KTRACE 15237728Smckusick if (ktriov != NULL) { 15341178Smarc if (error == 0) 15443448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 15543448Smckusick cnt, error); 15637728Smckusick FREE(ktriov, M_TEMP); 15737728Smckusick } 15837728Smckusick #endif 15942922Smckusick *retval = cnt; 16037127Skarels done: 16137728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 16244939Skarels FREE(saveiov, M_IOV); 16344405Skarels return (error); 1647423Sroot } 1657423Sroot 1667423Sroot /* 1677423Sroot * Write system call 1687423Sroot */ 16942922Smckusick write(p, uap, retval) 17042922Smckusick struct proc *p; 17142922Smckusick register struct args { 1727423Sroot int fdes; 1737423Sroot char *cbuf; 17426474Skarels unsigned count; 17542922Smckusick } *uap; 17642922Smckusick int *retval; 17742922Smckusick { 17837728Smckusick register struct file *fp; 179*45914Smckusick register struct filedesc *fdp = p->p_fd; 1807820Sroot struct uio auio; 1817820Sroot struct iovec aiov; 18237728Smckusick long cnt, error = 0; 18337728Smckusick #ifdef KTRACE 18437728Smckusick struct iovec ktriov; 18537728Smckusick #endif 1867423Sroot 187*45914Smckusick if (((unsigned)uap->fdes) >= fdp->fd_maxfiles || 188*45914Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL || 18937728Smckusick (fp->f_flag & FWRITE) == 0) 19044405Skarels return (EBADF); 19137728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 19237728Smckusick aiov.iov_len = uap->count; 1937820Sroot auio.uio_iov = &aiov; 1947820Sroot auio.uio_iovcnt = 1; 19537728Smckusick auio.uio_resid = uap->count; 19637728Smckusick auio.uio_rw = UIO_WRITE; 19737728Smckusick auio.uio_segflg = UIO_USERSPACE; 19837728Smckusick #ifdef KTRACE 19937728Smckusick /* 20037728Smckusick * if tracing, save a copy of iovec 20137728Smckusick */ 20242922Smckusick if (KTRPOINT(p, KTR_GENIO)) 20337728Smckusick ktriov = aiov; 20437728Smckusick #endif 20537728Smckusick cnt = uap->count; 20640703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 20740703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 20840703Skarels error == EINTR || error == EWOULDBLOCK)) 20940703Skarels error = 0; 21040703Skarels if (error == EPIPE) 21142922Smckusick psignal(p, SIGPIPE); 21240703Skarels } 21337728Smckusick cnt -= auio.uio_resid; 21437728Smckusick #ifdef KTRACE 21542922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 21642922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 21743448Smckusick &ktriov, cnt, error); 21837728Smckusick #endif 21942922Smckusick *retval = cnt; 22044405Skarels return (error); 2217820Sroot } 2227820Sroot 22342922Smckusick /* 22442922Smckusick * Gather write system call 22542922Smckusick */ 22642922Smckusick writev(p, uap, retval) 22742922Smckusick struct proc *p; 22842922Smckusick register struct args { 2297820Sroot int fdes; 2307820Sroot struct iovec *iovp; 23126474Skarels unsigned iovcnt; 23242922Smckusick } *uap; 23342922Smckusick int *retval; 23442922Smckusick { 23537728Smckusick register struct file *fp; 236*45914Smckusick register struct filedesc *fdp = p->p_fd; 2377820Sroot struct uio auio; 23837728Smckusick register struct iovec *iov; 23944939Skarels struct iovec *saveiov; 24037728Smckusick struct iovec aiov[UIO_SMALLIOV]; 24137728Smckusick long i, cnt, error = 0; 24244939Skarels unsigned iovlen; 24337728Smckusick #ifdef KTRACE 24437728Smckusick struct iovec *ktriov = NULL; 24537728Smckusick #endif 2467820Sroot 247*45914Smckusick if (((unsigned)uap->fdes) >= fdp->fd_maxfiles || 248*45914Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL || 24937728Smckusick (fp->f_flag & FWRITE) == 0) 25044405Skarels return (EBADF); 25144939Skarels /* note: can't use iovlen until iovcnt is validated */ 25244939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 25337127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 25437728Smckusick if (uap->iovcnt > UIO_MAXIOV) 25544405Skarels return (EINVAL); 25644939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 25744939Skarels saveiov = iov; 25837127Skarels } else 25937127Skarels iov = aiov; 26037127Skarels auio.uio_iov = iov; 2617820Sroot auio.uio_iovcnt = uap->iovcnt; 26237728Smckusick auio.uio_rw = UIO_WRITE; 26337728Smckusick auio.uio_segflg = UIO_USERSPACE; 26444939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 26537127Skarels goto done; 26637728Smckusick auio.uio_resid = 0; 26737728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2687820Sroot if (iov->iov_len < 0) { 26937728Smckusick error = EINVAL; 27037728Smckusick goto done; 2717820Sroot } 27237728Smckusick auio.uio_resid += iov->iov_len; 27337728Smckusick if (auio.uio_resid < 0) { 27437728Smckusick error = EINVAL; 27537728Smckusick goto done; 2767820Sroot } 27713270Ssam iov++; 2787820Sroot } 27937127Skarels #ifdef KTRACE 28037728Smckusick /* 28137728Smckusick * if tracing, save a copy of iovec 28237728Smckusick */ 28342922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 28437127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 28537728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 28637127Skarels } 28737127Skarels #endif 28837728Smckusick cnt = auio.uio_resid; 28940703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 29040703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 29140703Skarels error == EINTR || error == EWOULDBLOCK)) 29240703Skarels error = 0; 29340703Skarels if (error == EPIPE) 29442922Smckusick psignal(p, SIGPIPE); 29540703Skarels } 29637728Smckusick cnt -= auio.uio_resid; 29737127Skarels #ifdef KTRACE 29837127Skarels if (ktriov != NULL) { 29941178Smarc if (error == 0) 30042922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 30143448Smckusick ktriov, cnt, error); 30237127Skarels FREE(ktriov, M_TEMP); 30337127Skarels } 30437127Skarels #endif 30542922Smckusick *retval = cnt; 30637728Smckusick done: 30737728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 30844939Skarels FREE(saveiov, M_IOV); 30944405Skarels return (error); 3107423Sroot } 3117423Sroot 3127423Sroot /* 3137423Sroot * Ioctl system call 3147423Sroot */ 31542922Smckusick /* ARGSUSED */ 31642922Smckusick ioctl(p, uap, retval) 31742922Smckusick struct proc *p; 31842922Smckusick register struct args { 3197423Sroot int fdes; 3207423Sroot int cmd; 3217423Sroot caddr_t cmarg; 32242922Smckusick } *uap; 32342922Smckusick int *retval; 32442922Smckusick { 32542922Smckusick register struct file *fp; 326*45914Smckusick register struct filedesc *fdp = p->p_fd; 32740703Skarels register int com, error; 3287820Sroot register u_int size; 32931653Smckusick caddr_t memp = 0; 33030530Skarels #define STK_PARAMS 128 33133480Skarels char stkbuf[STK_PARAMS]; 33233480Skarels caddr_t data = stkbuf; 3337423Sroot 334*45914Smckusick if ((unsigned)uap->fdes >= fdp->fd_maxfiles || 335*45914Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL) 33644405Skarels return (EBADF); 33740703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 33844405Skarels return (EBADF); 3397624Ssam com = uap->cmd; 3407624Ssam 3417624Ssam if (com == FIOCLEX) { 342*45914Smckusick OFILEFLAGS(fdp, uap->fdes) |= UF_EXCLOSE; 34344405Skarels return (0); 3447423Sroot } 3457624Ssam if (com == FIONCLEX) { 346*45914Smckusick OFILEFLAGS(fdp, uap->fdes) &= ~UF_EXCLOSE; 34744405Skarels return (0); 3487423Sroot } 3497624Ssam 3507624Ssam /* 3517624Ssam * Interpret high order word to find 3527624Ssam * amount of data to be copied to/from the 3537624Ssam * user's address space. 3547624Ssam */ 35530530Skarels size = IOCPARM_LEN(com); 35640703Skarels if (size > IOCPARM_MAX) 35744405Skarels return (ENOTTY); 35833480Skarels if (size > sizeof (stkbuf)) { 35943383Smckusick memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 36031653Smckusick data = memp; 36130530Skarels } 36210601Ssam if (com&IOC_IN) { 36310601Ssam if (size) { 36440703Skarels error = copyin(uap->cmarg, data, (u_int)size); 36540703Skarels if (error) { 36631653Smckusick if (memp) 36731653Smckusick free(memp, M_IOCTLOPS); 36844405Skarels return (error); 36931653Smckusick } 37010601Ssam } else 37110601Ssam *(caddr_t *)data = uap->cmarg; 37210601Ssam } else if ((com&IOC_OUT) && size) 37310601Ssam /* 37437127Skarels * Zero the buffer so the user always 37537127Skarels * gets back something deterministic. 37610601Ssam */ 37730530Skarels bzero(data, size); 37811284Ssam else if (com&IOC_VOID) 37911284Ssam *(caddr_t *)data = uap->cmarg; 3807423Sroot 38112751Ssam switch (com) { 3827624Ssam 38312751Ssam case FIONBIO: 38440703Skarels error = fset(fp, FNDELAY, *(int *)data); 38530530Skarels break; 38612751Ssam 38712751Ssam case FIOASYNC: 38840703Skarels error = fset(fp, FASYNC, *(int *)data); 38930530Skarels break; 39012751Ssam 39112751Ssam case FIOSETOWN: 39240703Skarels error = fsetown(fp, *(int *)data); 39330530Skarels break; 39412751Ssam 39512751Ssam case FIOGETOWN: 39640703Skarels error = fgetown(fp, (int *)data); 39730530Skarels break; 39830530Skarels default: 39940703Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data); 40030530Skarels /* 40130530Skarels * Copy any data to user, size was 40230530Skarels * already set and checked above. 40330530Skarels */ 40440703Skarels if (error == 0 && (com&IOC_OUT) && size) 40540703Skarels error = copyout(data, uap->cmarg, (u_int)size); 40630530Skarels break; 4077423Sroot } 40831653Smckusick if (memp) 40931653Smckusick free(memp, M_IOCTLOPS); 41044405Skarels return (error); 4117423Sroot } 4127423Sroot 41312751Ssam int nselcoll; 41417593Skarels 4157423Sroot /* 41612751Ssam * Select system call. 4177423Sroot */ 41842922Smckusick select(p, uap, retval) 41942922Smckusick register struct proc *p; 42042922Smckusick register struct args { 42112751Ssam int nd; 42223523Skarels fd_set *in, *ou, *ex; 42312751Ssam struct timeval *tv; 42442922Smckusick } *uap; 42542922Smckusick int *retval; 42642922Smckusick { 42723523Skarels fd_set ibits[3], obits[3]; 42812751Ssam struct timeval atv; 42940703Skarels int s, ncoll, ni, error = 0, timo; 43012751Ssam 43126277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 43226277Skarels bzero((caddr_t)obits, sizeof(obits)); 433*45914Smckusick if (uap->nd > p->p_fd->fd_maxfiles) 434*45914Smckusick uap->nd = p->p_fd->fd_maxfiles; /* forgiving; slightly wrong */ 43523523Skarels ni = howmany(uap->nd, NFDBITS); 43612751Ssam 43712751Ssam #define getbits(name, x) \ 43812751Ssam if (uap->name) { \ 43940703Skarels error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 44026277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 44140703Skarels if (error) \ 44212751Ssam goto done; \ 44317593Skarels } 44412751Ssam getbits(in, 0); 44512751Ssam getbits(ou, 1); 44612751Ssam getbits(ex, 2); 44712751Ssam #undef getbits 44812751Ssam 44912751Ssam if (uap->tv) { 45040703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 45112751Ssam sizeof (atv)); 45240703Skarels if (error) 45312751Ssam goto done; 45412751Ssam if (itimerfix(&atv)) { 45540703Skarels error = EINVAL; 45612751Ssam goto done; 45712751Ssam } 45817934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 45940703Skarels timo = hzto(&atv); 46040703Skarels } else 46140703Skarels timo = 0; 46212751Ssam retry: 46312751Ssam ncoll = nselcoll; 46442922Smckusick p->p_flag |= SSEL; 465*45914Smckusick error = selscan(p->p_fd, ibits, obits, uap->nd, retval); 46642922Smckusick if (error || *retval) 46712751Ssam goto done; 46817934Skarels s = splhigh(); 46912971Ssam /* this should be timercmp(&time, &atv, >=) */ 47012971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 47112971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 47212751Ssam splx(s); 47312751Ssam goto done; 47412751Ssam } 47542922Smckusick if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { 47612751Ssam splx(s); 47712751Ssam goto retry; 47812751Ssam } 47942922Smckusick p->p_flag &= ~SSEL; 48040703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 48112751Ssam splx(s); 48240703Skarels if (error == 0) 48340703Skarels goto retry; 48412751Ssam done: 48542922Smckusick p->p_flag &= ~SSEL; 48640703Skarels /* select is not restarted after signals... */ 48740703Skarels if (error == ERESTART) 48840703Skarels error = EINTR; 48940703Skarels if (error == EWOULDBLOCK) 49040703Skarels error = 0; 49112751Ssam #define putbits(name, x) \ 49212751Ssam if (uap->name) { \ 49340703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 49426277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 49540703Skarels if (error2) \ 49640703Skarels error = error2; \ 49712751Ssam } 49840703Skarels if (error == 0) { 49921106Skarels putbits(in, 0); 50021106Skarels putbits(ou, 1); 50121106Skarels putbits(ex, 2); 50212751Ssam #undef putbits 50321106Skarels } 50444405Skarels return (error); 50512751Ssam } 50612751Ssam 507*45914Smckusick selscan(fdp, ibits, obits, nfd, retval) 508*45914Smckusick register struct filedesc *fdp; 50923523Skarels fd_set *ibits, *obits; 51042922Smckusick int nfd, *retval; 51112751Ssam { 51223523Skarels register int which, i, j; 51323523Skarels register fd_mask bits; 51412751Ssam int flag; 51512751Ssam struct file *fp; 51642922Smckusick int error = 0, n = 0; 51712751Ssam 51812751Ssam for (which = 0; which < 3; which++) { 51912751Ssam switch (which) { 52012751Ssam 52112751Ssam case 0: 52212751Ssam flag = FREAD; break; 52312751Ssam 52412751Ssam case 1: 52512751Ssam flag = FWRITE; break; 52612751Ssam 52712751Ssam case 2: 52812751Ssam flag = 0; break; 52912751Ssam } 53023523Skarels for (i = 0; i < nfd; i += NFDBITS) { 53123523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 53217593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 53317593Skarels bits &= ~(1 << j); 534*45914Smckusick fp = OFILE(fdp, i + j); 53517593Skarels if (fp == NULL) { 53642922Smckusick error = EBADF; 53717593Skarels break; 53817593Skarels } 53917593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 54023523Skarels FD_SET(i + j, &obits[which]); 54117593Skarels n++; 54217593Skarels } 54312751Ssam } 54412751Ssam } 54512751Ssam } 54642922Smckusick *retval = n; 54742922Smckusick return (error); 54812751Ssam } 54912751Ssam 5507423Sroot /*ARGSUSED*/ 55112751Ssam seltrue(dev, flag) 55212751Ssam dev_t dev; 55312751Ssam int flag; 5547423Sroot { 5557423Sroot 55612751Ssam return (1); 5577423Sroot } 5588103Sroot 55912751Ssam selwakeup(p, coll) 56012751Ssam register struct proc *p; 56112751Ssam int coll; 5628103Sroot { 5638103Sroot 56412751Ssam if (coll) { 56512751Ssam nselcoll++; 56612751Ssam wakeup((caddr_t)&selwait); 56712751Ssam } 56812751Ssam if (p) { 56917934Skarels int s = splhigh(); 57017270Skarels if (p->p_wchan == (caddr_t)&selwait) { 57117270Skarels if (p->p_stat == SSLEEP) 57217270Skarels setrun(p); 57317270Skarels else 57417270Skarels unsleep(p); 57517270Skarels } else if (p->p_flag & SSEL) 57612751Ssam p->p_flag &= ~SSEL; 57712751Ssam splx(s); 57812751Ssam } 5798103Sroot } 580