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*40703Skarels * @(#)sys_generic.c 7.14 (Berkeley) 04/03/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; 73*40703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 74*40703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 75*40703Skarels error == EINTR || error == EWOULDBLOCK)) 76*40703Skarels error = 0; 7737728Smckusick cnt -= auio.uio_resid; 7837728Smckusick #ifdef KTRACE 7937728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 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; 145*40703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 146*40703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 147*40703Skarels error == EINTR || error == EWOULDBLOCK)) 148*40703Skarels error = 0; 14937728Smckusick cnt -= auio.uio_resid; 15037728Smckusick #ifdef KTRACE 15137728Smckusick if (ktriov != NULL) { 15237728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, ktriov, cnt); 15337728Smckusick FREE(ktriov, M_TEMP); 15437728Smckusick } 15537728Smckusick #endif 15637728Smckusick u.u_r.r_val1 = cnt; 15737127Skarels done: 15837728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 15937127Skarels FREE(iov, M_IOV); 16037728Smckusick RETURN (error); 1617423Sroot } 1627423Sroot 1637423Sroot /* 1647423Sroot * Write system call 1657423Sroot */ 1667423Sroot write() 1677423Sroot { 1687423Sroot register struct a { 1697423Sroot int fdes; 1707423Sroot char *cbuf; 17126474Skarels unsigned count; 1727820Sroot } *uap = (struct a *)u.u_ap; 17337728Smckusick register struct file *fp; 1747820Sroot struct uio auio; 1757820Sroot struct iovec aiov; 17637728Smckusick long cnt, error = 0; 17737728Smckusick #ifdef KTRACE 17837728Smckusick struct iovec ktriov; 17937728Smckusick #endif 1807423Sroot 18137728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 18237728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 18337728Smckusick (fp->f_flag & FWRITE) == 0) 18437728Smckusick RETURN (EBADF); 18537728Smckusick if (uap->count < 0) 18637728Smckusick RETURN (EINVAL); 18737728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 18837728Smckusick aiov.iov_len = uap->count; 1897820Sroot auio.uio_iov = &aiov; 1907820Sroot auio.uio_iovcnt = 1; 19137728Smckusick auio.uio_resid = uap->count; 19237728Smckusick auio.uio_rw = UIO_WRITE; 19337728Smckusick auio.uio_segflg = UIO_USERSPACE; 19437728Smckusick #ifdef KTRACE 19537728Smckusick /* 19637728Smckusick * if tracing, save a copy of iovec 19737728Smckusick */ 19837728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 19937728Smckusick ktriov = aiov; 20037728Smckusick #endif 20137728Smckusick cnt = uap->count; 202*40703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 203*40703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 204*40703Skarels error == EINTR || error == EWOULDBLOCK)) 205*40703Skarels error = 0; 206*40703Skarels if (error == EPIPE) 207*40703Skarels psignal(u.u_procp, SIGPIPE); 208*40703Skarels } 20937728Smckusick cnt -= auio.uio_resid; 21037728Smckusick #ifdef KTRACE 21137728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 21237728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 21338591Smarc &ktriov, cnt); 21437728Smckusick #endif 21537728Smckusick u.u_r.r_val1 = cnt; 21637728Smckusick RETURN (error); 2177820Sroot } 2187820Sroot 2197820Sroot writev() 2207820Sroot { 2217820Sroot register struct a { 2227820Sroot int fdes; 2237820Sroot struct iovec *iovp; 22426474Skarels unsigned iovcnt; 2257820Sroot } *uap = (struct a *)u.u_ap; 22637728Smckusick register struct file *fp; 2277820Sroot struct uio auio; 22837728Smckusick register struct iovec *iov; 22937728Smckusick struct iovec aiov[UIO_SMALLIOV]; 23037728Smckusick long i, cnt, error = 0; 23137728Smckusick #ifdef KTRACE 23237728Smckusick struct iovec *ktriov = NULL; 23337728Smckusick #endif 2347820Sroot 23537728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 23637728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 23737728Smckusick (fp->f_flag & FWRITE) == 0) 23837728Smckusick RETURN (EBADF); 23937127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 24037728Smckusick if (uap->iovcnt > UIO_MAXIOV) 24137728Smckusick RETURN (EINVAL); 24237127Skarels MALLOC(iov, struct iovec *, 24337127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 24437127Skarels } else 24537127Skarels iov = aiov; 24637127Skarels auio.uio_iov = iov; 2477820Sroot auio.uio_iovcnt = uap->iovcnt; 24837728Smckusick auio.uio_rw = UIO_WRITE; 24937728Smckusick auio.uio_segflg = UIO_USERSPACE; 25037728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 25137728Smckusick uap->iovcnt * sizeof (struct iovec))) 25237127Skarels goto done; 25337728Smckusick auio.uio_resid = 0; 25437728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2557820Sroot if (iov->iov_len < 0) { 25637728Smckusick error = EINVAL; 25737728Smckusick goto done; 2587820Sroot } 25937728Smckusick auio.uio_resid += iov->iov_len; 26037728Smckusick if (auio.uio_resid < 0) { 26137728Smckusick error = EINVAL; 26237728Smckusick goto done; 2637820Sroot } 26413270Ssam iov++; 2657820Sroot } 26637127Skarels #ifdef KTRACE 26737728Smckusick /* 26837728Smckusick * if tracing, save a copy of iovec 26937728Smckusick */ 27037127Skarels if (KTRPOINT(u.u_procp, KTR_GENIO)) { 27137728Smckusick int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 27237127Skarels 27337127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 27437728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 27537127Skarels } 27637127Skarels #endif 27737728Smckusick cnt = auio.uio_resid; 278*40703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 279*40703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 280*40703Skarels error == EINTR || error == EWOULDBLOCK)) 281*40703Skarels error = 0; 282*40703Skarels if (error == EPIPE) 283*40703Skarels psignal(u.u_procp, SIGPIPE); 284*40703Skarels } 28537728Smckusick cnt -= auio.uio_resid; 28637127Skarels #ifdef KTRACE 28737127Skarels if (ktriov != NULL) { 28837728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 28937728Smckusick ktriov, cnt); 29037127Skarels FREE(ktriov, M_TEMP); 29137127Skarels } 29237127Skarels #endif 29337728Smckusick u.u_r.r_val1 = cnt; 29437728Smckusick done: 29537728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 29637728Smckusick FREE(iov, M_IOV); 29737728Smckusick RETURN (error); 2987423Sroot } 2997423Sroot 3007423Sroot /* 3017423Sroot * Ioctl system call 3027423Sroot */ 3037423Sroot ioctl() 3047423Sroot { 3057423Sroot register struct file *fp; 3067624Ssam struct a { 3077423Sroot int fdes; 3087423Sroot int cmd; 3097423Sroot caddr_t cmarg; 31037728Smckusick } *uap = (struct a *)u.u_ap; 311*40703Skarels register int com, error; 3127820Sroot register u_int size; 31331653Smckusick caddr_t memp = 0; 31430530Skarels #define STK_PARAMS 128 31533480Skarels char stkbuf[STK_PARAMS]; 31633480Skarels caddr_t data = stkbuf; 3177423Sroot 31837728Smckusick if ((unsigned)uap->fdes >= NOFILE || 31937728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 32037728Smckusick RETURN (EBADF); 321*40703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 322*40703Skarels RETURN (EBADF); 3237624Ssam com = uap->cmd; 3247624Ssam 3257624Ssam if (com == FIOCLEX) { 3269592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 3277423Sroot return; 3287423Sroot } 3297624Ssam if (com == FIONCLEX) { 3309592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 331*40703Skarels RETURN (0); 3327423Sroot } 3337624Ssam 3347624Ssam /* 3357624Ssam * Interpret high order word to find 3367624Ssam * amount of data to be copied to/from the 3377624Ssam * user's address space. 3387624Ssam */ 33930530Skarels size = IOCPARM_LEN(com); 340*40703Skarels if (size > IOCPARM_MAX) 341*40703Skarels RETURN (ENOTTY); 34233480Skarels if (size > sizeof (stkbuf)) { 34337127Skarels memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS, 34434473Smckusick M_WAITOK); 34531653Smckusick data = memp; 34630530Skarels } 34710601Ssam if (com&IOC_IN) { 34810601Ssam if (size) { 349*40703Skarels error = copyin(uap->cmarg, data, (u_int)size); 350*40703Skarels if (error) { 35131653Smckusick if (memp) 35231653Smckusick free(memp, M_IOCTLOPS); 353*40703Skarels RETURN (error); 35431653Smckusick } 35510601Ssam } else 35610601Ssam *(caddr_t *)data = uap->cmarg; 35710601Ssam } else if ((com&IOC_OUT) && size) 35810601Ssam /* 35937127Skarels * Zero the buffer so the user always 36037127Skarels * gets back something deterministic. 36110601Ssam */ 36230530Skarels bzero(data, size); 36311284Ssam else if (com&IOC_VOID) 36411284Ssam *(caddr_t *)data = uap->cmarg; 3657423Sroot 36612751Ssam switch (com) { 3677624Ssam 36812751Ssam case FIONBIO: 369*40703Skarels error = fset(fp, FNDELAY, *(int *)data); 37030530Skarels break; 37112751Ssam 37212751Ssam case FIOASYNC: 373*40703Skarels error = fset(fp, FASYNC, *(int *)data); 37430530Skarels break; 37512751Ssam 37612751Ssam case FIOSETOWN: 377*40703Skarels error = fsetown(fp, *(int *)data); 37830530Skarels break; 37912751Ssam 38012751Ssam case FIOGETOWN: 381*40703Skarels error = fgetown(fp, (int *)data); 38230530Skarels break; 38330530Skarels default: 384*40703Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data); 38530530Skarels /* 38630530Skarels * Copy any data to user, size was 38730530Skarels * already set and checked above. 38830530Skarels */ 389*40703Skarels if (error == 0 && (com&IOC_OUT) && size) 390*40703Skarels error = copyout(data, uap->cmarg, (u_int)size); 39130530Skarels break; 3927423Sroot } 39331653Smckusick if (memp) 39431653Smckusick free(memp, M_IOCTLOPS); 395*40703Skarels RETURN (error); 3967423Sroot } 3977423Sroot 39812751Ssam int nselcoll; 39917593Skarels 4007423Sroot /* 40112751Ssam * Select system call. 4027423Sroot */ 40312751Ssam select() 40412751Ssam { 40512751Ssam register struct uap { 40612751Ssam int nd; 40723523Skarels fd_set *in, *ou, *ex; 40812751Ssam struct timeval *tv; 40912751Ssam } *uap = (struct uap *)u.u_ap; 41023523Skarels fd_set ibits[3], obits[3]; 41112751Ssam struct timeval atv; 412*40703Skarels int s, ncoll, ni, error = 0, timo; 41312751Ssam 41426277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 41526277Skarels bzero((caddr_t)obits, sizeof(obits)); 41612751Ssam if (uap->nd > NOFILE) 41712751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 41823523Skarels ni = howmany(uap->nd, NFDBITS); 41912751Ssam 42012751Ssam #define getbits(name, x) \ 42112751Ssam if (uap->name) { \ 422*40703Skarels error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 42326277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 424*40703Skarels if (error) \ 42512751Ssam goto done; \ 42617593Skarels } 42712751Ssam getbits(in, 0); 42812751Ssam getbits(ou, 1); 42912751Ssam getbits(ex, 2); 43012751Ssam #undef getbits 43112751Ssam 43212751Ssam if (uap->tv) { 433*40703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 43412751Ssam sizeof (atv)); 435*40703Skarels if (error) 43612751Ssam goto done; 43712751Ssam if (itimerfix(&atv)) { 438*40703Skarels error = EINVAL; 43912751Ssam goto done; 44012751Ssam } 44117934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 442*40703Skarels timo = hzto(&atv); 443*40703Skarels } else 444*40703Skarels timo = 0; 44512751Ssam retry: 44612751Ssam ncoll = nselcoll; 44712751Ssam u.u_procp->p_flag |= SSEL; 448*40703Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd, &error); 449*40703Skarels if (error == 0) 450*40703Skarels error = u.u_error; /* XXX */ 451*40703Skarels if (error || u.u_r.r_val1) 45212751Ssam goto done; 45317934Skarels s = splhigh(); 45412971Ssam /* this should be timercmp(&time, &atv, >=) */ 45512971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 45612971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 45712751Ssam splx(s); 45812751Ssam goto done; 45912751Ssam } 46012751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 46112751Ssam splx(s); 46212751Ssam goto retry; 46312751Ssam } 46412751Ssam u.u_procp->p_flag &= ~SSEL; 465*40703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 46612751Ssam splx(s); 467*40703Skarels if (error == 0) 468*40703Skarels goto retry; 46912751Ssam done: 47033712Skarels u.u_procp->p_flag &= ~SSEL; 471*40703Skarels /* select is not restarted after signals... */ 472*40703Skarels if (error == ERESTART) 473*40703Skarels error = EINTR; 474*40703Skarels if (error == EWOULDBLOCK) 475*40703Skarels error = 0; 47612751Ssam #define putbits(name, x) \ 47712751Ssam if (uap->name) { \ 478*40703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 47926277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 480*40703Skarels if (error2) \ 481*40703Skarels error = error2; \ 48212751Ssam } 483*40703Skarels if (error == 0) { 48421106Skarels putbits(in, 0); 48521106Skarels putbits(ou, 1); 48621106Skarels putbits(ex, 2); 48712751Ssam #undef putbits 48821106Skarels } 489*40703Skarels RETURN (error); 49012751Ssam } 49112751Ssam 492*40703Skarels selscan(ibits, obits, nfd, errp) 49323523Skarels fd_set *ibits, *obits; 494*40703Skarels int nfd, *errp; 49512751Ssam { 49623523Skarels register int which, i, j; 49723523Skarels register fd_mask bits; 49812751Ssam int flag; 49912751Ssam struct file *fp; 50012751Ssam int n = 0; 50112751Ssam 50212751Ssam for (which = 0; which < 3; which++) { 50312751Ssam switch (which) { 50412751Ssam 50512751Ssam case 0: 50612751Ssam flag = FREAD; break; 50712751Ssam 50812751Ssam case 1: 50912751Ssam flag = FWRITE; break; 51012751Ssam 51112751Ssam case 2: 51212751Ssam flag = 0; break; 51312751Ssam } 51423523Skarels for (i = 0; i < nfd; i += NFDBITS) { 51523523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 51617593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 51717593Skarels bits &= ~(1 << j); 51817593Skarels fp = u.u_ofile[i + j]; 51917593Skarels if (fp == NULL) { 520*40703Skarels *errp = EBADF; 52117593Skarels break; 52217593Skarels } 52317593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 52423523Skarels FD_SET(i + j, &obits[which]); 52517593Skarels n++; 52617593Skarels } 52712751Ssam } 52812751Ssam } 52912751Ssam } 53012751Ssam return (n); 53112751Ssam } 53212751Ssam 5337423Sroot /*ARGSUSED*/ 53412751Ssam seltrue(dev, flag) 53512751Ssam dev_t dev; 53612751Ssam int flag; 5377423Sroot { 5387423Sroot 53912751Ssam return (1); 5407423Sroot } 5418103Sroot 54212751Ssam selwakeup(p, coll) 54312751Ssam register struct proc *p; 54412751Ssam int coll; 5458103Sroot { 5468103Sroot 54712751Ssam if (coll) { 54812751Ssam nselcoll++; 54912751Ssam wakeup((caddr_t)&selwait); 55012751Ssam } 55112751Ssam if (p) { 55217934Skarels int s = splhigh(); 55317270Skarels if (p->p_wchan == (caddr_t)&selwait) { 55417270Skarels if (p->p_stat == SSLEEP) 55517270Skarels setrun(p); 55617270Skarels else 55717270Skarels unsleep(p); 55817270Skarels } else if (p->p_flag & SSEL) 55912751Ssam p->p_flag &= ~SSEL; 56012751Ssam splx(s); 56112751Ssam } 5628103Sroot } 563