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*67661Smckusick * @(#)sys_generic.c 8.8 (Berkeley) 08/11/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 }; 466*67661Smckusick 46742922Smckusick select(p, uap, retval) 46842922Smckusick register struct proc *p; 46954930Storek register struct select_args *uap; 47042922Smckusick int *retval; 47142922Smckusick { 47223523Skarels fd_set ibits[3], obits[3]; 47312751Ssam struct timeval atv; 474*67661Smckusick int s, ncoll, error, timo = 0; 47563864Smckusick u_int ni; 47612751Ssam 47726277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 47826277Skarels bzero((caddr_t)obits, sizeof(obits)); 47963864Smckusick if (uap->nd > FD_SETSIZE) 48063864Smckusick return (EINVAL); 48147540Skarels if (uap->nd > p->p_fd->fd_nfiles) 48247540Skarels uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 48363864Smckusick ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask); 48412751Ssam 48512751Ssam #define getbits(name, x) \ 48663864Smckusick if (uap->name && \ 48763864Smckusick (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \ 48863864Smckusick goto done; 48912751Ssam getbits(in, 0); 49012751Ssam getbits(ou, 1); 49112751Ssam getbits(ex, 2); 49212751Ssam #undef getbits 49312751Ssam 49412751Ssam if (uap->tv) { 49540703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 49612751Ssam sizeof (atv)); 49740703Skarels if (error) 49812751Ssam goto done; 49912751Ssam if (itimerfix(&atv)) { 50040703Skarels error = EINVAL; 50112751Ssam goto done; 50212751Ssam } 50354760Storek s = splclock(); 50454760Storek timevaladd(&atv, (struct timeval *)&time); 50554276Sbostic splx(s); 506*67661Smckusick } 50712751Ssam retry: 50812751Ssam ncoll = nselcoll; 50964583Sbostic p->p_flag |= P_SELECT; 51047540Skarels error = selscan(p, ibits, obits, uap->nd, retval); 51142922Smckusick if (error || *retval) 51212751Ssam goto done; 51317934Skarels s = splhigh(); 51467633Smckusick if (uap->tv) { 51567633Smckusick if (timercmp(&time, &atv, >=)) { 51667633Smckusick splx(s); 51767633Smckusick goto done; 51867633Smckusick } 51967633Smckusick /* 520*67661Smckusick * If poll wait was tiny, this could be zero; we will 521*67661Smckusick * have to round it up to avoid sleeping forever. If 522*67661Smckusick * we retry below, the timercmp above will get us out. 523*67661Smckusick * Note that if wait was 0, the timercmp will prevent 524*67661Smckusick * us from getting here the first time. 52567633Smckusick */ 526*67661Smckusick timo = hzto(&atv); 527*67661Smckusick if (timo == 0) 52867633Smckusick timo = 1; 52912751Ssam } 53064583Sbostic if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { 53112751Ssam splx(s); 53212751Ssam goto retry; 53312751Ssam } 53464583Sbostic p->p_flag &= ~P_SELECT; 53540703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 53612751Ssam splx(s); 53740703Skarels if (error == 0) 53840703Skarels goto retry; 53912751Ssam done: 54064583Sbostic p->p_flag &= ~P_SELECT; 54140703Skarels /* select is not restarted after signals... */ 54240703Skarels if (error == ERESTART) 54340703Skarels error = EINTR; 54440703Skarels if (error == EWOULDBLOCK) 54540703Skarels error = 0; 54612751Ssam #define putbits(name, x) \ 54763864Smckusick if (uap->name && \ 54863864Smckusick (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \ 54963864Smckusick error = error2; 55040703Skarels if (error == 0) { 55163864Smckusick int error2; 55263864Smckusick 55321106Skarels putbits(in, 0); 55421106Skarels putbits(ou, 1); 55521106Skarels putbits(ex, 2); 55612751Ssam #undef putbits 55721106Skarels } 55844405Skarels return (error); 55912751Ssam } 56012751Ssam 56147540Skarels selscan(p, ibits, obits, nfd, retval) 56247540Skarels struct proc *p; 56323523Skarels fd_set *ibits, *obits; 56442922Smckusick int nfd, *retval; 56512751Ssam { 56647540Skarels register struct filedesc *fdp = p->p_fd; 56752481Storek register int msk, i, j, fd; 56823523Skarels register fd_mask bits; 56912751Ssam struct file *fp; 57052481Storek int n = 0; 57152481Storek static int flag[3] = { FREAD, FWRITE, 0 }; 57212751Ssam 57352481Storek for (msk = 0; msk < 3; msk++) { 57423523Skarels for (i = 0; i < nfd; i += NFDBITS) { 57552481Storek bits = ibits[msk].fds_bits[i/NFDBITS]; 57652481Storek while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 57717593Skarels bits &= ~(1 << j); 57852481Storek fp = fdp->fd_ofiles[fd]; 57952481Storek if (fp == NULL) 58052481Storek return (EBADF); 58152481Storek if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 58252481Storek FD_SET(fd, &obits[msk]); 58317593Skarels n++; 58417593Skarels } 58512751Ssam } 58612751Ssam } 58712751Ssam } 58842922Smckusick *retval = n; 58952481Storek return (0); 59012751Ssam } 59112751Ssam 5927423Sroot /*ARGSUSED*/ 59347540Skarels seltrue(dev, flag, p) 59412751Ssam dev_t dev; 59512751Ssam int flag; 59647540Skarels struct proc *p; 5977423Sroot { 5987423Sroot 59912751Ssam return (1); 6007423Sroot } 6018103Sroot 60252525Smckusick /* 60352525Smckusick * Record a select request. 60452525Smckusick */ 60552525Smckusick void 60652525Smckusick selrecord(selector, sip) 60752525Smckusick struct proc *selector; 60852525Smckusick struct selinfo *sip; 6098103Sroot { 61052525Smckusick struct proc *p; 61152525Smckusick pid_t mypid; 6128103Sroot 61352525Smckusick mypid = selector->p_pid; 61452525Smckusick if (sip->si_pid == mypid) 61552525Smckusick return; 61652525Smckusick if (sip->si_pid && (p = pfind(sip->si_pid)) && 61752525Smckusick p->p_wchan == (caddr_t)&selwait) 61852525Smckusick sip->si_flags |= SI_COLL; 61952525Smckusick else 62052525Smckusick sip->si_pid = mypid; 62152525Smckusick } 62252525Smckusick 62352525Smckusick /* 62452525Smckusick * Do a wakeup when a selectable event occurs. 62552525Smckusick */ 62652525Smckusick void 62752525Smckusick selwakeup(sip) 62852525Smckusick register struct selinfo *sip; 62952525Smckusick { 63052525Smckusick register struct proc *p; 63152525Smckusick int s; 63252525Smckusick 63352525Smckusick if (sip->si_pid == 0) 63452525Smckusick return; 63552525Smckusick if (sip->si_flags & SI_COLL) { 63612751Ssam nselcoll++; 63752525Smckusick sip->si_flags &= ~SI_COLL; 63812751Ssam wakeup((caddr_t)&selwait); 63912751Ssam } 64052922Smckusick p = pfind(sip->si_pid); 64152922Smckusick sip->si_pid = 0; 64252922Smckusick if (p != NULL) { 64352525Smckusick s = splhigh(); 64417270Skarels if (p->p_wchan == (caddr_t)&selwait) { 64517270Skarels if (p->p_stat == SSLEEP) 64664538Sbostic setrunnable(p); 64717270Skarels else 64817270Skarels unsleep(p); 64964583Sbostic } else if (p->p_flag & P_SELECT) 65064583Sbostic p->p_flag &= ~P_SELECT; 65112751Ssam splx(s); 65212751Ssam } 6538103Sroot } 654