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*41178Smarc * @(#)sys_generic.c 7.15 (Berkeley) 05/01/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 */ 377423Sroot read() 387423Sroot { 397423Sroot register struct a { 407423Sroot int fdes; 417423Sroot char *cbuf; 427423Sroot unsigned count; 437820Sroot } *uap = (struct a *)u.u_ap; 4437728Smckusick register struct file *fp; 457746Sroot struct uio auio; 467746Sroot struct iovec aiov; 4737728Smckusick long cnt, error = 0; 4837728Smckusick #ifdef KTRACE 4937728Smckusick struct iovec ktriov; 5037728Smckusick #endif 517423Sroot 5237728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 5337728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 5437728Smckusick (fp->f_flag & FREAD) == 0) 5537728Smckusick RETURN (EBADF); 5637728Smckusick if (uap->count < 0) 5737728Smckusick RETURN (EINVAL); 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 */ 6937728Smckusick if (KTRPOINT(u.u_procp, 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*41178Smarc if (KTRPOINT(u.u_procp, KTR_GENIO) && error == 0) 8038591Smarc ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt); 8137728Smckusick #endif 8237728Smckusick u.u_r.r_val1 = cnt; 8337728Smckusick RETURN (error); 847820Sroot } 857820Sroot 867820Sroot readv() 877820Sroot { 887820Sroot register struct a { 897820Sroot int fdes; 907820Sroot struct iovec *iovp; 9126474Skarels unsigned iovcnt; 927820Sroot } *uap = (struct a *)u.u_ap; 9337728Smckusick register struct file *fp; 947820Sroot struct uio auio; 9537728Smckusick register struct iovec *iov; 9637728Smckusick struct iovec aiov[UIO_SMALLIOV]; 9737728Smckusick long i, cnt, error = 0; 9837728Smckusick #ifdef KTRACE 9937728Smckusick struct iovec *ktriov = NULL; 10037728Smckusick #endif 1017820Sroot 10237728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 10337728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 10437728Smckusick (fp->f_flag & FREAD) == 0) 10537728Smckusick RETURN (EBADF); 10637127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 10737728Smckusick if (uap->iovcnt > UIO_MAXIOV) 10837728Smckusick RETURN (EINVAL); 10937127Skarels MALLOC(iov, struct iovec *, 11037127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 11137127Skarels } else 11237127Skarels iov = aiov; 11337127Skarels auio.uio_iov = iov; 1147820Sroot auio.uio_iovcnt = uap->iovcnt; 11537728Smckusick auio.uio_rw = UIO_READ; 11637728Smckusick auio.uio_segflg = UIO_USERSPACE; 11737728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 11837728Smckusick uap->iovcnt * sizeof (struct iovec))) 11937127Skarels goto done; 12037728Smckusick auio.uio_resid = 0; 12137728Smckusick for (i = 0; i < uap->iovcnt; i++) { 12237728Smckusick if (iov->iov_len < 0) { 12337728Smckusick error = EINVAL; 12437728Smckusick goto done; 12537728Smckusick } 12637728Smckusick auio.uio_resid += iov->iov_len; 12737728Smckusick if (auio.uio_resid < 0) { 12837728Smckusick error = EINVAL; 12937728Smckusick goto done; 13037728Smckusick } 13137728Smckusick iov++; 13237728Smckusick } 13337728Smckusick #ifdef KTRACE 13437728Smckusick /* 13537728Smckusick * if tracing, save a copy of iovec 13637728Smckusick */ 13737728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) { 13837728Smckusick int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 13937728Smckusick 14037728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 14137728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 14237728Smckusick } 14337728Smckusick #endif 14437728Smckusick cnt = auio.uio_resid; 14540703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 14640703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 14740703Skarels error == EINTR || error == EWOULDBLOCK)) 14840703Skarels error = 0; 14937728Smckusick cnt -= auio.uio_resid; 15037728Smckusick #ifdef KTRACE 15137728Smckusick if (ktriov != NULL) { 152*41178Smarc if (error == 0) 153*41178Smarc ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, 154*41178Smarc ktriov, cnt); 15537728Smckusick FREE(ktriov, M_TEMP); 15637728Smckusick } 15737728Smckusick #endif 15837728Smckusick u.u_r.r_val1 = cnt; 15937127Skarels done: 16037728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 16137127Skarels FREE(iov, M_IOV); 16237728Smckusick RETURN (error); 1637423Sroot } 1647423Sroot 1657423Sroot /* 1667423Sroot * Write system call 1677423Sroot */ 1687423Sroot write() 1697423Sroot { 1707423Sroot register struct a { 1717423Sroot int fdes; 1727423Sroot char *cbuf; 17326474Skarels unsigned count; 1747820Sroot } *uap = (struct a *)u.u_ap; 17537728Smckusick register struct file *fp; 1767820Sroot struct uio auio; 1777820Sroot struct iovec aiov; 17837728Smckusick long cnt, error = 0; 17937728Smckusick #ifdef KTRACE 18037728Smckusick struct iovec ktriov; 18137728Smckusick #endif 1827423Sroot 18337728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 18437728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 18537728Smckusick (fp->f_flag & FWRITE) == 0) 18637728Smckusick RETURN (EBADF); 18737728Smckusick if (uap->count < 0) 18837728Smckusick RETURN (EINVAL); 18937728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 19037728Smckusick aiov.iov_len = uap->count; 1917820Sroot auio.uio_iov = &aiov; 1927820Sroot auio.uio_iovcnt = 1; 19337728Smckusick auio.uio_resid = uap->count; 19437728Smckusick auio.uio_rw = UIO_WRITE; 19537728Smckusick auio.uio_segflg = UIO_USERSPACE; 19637728Smckusick #ifdef KTRACE 19737728Smckusick /* 19837728Smckusick * if tracing, save a copy of iovec 19937728Smckusick */ 20037728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 20137728Smckusick ktriov = aiov; 20237728Smckusick #endif 20337728Smckusick cnt = uap->count; 20440703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 20540703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 20640703Skarels error == EINTR || error == EWOULDBLOCK)) 20740703Skarels error = 0; 20840703Skarels if (error == EPIPE) 20940703Skarels psignal(u.u_procp, SIGPIPE); 21040703Skarels } 21137728Smckusick cnt -= auio.uio_resid; 21237728Smckusick #ifdef KTRACE 213*41178Smarc if (KTRPOINT(u.u_procp, KTR_GENIO) && error == 0) 21437728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 21538591Smarc &ktriov, cnt); 21637728Smckusick #endif 21737728Smckusick u.u_r.r_val1 = cnt; 21837728Smckusick RETURN (error); 2197820Sroot } 2207820Sroot 2217820Sroot writev() 2227820Sroot { 2237820Sroot register struct a { 2247820Sroot int fdes; 2257820Sroot struct iovec *iovp; 22626474Skarels unsigned iovcnt; 2277820Sroot } *uap = (struct a *)u.u_ap; 22837728Smckusick register struct file *fp; 2297820Sroot struct uio auio; 23037728Smckusick register struct iovec *iov; 23137728Smckusick struct iovec aiov[UIO_SMALLIOV]; 23237728Smckusick long i, cnt, error = 0; 23337728Smckusick #ifdef KTRACE 23437728Smckusick struct iovec *ktriov = NULL; 23537728Smckusick #endif 2367820Sroot 23737728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 23837728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 23937728Smckusick (fp->f_flag & FWRITE) == 0) 24037728Smckusick RETURN (EBADF); 24137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 24237728Smckusick if (uap->iovcnt > UIO_MAXIOV) 24337728Smckusick RETURN (EINVAL); 24437127Skarels MALLOC(iov, struct iovec *, 24537127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 24637127Skarels } else 24737127Skarels iov = aiov; 24837127Skarels auio.uio_iov = iov; 2497820Sroot auio.uio_iovcnt = uap->iovcnt; 25037728Smckusick auio.uio_rw = UIO_WRITE; 25137728Smckusick auio.uio_segflg = UIO_USERSPACE; 25237728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 25337728Smckusick uap->iovcnt * sizeof (struct iovec))) 25437127Skarels goto done; 25537728Smckusick auio.uio_resid = 0; 25637728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2577820Sroot if (iov->iov_len < 0) { 25837728Smckusick error = EINVAL; 25937728Smckusick goto done; 2607820Sroot } 26137728Smckusick auio.uio_resid += iov->iov_len; 26237728Smckusick if (auio.uio_resid < 0) { 26337728Smckusick error = EINVAL; 26437728Smckusick goto done; 2657820Sroot } 26613270Ssam iov++; 2677820Sroot } 26837127Skarels #ifdef KTRACE 26937728Smckusick /* 27037728Smckusick * if tracing, save a copy of iovec 27137728Smckusick */ 27237127Skarels if (KTRPOINT(u.u_procp, KTR_GENIO)) { 27337728Smckusick int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 27437127Skarels 27537127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 27637728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 27737127Skarels } 27837127Skarels #endif 27937728Smckusick cnt = auio.uio_resid; 28040703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 28140703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 28240703Skarels error == EINTR || error == EWOULDBLOCK)) 28340703Skarels error = 0; 28440703Skarels if (error == EPIPE) 28540703Skarels psignal(u.u_procp, SIGPIPE); 28640703Skarels } 28737728Smckusick cnt -= auio.uio_resid; 28837127Skarels #ifdef KTRACE 28937127Skarels if (ktriov != NULL) { 290*41178Smarc if (error == 0) 291*41178Smarc ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 292*41178Smarc ktriov, cnt); 29337127Skarels FREE(ktriov, M_TEMP); 29437127Skarels } 29537127Skarels #endif 29637728Smckusick u.u_r.r_val1 = cnt; 29737728Smckusick done: 29837728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 29937728Smckusick FREE(iov, M_IOV); 30037728Smckusick RETURN (error); 3017423Sroot } 3027423Sroot 3037423Sroot /* 3047423Sroot * Ioctl system call 3057423Sroot */ 3067423Sroot ioctl() 3077423Sroot { 3087423Sroot register struct file *fp; 3097624Ssam struct a { 3107423Sroot int fdes; 3117423Sroot int cmd; 3127423Sroot caddr_t cmarg; 31337728Smckusick } *uap = (struct a *)u.u_ap; 31440703Skarels register int com, error; 3157820Sroot register u_int size; 31631653Smckusick caddr_t memp = 0; 31730530Skarels #define STK_PARAMS 128 31833480Skarels char stkbuf[STK_PARAMS]; 31933480Skarels caddr_t data = stkbuf; 3207423Sroot 32137728Smckusick if ((unsigned)uap->fdes >= NOFILE || 32237728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 32337728Smckusick RETURN (EBADF); 32440703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 32540703Skarels RETURN (EBADF); 3267624Ssam com = uap->cmd; 3277624Ssam 3287624Ssam if (com == FIOCLEX) { 3299592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 3307423Sroot return; 3317423Sroot } 3327624Ssam if (com == FIONCLEX) { 3339592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 33440703Skarels RETURN (0); 3357423Sroot } 3367624Ssam 3377624Ssam /* 3387624Ssam * Interpret high order word to find 3397624Ssam * amount of data to be copied to/from the 3407624Ssam * user's address space. 3417624Ssam */ 34230530Skarels size = IOCPARM_LEN(com); 34340703Skarels if (size > IOCPARM_MAX) 34440703Skarels RETURN (ENOTTY); 34533480Skarels if (size > sizeof (stkbuf)) { 34637127Skarels memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS, 34734473Smckusick M_WAITOK); 34831653Smckusick data = memp; 34930530Skarels } 35010601Ssam if (com&IOC_IN) { 35110601Ssam if (size) { 35240703Skarels error = copyin(uap->cmarg, data, (u_int)size); 35340703Skarels if (error) { 35431653Smckusick if (memp) 35531653Smckusick free(memp, M_IOCTLOPS); 35640703Skarels RETURN (error); 35731653Smckusick } 35810601Ssam } else 35910601Ssam *(caddr_t *)data = uap->cmarg; 36010601Ssam } else if ((com&IOC_OUT) && size) 36110601Ssam /* 36237127Skarels * Zero the buffer so the user always 36337127Skarels * gets back something deterministic. 36410601Ssam */ 36530530Skarels bzero(data, size); 36611284Ssam else if (com&IOC_VOID) 36711284Ssam *(caddr_t *)data = uap->cmarg; 3687423Sroot 36912751Ssam switch (com) { 3707624Ssam 37112751Ssam case FIONBIO: 37240703Skarels error = fset(fp, FNDELAY, *(int *)data); 37330530Skarels break; 37412751Ssam 37512751Ssam case FIOASYNC: 37640703Skarels error = fset(fp, FASYNC, *(int *)data); 37730530Skarels break; 37812751Ssam 37912751Ssam case FIOSETOWN: 38040703Skarels error = fsetown(fp, *(int *)data); 38130530Skarels break; 38212751Ssam 38312751Ssam case FIOGETOWN: 38440703Skarels error = fgetown(fp, (int *)data); 38530530Skarels break; 38630530Skarels default: 38740703Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data); 38830530Skarels /* 38930530Skarels * Copy any data to user, size was 39030530Skarels * already set and checked above. 39130530Skarels */ 39240703Skarels if (error == 0 && (com&IOC_OUT) && size) 39340703Skarels error = copyout(data, uap->cmarg, (u_int)size); 39430530Skarels break; 3957423Sroot } 39631653Smckusick if (memp) 39731653Smckusick free(memp, M_IOCTLOPS); 39840703Skarels RETURN (error); 3997423Sroot } 4007423Sroot 40112751Ssam int nselcoll; 40217593Skarels 4037423Sroot /* 40412751Ssam * Select system call. 4057423Sroot */ 40612751Ssam select() 40712751Ssam { 40812751Ssam register struct uap { 40912751Ssam int nd; 41023523Skarels fd_set *in, *ou, *ex; 41112751Ssam struct timeval *tv; 41212751Ssam } *uap = (struct uap *)u.u_ap; 41323523Skarels fd_set ibits[3], obits[3]; 41412751Ssam struct timeval atv; 41540703Skarels int s, ncoll, ni, error = 0, timo; 41612751Ssam 41726277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 41826277Skarels bzero((caddr_t)obits, sizeof(obits)); 41912751Ssam if (uap->nd > NOFILE) 42012751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 42123523Skarels ni = howmany(uap->nd, NFDBITS); 42212751Ssam 42312751Ssam #define getbits(name, x) \ 42412751Ssam if (uap->name) { \ 42540703Skarels error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 42626277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 42740703Skarels if (error) \ 42812751Ssam goto done; \ 42917593Skarels } 43012751Ssam getbits(in, 0); 43112751Ssam getbits(ou, 1); 43212751Ssam getbits(ex, 2); 43312751Ssam #undef getbits 43412751Ssam 43512751Ssam if (uap->tv) { 43640703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 43712751Ssam sizeof (atv)); 43840703Skarels if (error) 43912751Ssam goto done; 44012751Ssam if (itimerfix(&atv)) { 44140703Skarels error = EINVAL; 44212751Ssam goto done; 44312751Ssam } 44417934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 44540703Skarels timo = hzto(&atv); 44640703Skarels } else 44740703Skarels timo = 0; 44812751Ssam retry: 44912751Ssam ncoll = nselcoll; 45012751Ssam u.u_procp->p_flag |= SSEL; 45140703Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd, &error); 45240703Skarels if (error == 0) 45340703Skarels error = u.u_error; /* XXX */ 45440703Skarels if (error || u.u_r.r_val1) 45512751Ssam goto done; 45617934Skarels s = splhigh(); 45712971Ssam /* this should be timercmp(&time, &atv, >=) */ 45812971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 45912971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 46012751Ssam splx(s); 46112751Ssam goto done; 46212751Ssam } 46312751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 46412751Ssam splx(s); 46512751Ssam goto retry; 46612751Ssam } 46712751Ssam u.u_procp->p_flag &= ~SSEL; 46840703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 46912751Ssam splx(s); 47040703Skarels if (error == 0) 47140703Skarels goto retry; 47212751Ssam done: 47333712Skarels u.u_procp->p_flag &= ~SSEL; 47440703Skarels /* select is not restarted after signals... */ 47540703Skarels if (error == ERESTART) 47640703Skarels error = EINTR; 47740703Skarels if (error == EWOULDBLOCK) 47840703Skarels error = 0; 47912751Ssam #define putbits(name, x) \ 48012751Ssam if (uap->name) { \ 48140703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 48226277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 48340703Skarels if (error2) \ 48440703Skarels error = error2; \ 48512751Ssam } 48640703Skarels if (error == 0) { 48721106Skarels putbits(in, 0); 48821106Skarels putbits(ou, 1); 48921106Skarels putbits(ex, 2); 49012751Ssam #undef putbits 49121106Skarels } 49240703Skarels RETURN (error); 49312751Ssam } 49412751Ssam 49540703Skarels selscan(ibits, obits, nfd, errp) 49623523Skarels fd_set *ibits, *obits; 49740703Skarels int nfd, *errp; 49812751Ssam { 49923523Skarels register int which, i, j; 50023523Skarels register fd_mask bits; 50112751Ssam int flag; 50212751Ssam struct file *fp; 50312751Ssam int n = 0; 50412751Ssam 50512751Ssam for (which = 0; which < 3; which++) { 50612751Ssam switch (which) { 50712751Ssam 50812751Ssam case 0: 50912751Ssam flag = FREAD; break; 51012751Ssam 51112751Ssam case 1: 51212751Ssam flag = FWRITE; break; 51312751Ssam 51412751Ssam case 2: 51512751Ssam flag = 0; break; 51612751Ssam } 51723523Skarels for (i = 0; i < nfd; i += NFDBITS) { 51823523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 51917593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 52017593Skarels bits &= ~(1 << j); 52117593Skarels fp = u.u_ofile[i + j]; 52217593Skarels if (fp == NULL) { 52340703Skarels *errp = EBADF; 52417593Skarels break; 52517593Skarels } 52617593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 52723523Skarels FD_SET(i + j, &obits[which]); 52817593Skarels n++; 52917593Skarels } 53012751Ssam } 53112751Ssam } 53212751Ssam } 53312751Ssam return (n); 53412751Ssam } 53512751Ssam 5367423Sroot /*ARGSUSED*/ 53712751Ssam seltrue(dev, flag) 53812751Ssam dev_t dev; 53912751Ssam int flag; 5407423Sroot { 5417423Sroot 54212751Ssam return (1); 5437423Sroot } 5448103Sroot 54512751Ssam selwakeup(p, coll) 54612751Ssam register struct proc *p; 54712751Ssam int coll; 5488103Sroot { 5498103Sroot 55012751Ssam if (coll) { 55112751Ssam nselcoll++; 55212751Ssam wakeup((caddr_t)&selwait); 55312751Ssam } 55412751Ssam if (p) { 55517934Skarels int s = splhigh(); 55617270Skarels if (p->p_wchan == (caddr_t)&selwait) { 55717270Skarels if (p->p_stat == SSLEEP) 55817270Skarels setrun(p); 55917270Skarels else 56017270Skarels unsleep(p); 56117270Skarels } else if (p->p_flag & SSEL) 56212751Ssam p->p_flag &= ~SSEL; 56312751Ssam splx(s); 56412751Ssam } 5658103Sroot } 566