123384Smckusick /* 263865Sbostic * Copyright (c) 1982, 1986, 1989, 1993 363865Sbostic * The Regents of the University of California. All rights reserved. 465771Sbostic * (c) UNIX System Laboratories, Inc. 565771Sbostic * All or some portions of this file are derived from material licensed 665771Sbostic * to the University of California by American Telephone and Telegraph 765771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 865771Sbostic * the permission of UNIX System Laboratories, Inc. 923384Smckusick * 1044444Sbostic * %sccs.include.redist.c% 1137728Smckusick * 12*67633Smckusick * @(#)sys_generic.c 8.7 (Berkeley) 08/10/94 1323384Smckusick */ 147423Sroot 1556517Sbostic #include <sys/param.h> 1656517Sbostic #include <sys/systm.h> 1756517Sbostic #include <sys/filedesc.h> 1856517Sbostic #include <sys/ioctl.h> 1956517Sbostic #include <sys/file.h> 2056517Sbostic #include <sys/proc.h> 2156517Sbostic #include <sys/socketvar.h> 2256517Sbostic #include <sys/uio.h> 2356517Sbostic #include <sys/kernel.h> 2456517Sbostic #include <sys/stat.h> 2556517Sbostic #include <sys/malloc.h> 2637127Skarels #ifdef KTRACE 2756517Sbostic #include <sys/ktrace.h> 2837127Skarels #endif 297423Sroot 307423Sroot /* 317423Sroot * Read system call. 327423Sroot */ 3354930Storek struct read_args { 3464409Sbostic int fd; 3564409Sbostic char *buf; 3664409Sbostic u_int nbyte; 3754930Storek }; 3845122Sbostic /* ARGSUSED */ 3942922Smckusick read(p, uap, retval) 4042922Smckusick struct proc *p; 4154930Storek register struct read_args *uap; 4242922Smckusick int *retval; 4342922Smckusick { 4437728Smckusick register struct file *fp; 4545914Smckusick register struct filedesc *fdp = p->p_fd; 467746Sroot struct uio auio; 477746Sroot struct iovec aiov; 4837728Smckusick long cnt, error = 0; 4937728Smckusick #ifdef KTRACE 5037728Smckusick struct iovec ktriov; 5137728Smckusick #endif 527423Sroot 5364409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 5464409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 5537728Smckusick (fp->f_flag & FREAD) == 0) 5644405Skarels return (EBADF); 5764409Sbostic aiov.iov_base = (caddr_t)uap->buf; 5864409Sbostic aiov.iov_len = uap->nbyte; 597820Sroot auio.uio_iov = &aiov; 607820Sroot auio.uio_iovcnt = 1; 6164409Sbostic auio.uio_resid = uap->nbyte; 6237728Smckusick auio.uio_rw = UIO_READ; 6337728Smckusick auio.uio_segflg = UIO_USERSPACE; 6448027Smckusick auio.uio_procp = p; 6537728Smckusick #ifdef KTRACE 6637728Smckusick /* 6737728Smckusick * if tracing, save a copy of iovec 6837728Smckusick */ 6942922Smckusick if (KTRPOINT(p, KTR_GENIO)) 7037728Smckusick ktriov = aiov; 7137728Smckusick #endif 7264409Sbostic cnt = uap->nbyte; 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 7942922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 8064409Sbostic ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error); 8137728Smckusick #endif 8242922Smckusick *retval = cnt; 8344405Skarels return (error); 847820Sroot } 857820Sroot 8642922Smckusick /* 8742922Smckusick * Scatter read system call. 8842922Smckusick */ 8954930Storek struct readv_args { 9054930Storek int fdes; 9154930Storek struct iovec *iovp; 9264409Sbostic u_int iovcnt; 9354930Storek }; 9442922Smckusick readv(p, uap, retval) 9542922Smckusick struct proc *p; 9654930Storek register struct readv_args *uap; 9742922Smckusick int *retval; 9842922Smckusick { 9937728Smckusick register struct file *fp; 10045914Smckusick register struct filedesc *fdp = p->p_fd; 1017820Sroot struct uio auio; 10237728Smckusick register struct iovec *iov; 10352481Storek struct iovec *needfree; 10437728Smckusick struct iovec aiov[UIO_SMALLIOV]; 10537728Smckusick long i, cnt, error = 0; 10664409Sbostic u_int iovlen; 10737728Smckusick #ifdef KTRACE 10837728Smckusick struct iovec *ktriov = NULL; 10937728Smckusick #endif 1107820Sroot 11164409Sbostic if (((u_int)uap->fdes) >= fdp->fd_nfiles || 11247974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 11337728Smckusick (fp->f_flag & FREAD) == 0) 11444405Skarels return (EBADF); 11544939Skarels /* note: can't use iovlen until iovcnt is validated */ 11644939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 11737127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 11837728Smckusick if (uap->iovcnt > UIO_MAXIOV) 11944405Skarels return (EINVAL); 12044939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 12152481Storek needfree = iov; 12252481Storek } else { 12337127Skarels iov = aiov; 12452481Storek needfree = NULL; 12552481Storek } 12637127Skarels auio.uio_iov = iov; 1277820Sroot auio.uio_iovcnt = uap->iovcnt; 12837728Smckusick auio.uio_rw = UIO_READ; 12937728Smckusick auio.uio_segflg = UIO_USERSPACE; 13048027Smckusick auio.uio_procp = p; 13144939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 13237127Skarels goto done; 13337728Smckusick auio.uio_resid = 0; 13437728Smckusick for (i = 0; i < uap->iovcnt; i++) { 13567491Smckusick if (auio.uio_resid + iov->iov_len < auio.uio_resid) { 13637728Smckusick error = EINVAL; 13737728Smckusick goto done; 13837728Smckusick } 13937728Smckusick auio.uio_resid += iov->iov_len; 14037728Smckusick iov++; 14137728Smckusick } 14237728Smckusick #ifdef KTRACE 14337728Smckusick /* 14437728Smckusick * if tracing, save a copy of iovec 14537728Smckusick */ 14642922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 14737728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 14837728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 14937728Smckusick } 15037728Smckusick #endif 15137728Smckusick cnt = auio.uio_resid; 15240703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 15340703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 15440703Skarels error == EINTR || error == EWOULDBLOCK)) 15540703Skarels error = 0; 15637728Smckusick cnt -= auio.uio_resid; 15737728Smckusick #ifdef KTRACE 15837728Smckusick if (ktriov != NULL) { 15941178Smarc if (error == 0) 16043448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 16143448Smckusick cnt, error); 16237728Smckusick FREE(ktriov, M_TEMP); 16337728Smckusick } 16437728Smckusick #endif 16542922Smckusick *retval = cnt; 16637127Skarels done: 16752481Storek if (needfree) 16852481Storek FREE(needfree, M_IOV); 16944405Skarels return (error); 1707423Sroot } 1717423Sroot 1727423Sroot /* 1737423Sroot * Write system call 1747423Sroot */ 17554930Storek struct write_args { 17664409Sbostic int fd; 17764409Sbostic char *buf; 17864409Sbostic u_int nbyte; 17954930Storek }; 18042922Smckusick write(p, uap, retval) 18142922Smckusick struct proc *p; 18254930Storek register struct write_args *uap; 18342922Smckusick int *retval; 18442922Smckusick { 18537728Smckusick register struct file *fp; 18645914Smckusick register struct filedesc *fdp = p->p_fd; 1877820Sroot struct uio auio; 1887820Sroot struct iovec aiov; 18937728Smckusick long cnt, error = 0; 19037728Smckusick #ifdef KTRACE 19137728Smckusick struct iovec ktriov; 19237728Smckusick #endif 1937423Sroot 19464409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 19564409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 19637728Smckusick (fp->f_flag & FWRITE) == 0) 19744405Skarels return (EBADF); 19864409Sbostic aiov.iov_base = (caddr_t)uap->buf; 19964409Sbostic aiov.iov_len = uap->nbyte; 2007820Sroot auio.uio_iov = &aiov; 2017820Sroot auio.uio_iovcnt = 1; 20264409Sbostic auio.uio_resid = uap->nbyte; 20337728Smckusick auio.uio_rw = UIO_WRITE; 20437728Smckusick auio.uio_segflg = UIO_USERSPACE; 20548027Smckusick auio.uio_procp = p; 20637728Smckusick #ifdef KTRACE 20737728Smckusick /* 20837728Smckusick * if tracing, save a copy of iovec 20937728Smckusick */ 21042922Smckusick if (KTRPOINT(p, KTR_GENIO)) 21137728Smckusick ktriov = aiov; 21237728Smckusick #endif 21364409Sbostic cnt = uap->nbyte; 21440703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 21540703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 21640703Skarels error == EINTR || error == EWOULDBLOCK)) 21740703Skarels error = 0; 21840703Skarels if (error == EPIPE) 21942922Smckusick psignal(p, SIGPIPE); 22040703Skarels } 22137728Smckusick cnt -= auio.uio_resid; 22237728Smckusick #ifdef KTRACE 22342922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 22464409Sbostic ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 22543448Smckusick &ktriov, cnt, error); 22637728Smckusick #endif 22742922Smckusick *retval = cnt; 22844405Skarels return (error); 2297820Sroot } 2307820Sroot 23142922Smckusick /* 23242922Smckusick * Gather write system call 23342922Smckusick */ 23454930Storek struct writev_args { 23564409Sbostic int fd; 23654930Storek struct iovec *iovp; 23764409Sbostic u_int iovcnt; 23854930Storek }; 23942922Smckusick writev(p, uap, retval) 24042922Smckusick struct proc *p; 24154930Storek register struct writev_args *uap; 24242922Smckusick int *retval; 24342922Smckusick { 24437728Smckusick register struct file *fp; 24545914Smckusick register struct filedesc *fdp = p->p_fd; 2467820Sroot struct uio auio; 24737728Smckusick register struct iovec *iov; 24852481Storek struct iovec *needfree; 24937728Smckusick struct iovec aiov[UIO_SMALLIOV]; 25037728Smckusick long i, cnt, error = 0; 25164409Sbostic u_int iovlen; 25237728Smckusick #ifdef KTRACE 25337728Smckusick struct iovec *ktriov = NULL; 25437728Smckusick #endif 2557820Sroot 25664409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 25764409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 25837728Smckusick (fp->f_flag & FWRITE) == 0) 25944405Skarels return (EBADF); 26044939Skarels /* note: can't use iovlen until iovcnt is validated */ 26144939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 26237127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 26337728Smckusick if (uap->iovcnt > UIO_MAXIOV) 26444405Skarels return (EINVAL); 26544939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 26652481Storek needfree = iov; 26752481Storek } else { 26837127Skarels iov = aiov; 26952481Storek needfree = NULL; 27052481Storek } 27137127Skarels auio.uio_iov = iov; 2727820Sroot auio.uio_iovcnt = uap->iovcnt; 27337728Smckusick auio.uio_rw = UIO_WRITE; 27437728Smckusick auio.uio_segflg = UIO_USERSPACE; 27548027Smckusick auio.uio_procp = p; 27644939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 27737127Skarels goto done; 27837728Smckusick auio.uio_resid = 0; 27937728Smckusick for (i = 0; i < uap->iovcnt; i++) { 28067491Smckusick if (auio.uio_resid + iov->iov_len < auio.uio_resid) { 28137728Smckusick error = EINVAL; 28237728Smckusick goto done; 2837820Sroot } 28437728Smckusick auio.uio_resid += iov->iov_len; 28513270Ssam iov++; 2867820Sroot } 28737127Skarels #ifdef KTRACE 28837728Smckusick /* 28937728Smckusick * if tracing, save a copy of iovec 29037728Smckusick */ 29142922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 29237127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 29337728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 29437127Skarels } 29537127Skarels #endif 29637728Smckusick cnt = auio.uio_resid; 29740703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 29840703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 29940703Skarels error == EINTR || error == EWOULDBLOCK)) 30040703Skarels error = 0; 30140703Skarels if (error == EPIPE) 30242922Smckusick psignal(p, SIGPIPE); 30340703Skarels } 30437728Smckusick cnt -= auio.uio_resid; 30537127Skarels #ifdef KTRACE 30637127Skarels if (ktriov != NULL) { 30741178Smarc if (error == 0) 30864409Sbostic ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 30943448Smckusick ktriov, cnt, error); 31037127Skarels FREE(ktriov, M_TEMP); 31137127Skarels } 31237127Skarels #endif 31342922Smckusick *retval = cnt; 31437728Smckusick done: 31552481Storek if (needfree) 31652481Storek FREE(needfree, M_IOV); 31744405Skarels return (error); 3187423Sroot } 3197423Sroot 3207423Sroot /* 3217423Sroot * Ioctl system call 3227423Sroot */ 32354930Storek struct ioctl_args { 32464409Sbostic int fd; 32564409Sbostic int com; 32664409Sbostic caddr_t data; 32754930Storek }; 32842922Smckusick /* ARGSUSED */ 32942922Smckusick ioctl(p, uap, retval) 33042922Smckusick struct proc *p; 33154930Storek register struct ioctl_args *uap; 33242922Smckusick int *retval; 33342922Smckusick { 33442922Smckusick register struct file *fp; 33564538Sbostic register struct filedesc *fdp; 33640703Skarels register int com, error; 3377820Sroot register u_int size; 33864538Sbostic caddr_t data, memp; 33964538Sbostic int tmp; 34030530Skarels #define STK_PARAMS 128 34133480Skarels char stkbuf[STK_PARAMS]; 3427423Sroot 34364538Sbostic fdp = p->p_fd; 34464409Sbostic if ((u_int)uap->fd >= fdp->fd_nfiles || 34564409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL) 34644405Skarels return (EBADF); 34764538Sbostic 34864538Sbostic if ((fp->f_flag & (FREAD | FWRITE)) == 0) 34944405Skarels return (EBADF); 3507624Ssam 35164538Sbostic switch (com = uap->com) { 35264538Sbostic case FIONCLEX: 35364538Sbostic fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE; 35464538Sbostic return (0); 35564538Sbostic case FIOCLEX: 35664409Sbostic fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE; 35744405Skarels return (0); 3587423Sroot } 3597624Ssam 3607624Ssam /* 36164538Sbostic * Interpret high order word to find amount of data to be 36264538Sbostic * copied to/from the user's address space. 3637624Ssam */ 36430530Skarels size = IOCPARM_LEN(com); 36540703Skarels if (size > IOCPARM_MAX) 36644405Skarels return (ENOTTY); 36764538Sbostic memp = NULL; 36833480Skarels if (size > sizeof (stkbuf)) { 36943383Smckusick memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 37031653Smckusick data = memp; 37164538Sbostic } else 37264538Sbostic data = stkbuf; 37310601Ssam if (com&IOC_IN) { 37410601Ssam if (size) { 37564409Sbostic error = copyin(uap->data, data, (u_int)size); 37640703Skarels if (error) { 37731653Smckusick if (memp) 37831653Smckusick free(memp, M_IOCTLOPS); 37944405Skarels return (error); 38031653Smckusick } 38110601Ssam } else 38264409Sbostic *(caddr_t *)data = uap->data; 38310601Ssam } else if ((com&IOC_OUT) && size) 38410601Ssam /* 38537127Skarels * Zero the buffer so the user always 38637127Skarels * gets back something deterministic. 38710601Ssam */ 38830530Skarels bzero(data, size); 38911284Ssam else if (com&IOC_VOID) 39064409Sbostic *(caddr_t *)data = uap->data; 3917423Sroot 39212751Ssam switch (com) { 3937624Ssam 39412751Ssam case FIONBIO: 39548027Smckusick if (tmp = *(int *)data) 39649941Smckusick fp->f_flag |= FNONBLOCK; 39748027Smckusick else 39849941Smckusick fp->f_flag &= ~FNONBLOCK; 39948027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 40030530Skarels break; 40112751Ssam 40212751Ssam case FIOASYNC: 40348027Smckusick if (tmp = *(int *)data) 40448027Smckusick fp->f_flag |= FASYNC; 40548027Smckusick else 40648027Smckusick fp->f_flag &= ~FASYNC; 40748027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 40830530Skarels break; 40912751Ssam 41012751Ssam case FIOSETOWN: 41148027Smckusick tmp = *(int *)data; 41248027Smckusick if (fp->f_type == DTYPE_SOCKET) { 41348027Smckusick ((struct socket *)fp->f_data)->so_pgid = tmp; 41448027Smckusick error = 0; 41548027Smckusick break; 41648027Smckusick } 41748027Smckusick if (tmp <= 0) { 41848027Smckusick tmp = -tmp; 41948027Smckusick } else { 42048027Smckusick struct proc *p1 = pfind(tmp); 42148027Smckusick if (p1 == 0) { 42248027Smckusick error = ESRCH; 42348027Smckusick break; 42448027Smckusick } 42548027Smckusick tmp = p1->p_pgrp->pg_id; 42648027Smckusick } 42748027Smckusick error = (*fp->f_ops->fo_ioctl) 42848027Smckusick (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); 42930530Skarels break; 43012751Ssam 43112751Ssam case FIOGETOWN: 43248027Smckusick if (fp->f_type == DTYPE_SOCKET) { 43348027Smckusick error = 0; 43448027Smckusick *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 43548027Smckusick break; 43648027Smckusick } 43748027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); 43848027Smckusick *(int *)data = -*(int *)data; 43930530Skarels break; 44048027Smckusick 44130530Skarels default: 44247540Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 44330530Skarels /* 44430530Skarels * Copy any data to user, size was 44530530Skarels * already set and checked above. 44630530Skarels */ 44740703Skarels if (error == 0 && (com&IOC_OUT) && size) 44864409Sbostic error = copyout(data, uap->data, (u_int)size); 44930530Skarels break; 4507423Sroot } 45131653Smckusick if (memp) 45231653Smckusick free(memp, M_IOCTLOPS); 45344405Skarels return (error); 4547423Sroot } 4557423Sroot 45649227Skarels int selwait, nselcoll; 45717593Skarels 4587423Sroot /* 45912751Ssam * Select system call. 4607423Sroot */ 46154930Storek struct select_args { 46263864Smckusick u_int nd; 46354930Storek fd_set *in, *ou, *ex; 46454930Storek struct timeval *tv; 46554930Storek }; 46642922Smckusick select(p, uap, retval) 46742922Smckusick register struct proc *p; 46854930Storek register struct select_args *uap; 46942922Smckusick int *retval; 47042922Smckusick { 47123523Skarels fd_set ibits[3], obits[3]; 47212751Ssam struct timeval atv; 473*67633Smckusick int s, ncoll, error = 0, timo, doblock; 47463864Smckusick u_int ni; 47512751Ssam 47626277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 47726277Skarels bzero((caddr_t)obits, sizeof(obits)); 47863864Smckusick if (uap->nd > FD_SETSIZE) 47963864Smckusick return (EINVAL); 48047540Skarels if (uap->nd > p->p_fd->fd_nfiles) 48147540Skarels uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 48263864Smckusick ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask); 48312751Ssam 48412751Ssam #define getbits(name, x) \ 48563864Smckusick if (uap->name && \ 48663864Smckusick (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \ 48763864Smckusick goto done; 48812751Ssam getbits(in, 0); 48912751Ssam getbits(ou, 1); 49012751Ssam getbits(ex, 2); 49112751Ssam #undef getbits 49212751Ssam 49312751Ssam if (uap->tv) { 49440703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 49512751Ssam sizeof (atv)); 49640703Skarels if (error) 49712751Ssam goto done; 49812751Ssam if (itimerfix(&atv)) { 49940703Skarels error = EINVAL; 50012751Ssam goto done; 50112751Ssam } 502*67633Smckusick /* 503*67633Smckusick * Don't let a short time get rounded down to zero 504*67633Smckusick * and cause us to sleep forever, but exactly zero 505*67633Smckusick * means "do not block". 506*67633Smckusick */ 507*67633Smckusick doblock = (atv.tv_usec || atv.tv_sec); 50854760Storek s = splclock(); 50954760Storek timevaladd(&atv, (struct timeval *)&time); 51054276Sbostic splx(s); 51140703Skarels } else 51240703Skarels timo = 0; 51312751Ssam retry: 51412751Ssam ncoll = nselcoll; 51564583Sbostic p->p_flag |= P_SELECT; 51647540Skarels error = selscan(p, ibits, obits, uap->nd, retval); 51742922Smckusick if (error || *retval) 51812751Ssam goto done; 51917934Skarels s = splhigh(); 520*67633Smckusick if (uap->tv) { 521*67633Smckusick if (timercmp(&time, &atv, >=)) { 522*67633Smckusick splx(s); 523*67633Smckusick goto done; 524*67633Smckusick } 525*67633Smckusick timo = hzto(&atv); 526*67633Smckusick /* 527*67633Smckusick * Avoid inadvertently sleeping forever. 528*67633Smckusick */ 529*67633Smckusick if (doblock && timo == 0) 530*67633Smckusick timo = 1; 53112751Ssam } 53264583Sbostic if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { 53312751Ssam splx(s); 53412751Ssam goto retry; 53512751Ssam } 53664583Sbostic p->p_flag &= ~P_SELECT; 537*67633Smckusick doblock = 0; 53840703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 53912751Ssam splx(s); 54040703Skarels if (error == 0) 54140703Skarels goto retry; 54212751Ssam done: 54364583Sbostic p->p_flag &= ~P_SELECT; 54440703Skarels /* select is not restarted after signals... */ 54540703Skarels if (error == ERESTART) 54640703Skarels error = EINTR; 54740703Skarels if (error == EWOULDBLOCK) 54840703Skarels error = 0; 54912751Ssam #define putbits(name, x) \ 55063864Smckusick if (uap->name && \ 55163864Smckusick (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \ 55263864Smckusick error = error2; 55340703Skarels if (error == 0) { 55463864Smckusick int error2; 55563864Smckusick 55621106Skarels putbits(in, 0); 55721106Skarels putbits(ou, 1); 55821106Skarels putbits(ex, 2); 55912751Ssam #undef putbits 56021106Skarels } 56144405Skarels return (error); 56212751Ssam } 56312751Ssam 56447540Skarels selscan(p, ibits, obits, nfd, retval) 56547540Skarels struct proc *p; 56623523Skarels fd_set *ibits, *obits; 56742922Smckusick int nfd, *retval; 56812751Ssam { 56947540Skarels register struct filedesc *fdp = p->p_fd; 57052481Storek register int msk, i, j, fd; 57123523Skarels register fd_mask bits; 57212751Ssam struct file *fp; 57352481Storek int n = 0; 57452481Storek static int flag[3] = { FREAD, FWRITE, 0 }; 57512751Ssam 57652481Storek for (msk = 0; msk < 3; msk++) { 57723523Skarels for (i = 0; i < nfd; i += NFDBITS) { 57852481Storek bits = ibits[msk].fds_bits[i/NFDBITS]; 57952481Storek while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 58017593Skarels bits &= ~(1 << j); 58152481Storek fp = fdp->fd_ofiles[fd]; 58252481Storek if (fp == NULL) 58352481Storek return (EBADF); 58452481Storek if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 58552481Storek FD_SET(fd, &obits[msk]); 58617593Skarels n++; 58717593Skarels } 58812751Ssam } 58912751Ssam } 59012751Ssam } 59142922Smckusick *retval = n; 59252481Storek return (0); 59312751Ssam } 59412751Ssam 5957423Sroot /*ARGSUSED*/ 59647540Skarels seltrue(dev, flag, p) 59712751Ssam dev_t dev; 59812751Ssam int flag; 59947540Skarels struct proc *p; 6007423Sroot { 6017423Sroot 60212751Ssam return (1); 6037423Sroot } 6048103Sroot 60552525Smckusick /* 60652525Smckusick * Record a select request. 60752525Smckusick */ 60852525Smckusick void 60952525Smckusick selrecord(selector, sip) 61052525Smckusick struct proc *selector; 61152525Smckusick struct selinfo *sip; 6128103Sroot { 61352525Smckusick struct proc *p; 61452525Smckusick pid_t mypid; 6158103Sroot 61652525Smckusick mypid = selector->p_pid; 61752525Smckusick if (sip->si_pid == mypid) 61852525Smckusick return; 61952525Smckusick if (sip->si_pid && (p = pfind(sip->si_pid)) && 62052525Smckusick p->p_wchan == (caddr_t)&selwait) 62152525Smckusick sip->si_flags |= SI_COLL; 62252525Smckusick else 62352525Smckusick sip->si_pid = mypid; 62452525Smckusick } 62552525Smckusick 62652525Smckusick /* 62752525Smckusick * Do a wakeup when a selectable event occurs. 62852525Smckusick */ 62952525Smckusick void 63052525Smckusick selwakeup(sip) 63152525Smckusick register struct selinfo *sip; 63252525Smckusick { 63352525Smckusick register struct proc *p; 63452525Smckusick int s; 63552525Smckusick 63652525Smckusick if (sip->si_pid == 0) 63752525Smckusick return; 63852525Smckusick if (sip->si_flags & SI_COLL) { 63912751Ssam nselcoll++; 64052525Smckusick sip->si_flags &= ~SI_COLL; 64112751Ssam wakeup((caddr_t)&selwait); 64212751Ssam } 64352922Smckusick p = pfind(sip->si_pid); 64452922Smckusick sip->si_pid = 0; 64552922Smckusick if (p != NULL) { 64652525Smckusick s = splhigh(); 64717270Skarels if (p->p_wchan == (caddr_t)&selwait) { 64817270Skarels if (p->p_stat == SSLEEP) 64964538Sbostic setrunnable(p); 65017270Skarels else 65117270Skarels unsleep(p); 65264583Sbostic } else if (p->p_flag & P_SELECT) 65364583Sbostic p->p_flag &= ~P_SELECT; 65412751Ssam splx(s); 65512751Ssam } 6568103Sroot } 657