123384Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423384Smckusick * 537728Smckusick * Redistribution and use in source and binary forms are permitted 637728Smckusick * provided that the above copyright notice and this paragraph are 737728Smckusick * duplicated in all such forms and that any documentation, 837728Smckusick * advertising materials, and other materials related to such 937728Smckusick * distribution and use acknowledge that the software was developed 1037728Smckusick * by the University of California, Berkeley. The name of the 1137728Smckusick * University may not be used to endorse or promote products derived 1237728Smckusick * from this software without specific prior written permission. 1337728Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437728Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537728Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637728Smckusick * 17*42922Smckusick * @(#)sys_generic.c 7.17 (Berkeley) 06/05/90 1823384Smckusick */ 197423Sroot 2017094Sbloom #include "param.h" 2117094Sbloom #include "systm.h" 2237728Smckusick #include "syscontext.h" 2317094Sbloom #include "ioctl.h" 2417094Sbloom #include "file.h" 2517094Sbloom #include "proc.h" 2617094Sbloom #include "uio.h" 2717094Sbloom #include "kernel.h" 2817094Sbloom #include "stat.h" 2931653Smckusick #include "malloc.h" 3037127Skarels #ifdef KTRACE 3137127Skarels #include "ktrace.h" 3237127Skarels #endif 337423Sroot 347423Sroot /* 357423Sroot * Read system call. 367423Sroot */ 37*42922Smckusick read(p, uap, retval) 38*42922Smckusick struct proc *p; 39*42922Smckusick register struct args { 407423Sroot int fdes; 417423Sroot char *cbuf; 427423Sroot unsigned count; 43*42922Smckusick } *uap; 44*42922Smckusick int *retval; 45*42922Smckusick { 4637728Smckusick register struct file *fp; 477746Sroot struct uio auio; 487746Sroot struct iovec aiov; 4937728Smckusick long cnt, error = 0; 5037728Smckusick #ifdef KTRACE 5137728Smckusick struct iovec ktriov; 5237728Smckusick #endif 537423Sroot 5437728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 5537728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 5637728Smckusick (fp->f_flag & FREAD) == 0) 5737728Smckusick RETURN (EBADF); 587820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 597820Sroot aiov.iov_len = uap->count; 607820Sroot auio.uio_iov = &aiov; 617820Sroot auio.uio_iovcnt = 1; 6237728Smckusick auio.uio_resid = uap->count; 6337728Smckusick auio.uio_rw = UIO_READ; 6437728Smckusick auio.uio_segflg = UIO_USERSPACE; 6537728Smckusick #ifdef KTRACE 6637728Smckusick /* 6737728Smckusick * if tracing, save a copy of iovec 6837728Smckusick */ 69*42922Smckusick if (KTRPOINT(p, KTR_GENIO)) 7037728Smckusick ktriov = aiov; 7137728Smckusick #endif 7237728Smckusick cnt = uap->count; 7340703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 7440703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 7540703Skarels error == EINTR || error == EWOULDBLOCK)) 7640703Skarels error = 0; 7737728Smckusick cnt -= auio.uio_resid; 7837728Smckusick #ifdef KTRACE 79*42922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 80*42922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt); 8137728Smckusick #endif 82*42922Smckusick *retval = cnt; 8337728Smckusick RETURN (error); 847820Sroot } 857820Sroot 86*42922Smckusick /* 87*42922Smckusick * Scatter read system call. 88*42922Smckusick */ 89*42922Smckusick readv(p, uap, retval) 90*42922Smckusick struct proc *p; 91*42922Smckusick register struct args { 927820Sroot int fdes; 937820Sroot struct iovec *iovp; 9426474Skarels unsigned iovcnt; 95*42922Smckusick } *uap; 96*42922Smckusick int *retval; 97*42922Smckusick { 9837728Smckusick register struct file *fp; 997820Sroot struct uio auio; 10037728Smckusick register struct iovec *iov; 10137728Smckusick struct iovec aiov[UIO_SMALLIOV]; 10237728Smckusick long i, cnt, error = 0; 10337728Smckusick #ifdef KTRACE 10437728Smckusick struct iovec *ktriov = NULL; 10537728Smckusick #endif 1067820Sroot 10737728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 10837728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 10937728Smckusick (fp->f_flag & FREAD) == 0) 11037728Smckusick RETURN (EBADF); 11137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 11237728Smckusick if (uap->iovcnt > UIO_MAXIOV) 11337728Smckusick RETURN (EINVAL); 11437127Skarels MALLOC(iov, struct iovec *, 11537127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 11637127Skarels } else 11737127Skarels iov = aiov; 11837127Skarels auio.uio_iov = iov; 1197820Sroot auio.uio_iovcnt = uap->iovcnt; 12037728Smckusick auio.uio_rw = UIO_READ; 12137728Smckusick auio.uio_segflg = UIO_USERSPACE; 12237728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 12337728Smckusick uap->iovcnt * sizeof (struct iovec))) 12437127Skarels goto done; 12537728Smckusick auio.uio_resid = 0; 12637728Smckusick for (i = 0; i < uap->iovcnt; i++) { 12737728Smckusick if (iov->iov_len < 0) { 12837728Smckusick error = EINVAL; 12937728Smckusick goto done; 13037728Smckusick } 13137728Smckusick auio.uio_resid += iov->iov_len; 13237728Smckusick if (auio.uio_resid < 0) { 13337728Smckusick error = EINVAL; 13437728Smckusick goto done; 13537728Smckusick } 13637728Smckusick iov++; 13737728Smckusick } 13837728Smckusick #ifdef KTRACE 13937728Smckusick /* 14037728Smckusick * if tracing, save a copy of iovec 14137728Smckusick */ 142*42922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 14341990Smckusick unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); 14437728Smckusick 14537728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 14637728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 14737728Smckusick } 14837728Smckusick #endif 14937728Smckusick cnt = auio.uio_resid; 15040703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 15140703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 15240703Skarels error == EINTR || error == EWOULDBLOCK)) 15340703Skarels error = 0; 15437728Smckusick cnt -= auio.uio_resid; 15537728Smckusick #ifdef KTRACE 15637728Smckusick if (ktriov != NULL) { 15741178Smarc if (error == 0) 158*42922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, cnt); 15937728Smckusick FREE(ktriov, M_TEMP); 16037728Smckusick } 16137728Smckusick #endif 162*42922Smckusick *retval = cnt; 16337127Skarels done: 16437728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 16537127Skarels FREE(iov, M_IOV); 16637728Smckusick RETURN (error); 1677423Sroot } 1687423Sroot 1697423Sroot /* 1707423Sroot * Write system call 1717423Sroot */ 172*42922Smckusick write(p, uap, retval) 173*42922Smckusick struct proc *p; 174*42922Smckusick register struct args { 1757423Sroot int fdes; 1767423Sroot char *cbuf; 17726474Skarels unsigned count; 178*42922Smckusick } *uap; 179*42922Smckusick int *retval; 180*42922Smckusick { 18137728Smckusick register struct file *fp; 1827820Sroot struct uio auio; 1837820Sroot struct iovec aiov; 18437728Smckusick long cnt, error = 0; 18537728Smckusick #ifdef KTRACE 18637728Smckusick struct iovec ktriov; 18737728Smckusick #endif 1887423Sroot 18937728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 19037728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 19137728Smckusick (fp->f_flag & FWRITE) == 0) 19237728Smckusick RETURN (EBADF); 19337728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 19437728Smckusick aiov.iov_len = uap->count; 1957820Sroot auio.uio_iov = &aiov; 1967820Sroot auio.uio_iovcnt = 1; 19737728Smckusick auio.uio_resid = uap->count; 19837728Smckusick auio.uio_rw = UIO_WRITE; 19937728Smckusick auio.uio_segflg = UIO_USERSPACE; 20037728Smckusick #ifdef KTRACE 20137728Smckusick /* 20237728Smckusick * if tracing, save a copy of iovec 20337728Smckusick */ 204*42922Smckusick if (KTRPOINT(p, KTR_GENIO)) 20537728Smckusick ktriov = aiov; 20637728Smckusick #endif 20737728Smckusick cnt = uap->count; 20840703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 20940703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 21040703Skarels error == EINTR || error == EWOULDBLOCK)) 21140703Skarels error = 0; 21240703Skarels if (error == EPIPE) 213*42922Smckusick psignal(p, SIGPIPE); 21440703Skarels } 21537728Smckusick cnt -= auio.uio_resid; 21637728Smckusick #ifdef KTRACE 217*42922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 218*42922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 21938591Smarc &ktriov, cnt); 22037728Smckusick #endif 221*42922Smckusick *retval = cnt; 22237728Smckusick RETURN (error); 2237820Sroot } 2247820Sroot 225*42922Smckusick /* 226*42922Smckusick * Gather write system call 227*42922Smckusick */ 228*42922Smckusick writev(p, uap, retval) 229*42922Smckusick struct proc *p; 230*42922Smckusick register struct args { 2317820Sroot int fdes; 2327820Sroot struct iovec *iovp; 23326474Skarels unsigned iovcnt; 234*42922Smckusick } *uap; 235*42922Smckusick int *retval; 236*42922Smckusick { 23737728Smckusick register struct file *fp; 2387820Sroot struct uio auio; 23937728Smckusick register struct iovec *iov; 24037728Smckusick struct iovec aiov[UIO_SMALLIOV]; 24137728Smckusick long i, cnt, error = 0; 24237728Smckusick #ifdef KTRACE 24337728Smckusick struct iovec *ktriov = NULL; 24437728Smckusick #endif 2457820Sroot 24637728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 24737728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 24837728Smckusick (fp->f_flag & FWRITE) == 0) 24937728Smckusick RETURN (EBADF); 25037127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 25137728Smckusick if (uap->iovcnt > UIO_MAXIOV) 25237728Smckusick RETURN (EINVAL); 25337127Skarels MALLOC(iov, struct iovec *, 25437127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 25537127Skarels } else 25637127Skarels iov = aiov; 25737127Skarels auio.uio_iov = iov; 2587820Sroot auio.uio_iovcnt = uap->iovcnt; 25937728Smckusick auio.uio_rw = UIO_WRITE; 26037728Smckusick auio.uio_segflg = UIO_USERSPACE; 26137728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 26237728Smckusick uap->iovcnt * sizeof (struct iovec))) 26337127Skarels goto done; 26437728Smckusick auio.uio_resid = 0; 26537728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2667820Sroot if (iov->iov_len < 0) { 26737728Smckusick error = EINVAL; 26837728Smckusick goto done; 2697820Sroot } 27037728Smckusick auio.uio_resid += iov->iov_len; 27137728Smckusick if (auio.uio_resid < 0) { 27237728Smckusick error = EINVAL; 27337728Smckusick goto done; 2747820Sroot } 27513270Ssam iov++; 2767820Sroot } 27737127Skarels #ifdef KTRACE 27837728Smckusick /* 27937728Smckusick * if tracing, save a copy of iovec 28037728Smckusick */ 281*42922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 28241990Smckusick unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); 28337127Skarels 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) 294*42922Smckusick psignal(p, SIGPIPE); 29540703Skarels } 29637728Smckusick cnt -= auio.uio_resid; 29737127Skarels #ifdef KTRACE 29837127Skarels if (ktriov != NULL) { 29941178Smarc if (error == 0) 300*42922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 30141178Smarc ktriov, cnt); 30237127Skarels FREE(ktriov, M_TEMP); 30337127Skarels } 30437127Skarels #endif 305*42922Smckusick *retval = cnt; 30637728Smckusick done: 30737728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 30837728Smckusick FREE(iov, M_IOV); 30937728Smckusick RETURN (error); 3107423Sroot } 3117423Sroot 3127423Sroot /* 3137423Sroot * Ioctl system call 3147423Sroot */ 315*42922Smckusick /* ARGSUSED */ 316*42922Smckusick ioctl(p, uap, retval) 317*42922Smckusick struct proc *p; 318*42922Smckusick register struct args { 3197423Sroot int fdes; 3207423Sroot int cmd; 3217423Sroot caddr_t cmarg; 322*42922Smckusick } *uap; 323*42922Smckusick int *retval; 324*42922Smckusick { 325*42922Smckusick register struct file *fp; 32640703Skarels register int com, error; 3277820Sroot register u_int size; 32831653Smckusick caddr_t memp = 0; 32930530Skarels #define STK_PARAMS 128 33033480Skarels char stkbuf[STK_PARAMS]; 33133480Skarels caddr_t data = stkbuf; 3327423Sroot 33337728Smckusick if ((unsigned)uap->fdes >= NOFILE || 33437728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 33537728Smckusick RETURN (EBADF); 33640703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 33740703Skarels RETURN (EBADF); 3387624Ssam com = uap->cmd; 3397624Ssam 3407624Ssam if (com == FIOCLEX) { 3419592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 3427423Sroot return; 3437423Sroot } 3447624Ssam if (com == FIONCLEX) { 3459592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 34640703Skarels RETURN (0); 3477423Sroot } 3487624Ssam 3497624Ssam /* 3507624Ssam * Interpret high order word to find 3517624Ssam * amount of data to be copied to/from the 3527624Ssam * user's address space. 3537624Ssam */ 35430530Skarels size = IOCPARM_LEN(com); 35540703Skarels if (size > IOCPARM_MAX) 35640703Skarels RETURN (ENOTTY); 35733480Skarels if (size > sizeof (stkbuf)) { 35837127Skarels memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS, 35934473Smckusick 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); 36840703Skarels 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); 41040703Skarels RETURN (error); 4117423Sroot } 4127423Sroot 41312751Ssam int nselcoll; 41417593Skarels 4157423Sroot /* 41612751Ssam * Select system call. 4177423Sroot */ 418*42922Smckusick select(p, uap, retval) 419*42922Smckusick register struct proc *p; 420*42922Smckusick register struct args { 42112751Ssam int nd; 42223523Skarels fd_set *in, *ou, *ex; 42312751Ssam struct timeval *tv; 424*42922Smckusick } *uap; 425*42922Smckusick int *retval; 426*42922Smckusick { 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)); 43312751Ssam if (uap->nd > NOFILE) 43412751Ssam uap->nd = NOFILE; /* forgiving, if 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; 464*42922Smckusick p->p_flag |= SSEL; 465*42922Smckusick error = selscan(ibits, obits, uap->nd, retval); 46640703Skarels if (error == 0) 46740703Skarels error = u.u_error; /* XXX */ 468*42922Smckusick if (error || *retval) 46912751Ssam goto done; 47017934Skarels s = splhigh(); 47112971Ssam /* this should be timercmp(&time, &atv, >=) */ 47212971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 47312971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 47412751Ssam splx(s); 47512751Ssam goto done; 47612751Ssam } 477*42922Smckusick if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { 47812751Ssam splx(s); 47912751Ssam goto retry; 48012751Ssam } 481*42922Smckusick p->p_flag &= ~SSEL; 48240703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 48312751Ssam splx(s); 48440703Skarels if (error == 0) 48540703Skarels goto retry; 48612751Ssam done: 487*42922Smckusick p->p_flag &= ~SSEL; 48840703Skarels /* select is not restarted after signals... */ 48940703Skarels if (error == ERESTART) 49040703Skarels error = EINTR; 49140703Skarels if (error == EWOULDBLOCK) 49240703Skarels error = 0; 49312751Ssam #define putbits(name, x) \ 49412751Ssam if (uap->name) { \ 49540703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 49626277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 49740703Skarels if (error2) \ 49840703Skarels error = error2; \ 49912751Ssam } 50040703Skarels if (error == 0) { 50121106Skarels putbits(in, 0); 50221106Skarels putbits(ou, 1); 50321106Skarels putbits(ex, 2); 50412751Ssam #undef putbits 50521106Skarels } 50640703Skarels RETURN (error); 50712751Ssam } 50812751Ssam 509*42922Smckusick selscan(ibits, obits, nfd, retval) 51023523Skarels fd_set *ibits, *obits; 511*42922Smckusick int nfd, *retval; 51212751Ssam { 51323523Skarels register int which, i, j; 51423523Skarels register fd_mask bits; 51512751Ssam int flag; 51612751Ssam struct file *fp; 517*42922Smckusick int error = 0, n = 0; 51812751Ssam 51912751Ssam for (which = 0; which < 3; which++) { 52012751Ssam switch (which) { 52112751Ssam 52212751Ssam case 0: 52312751Ssam flag = FREAD; break; 52412751Ssam 52512751Ssam case 1: 52612751Ssam flag = FWRITE; break; 52712751Ssam 52812751Ssam case 2: 52912751Ssam flag = 0; break; 53012751Ssam } 53123523Skarels for (i = 0; i < nfd; i += NFDBITS) { 53223523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 53317593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 53417593Skarels bits &= ~(1 << j); 53517593Skarels fp = u.u_ofile[i + j]; 53617593Skarels if (fp == NULL) { 537*42922Smckusick error = EBADF; 53817593Skarels break; 53917593Skarels } 54017593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 54123523Skarels FD_SET(i + j, &obits[which]); 54217593Skarels n++; 54317593Skarels } 54412751Ssam } 54512751Ssam } 54612751Ssam } 547*42922Smckusick *retval = n; 548*42922Smckusick return (error); 54912751Ssam } 55012751Ssam 5517423Sroot /*ARGSUSED*/ 55212751Ssam seltrue(dev, flag) 55312751Ssam dev_t dev; 55412751Ssam int flag; 5557423Sroot { 5567423Sroot 55712751Ssam return (1); 5587423Sroot } 5598103Sroot 56012751Ssam selwakeup(p, coll) 56112751Ssam register struct proc *p; 56212751Ssam int coll; 5638103Sroot { 5648103Sroot 56512751Ssam if (coll) { 56612751Ssam nselcoll++; 56712751Ssam wakeup((caddr_t)&selwait); 56812751Ssam } 56912751Ssam if (p) { 57017934Skarels int s = splhigh(); 57117270Skarels if (p->p_wchan == (caddr_t)&selwait) { 57217270Skarels if (p->p_stat == SSLEEP) 57317270Skarels setrun(p); 57417270Skarels else 57517270Skarels unsleep(p); 57617270Skarels } else if (p->p_flag & SSEL) 57712751Ssam p->p_flag &= ~SSEL; 57812751Ssam splx(s); 57912751Ssam } 5808103Sroot } 581