123384Smckusick /* 263865Sbostic * Copyright (c) 1982, 1986, 1989, 1993 363865Sbostic * The Regents of the University of California. All rights reserved. 4*65771Sbostic * (c) UNIX System Laboratories, Inc. 5*65771Sbostic * All or some portions of this file are derived from material licensed 6*65771Sbostic * to the University of California by American Telephone and Telegraph 7*65771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8*65771Sbostic * the permission of UNIX System Laboratories, Inc. 923384Smckusick * 1044444Sbostic * %sccs.include.redist.c% 1137728Smckusick * 12*65771Sbostic * @(#)sys_generic.c 8.5 (Berkeley) 01/21/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++) { 13537728Smckusick if (iov->iov_len < 0) { 13637728Smckusick error = EINVAL; 13737728Smckusick goto done; 13837728Smckusick } 13937728Smckusick auio.uio_resid += iov->iov_len; 14037728Smckusick if (auio.uio_resid < 0) { 14137728Smckusick error = EINVAL; 14237728Smckusick goto done; 14337728Smckusick } 14437728Smckusick iov++; 14537728Smckusick } 14637728Smckusick #ifdef KTRACE 14737728Smckusick /* 14837728Smckusick * if tracing, save a copy of iovec 14937728Smckusick */ 15042922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 15137728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 15237728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 15337728Smckusick } 15437728Smckusick #endif 15537728Smckusick cnt = auio.uio_resid; 15640703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 15740703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 15840703Skarels error == EINTR || error == EWOULDBLOCK)) 15940703Skarels error = 0; 16037728Smckusick cnt -= auio.uio_resid; 16137728Smckusick #ifdef KTRACE 16237728Smckusick if (ktriov != NULL) { 16341178Smarc if (error == 0) 16443448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 16543448Smckusick cnt, error); 16637728Smckusick FREE(ktriov, M_TEMP); 16737728Smckusick } 16837728Smckusick #endif 16942922Smckusick *retval = cnt; 17037127Skarels done: 17152481Storek if (needfree) 17252481Storek FREE(needfree, M_IOV); 17344405Skarels return (error); 1747423Sroot } 1757423Sroot 1767423Sroot /* 1777423Sroot * Write system call 1787423Sroot */ 17954930Storek struct write_args { 18064409Sbostic int fd; 18164409Sbostic char *buf; 18264409Sbostic u_int nbyte; 18354930Storek }; 18442922Smckusick write(p, uap, retval) 18542922Smckusick struct proc *p; 18654930Storek register struct write_args *uap; 18742922Smckusick int *retval; 18842922Smckusick { 18937728Smckusick register struct file *fp; 19045914Smckusick register struct filedesc *fdp = p->p_fd; 1917820Sroot struct uio auio; 1927820Sroot struct iovec aiov; 19337728Smckusick long cnt, error = 0; 19437728Smckusick #ifdef KTRACE 19537728Smckusick struct iovec ktriov; 19637728Smckusick #endif 1977423Sroot 19864409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 19964409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 20037728Smckusick (fp->f_flag & FWRITE) == 0) 20144405Skarels return (EBADF); 20264409Sbostic aiov.iov_base = (caddr_t)uap->buf; 20364409Sbostic aiov.iov_len = uap->nbyte; 2047820Sroot auio.uio_iov = &aiov; 2057820Sroot auio.uio_iovcnt = 1; 20664409Sbostic auio.uio_resid = uap->nbyte; 20737728Smckusick auio.uio_rw = UIO_WRITE; 20837728Smckusick auio.uio_segflg = UIO_USERSPACE; 20948027Smckusick auio.uio_procp = p; 21037728Smckusick #ifdef KTRACE 21137728Smckusick /* 21237728Smckusick * if tracing, save a copy of iovec 21337728Smckusick */ 21442922Smckusick if (KTRPOINT(p, KTR_GENIO)) 21537728Smckusick ktriov = aiov; 21637728Smckusick #endif 21764409Sbostic cnt = uap->nbyte; 21840703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 21940703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 22040703Skarels error == EINTR || error == EWOULDBLOCK)) 22140703Skarels error = 0; 22240703Skarels if (error == EPIPE) 22342922Smckusick psignal(p, SIGPIPE); 22440703Skarels } 22537728Smckusick cnt -= auio.uio_resid; 22637728Smckusick #ifdef KTRACE 22742922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 22864409Sbostic ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 22943448Smckusick &ktriov, cnt, error); 23037728Smckusick #endif 23142922Smckusick *retval = cnt; 23244405Skarels return (error); 2337820Sroot } 2347820Sroot 23542922Smckusick /* 23642922Smckusick * Gather write system call 23742922Smckusick */ 23854930Storek struct writev_args { 23964409Sbostic int fd; 24054930Storek struct iovec *iovp; 24164409Sbostic u_int iovcnt; 24254930Storek }; 24342922Smckusick writev(p, uap, retval) 24442922Smckusick struct proc *p; 24554930Storek register struct writev_args *uap; 24642922Smckusick int *retval; 24742922Smckusick { 24837728Smckusick register struct file *fp; 24945914Smckusick register struct filedesc *fdp = p->p_fd; 2507820Sroot struct uio auio; 25137728Smckusick register struct iovec *iov; 25252481Storek struct iovec *needfree; 25337728Smckusick struct iovec aiov[UIO_SMALLIOV]; 25437728Smckusick long i, cnt, error = 0; 25564409Sbostic u_int iovlen; 25637728Smckusick #ifdef KTRACE 25737728Smckusick struct iovec *ktriov = NULL; 25837728Smckusick #endif 2597820Sroot 26064409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 26164409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 26237728Smckusick (fp->f_flag & FWRITE) == 0) 26344405Skarels return (EBADF); 26444939Skarels /* note: can't use iovlen until iovcnt is validated */ 26544939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 26637127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 26737728Smckusick if (uap->iovcnt > UIO_MAXIOV) 26844405Skarels return (EINVAL); 26944939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 27052481Storek needfree = iov; 27152481Storek } else { 27237127Skarels iov = aiov; 27352481Storek needfree = NULL; 27452481Storek } 27537127Skarels auio.uio_iov = iov; 2767820Sroot auio.uio_iovcnt = uap->iovcnt; 27737728Smckusick auio.uio_rw = UIO_WRITE; 27837728Smckusick auio.uio_segflg = UIO_USERSPACE; 27948027Smckusick auio.uio_procp = p; 28044939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 28137127Skarels goto done; 28237728Smckusick auio.uio_resid = 0; 28337728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2847820Sroot if (iov->iov_len < 0) { 28537728Smckusick error = EINVAL; 28637728Smckusick goto done; 2877820Sroot } 28837728Smckusick auio.uio_resid += iov->iov_len; 28937728Smckusick if (auio.uio_resid < 0) { 29037728Smckusick error = EINVAL; 29137728Smckusick goto done; 2927820Sroot } 29313270Ssam iov++; 2947820Sroot } 29537127Skarels #ifdef KTRACE 29637728Smckusick /* 29737728Smckusick * if tracing, save a copy of iovec 29837728Smckusick */ 29942922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 30037127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 30137728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 30237127Skarels } 30337127Skarels #endif 30437728Smckusick cnt = auio.uio_resid; 30540703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 30640703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 30740703Skarels error == EINTR || error == EWOULDBLOCK)) 30840703Skarels error = 0; 30940703Skarels if (error == EPIPE) 31042922Smckusick psignal(p, SIGPIPE); 31140703Skarels } 31237728Smckusick cnt -= auio.uio_resid; 31337127Skarels #ifdef KTRACE 31437127Skarels if (ktriov != NULL) { 31541178Smarc if (error == 0) 31664409Sbostic ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 31743448Smckusick ktriov, cnt, error); 31837127Skarels FREE(ktriov, M_TEMP); 31937127Skarels } 32037127Skarels #endif 32142922Smckusick *retval = cnt; 32237728Smckusick done: 32352481Storek if (needfree) 32452481Storek FREE(needfree, M_IOV); 32544405Skarels return (error); 3267423Sroot } 3277423Sroot 3287423Sroot /* 3297423Sroot * Ioctl system call 3307423Sroot */ 33154930Storek struct ioctl_args { 33264409Sbostic int fd; 33364409Sbostic int com; 33464409Sbostic caddr_t data; 33554930Storek }; 33642922Smckusick /* ARGSUSED */ 33742922Smckusick ioctl(p, uap, retval) 33842922Smckusick struct proc *p; 33954930Storek register struct ioctl_args *uap; 34042922Smckusick int *retval; 34142922Smckusick { 34242922Smckusick register struct file *fp; 34364538Sbostic register struct filedesc *fdp; 34440703Skarels register int com, error; 3457820Sroot register u_int size; 34664538Sbostic caddr_t data, memp; 34764538Sbostic int tmp; 34830530Skarels #define STK_PARAMS 128 34933480Skarels char stkbuf[STK_PARAMS]; 3507423Sroot 35164538Sbostic fdp = p->p_fd; 35264409Sbostic if ((u_int)uap->fd >= fdp->fd_nfiles || 35364409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL) 35444405Skarels return (EBADF); 35564538Sbostic 35664538Sbostic if ((fp->f_flag & (FREAD | FWRITE)) == 0) 35744405Skarels return (EBADF); 3587624Ssam 35964538Sbostic switch (com = uap->com) { 36064538Sbostic case FIONCLEX: 36164538Sbostic fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE; 36264538Sbostic return (0); 36364538Sbostic case FIOCLEX: 36464409Sbostic fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE; 36544405Skarels return (0); 3667423Sroot } 3677624Ssam 3687624Ssam /* 36964538Sbostic * Interpret high order word to find amount of data to be 37064538Sbostic * copied to/from the user's address space. 3717624Ssam */ 37230530Skarels size = IOCPARM_LEN(com); 37340703Skarels if (size > IOCPARM_MAX) 37444405Skarels return (ENOTTY); 37564538Sbostic memp = NULL; 37633480Skarels if (size > sizeof (stkbuf)) { 37743383Smckusick memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 37831653Smckusick data = memp; 37964538Sbostic } else 38064538Sbostic data = stkbuf; 38110601Ssam if (com&IOC_IN) { 38210601Ssam if (size) { 38364409Sbostic error = copyin(uap->data, data, (u_int)size); 38440703Skarels if (error) { 38531653Smckusick if (memp) 38631653Smckusick free(memp, M_IOCTLOPS); 38744405Skarels return (error); 38831653Smckusick } 38910601Ssam } else 39064409Sbostic *(caddr_t *)data = uap->data; 39110601Ssam } else if ((com&IOC_OUT) && size) 39210601Ssam /* 39337127Skarels * Zero the buffer so the user always 39437127Skarels * gets back something deterministic. 39510601Ssam */ 39630530Skarels bzero(data, size); 39711284Ssam else if (com&IOC_VOID) 39864409Sbostic *(caddr_t *)data = uap->data; 3997423Sroot 40012751Ssam switch (com) { 4017624Ssam 40212751Ssam case FIONBIO: 40348027Smckusick if (tmp = *(int *)data) 40449941Smckusick fp->f_flag |= FNONBLOCK; 40548027Smckusick else 40649941Smckusick fp->f_flag &= ~FNONBLOCK; 40748027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 40830530Skarels break; 40912751Ssam 41012751Ssam case FIOASYNC: 41148027Smckusick if (tmp = *(int *)data) 41248027Smckusick fp->f_flag |= FASYNC; 41348027Smckusick else 41448027Smckusick fp->f_flag &= ~FASYNC; 41548027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 41630530Skarels break; 41712751Ssam 41812751Ssam case FIOSETOWN: 41948027Smckusick tmp = *(int *)data; 42048027Smckusick if (fp->f_type == DTYPE_SOCKET) { 42148027Smckusick ((struct socket *)fp->f_data)->so_pgid = tmp; 42248027Smckusick error = 0; 42348027Smckusick break; 42448027Smckusick } 42548027Smckusick if (tmp <= 0) { 42648027Smckusick tmp = -tmp; 42748027Smckusick } else { 42848027Smckusick struct proc *p1 = pfind(tmp); 42948027Smckusick if (p1 == 0) { 43048027Smckusick error = ESRCH; 43148027Smckusick break; 43248027Smckusick } 43348027Smckusick tmp = p1->p_pgrp->pg_id; 43448027Smckusick } 43548027Smckusick error = (*fp->f_ops->fo_ioctl) 43648027Smckusick (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); 43730530Skarels break; 43812751Ssam 43912751Ssam case FIOGETOWN: 44048027Smckusick if (fp->f_type == DTYPE_SOCKET) { 44148027Smckusick error = 0; 44248027Smckusick *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 44348027Smckusick break; 44448027Smckusick } 44548027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); 44648027Smckusick *(int *)data = -*(int *)data; 44730530Skarels break; 44848027Smckusick 44930530Skarels default: 45047540Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 45130530Skarels /* 45230530Skarels * Copy any data to user, size was 45330530Skarels * already set and checked above. 45430530Skarels */ 45540703Skarels if (error == 0 && (com&IOC_OUT) && size) 45664409Sbostic error = copyout(data, uap->data, (u_int)size); 45730530Skarels break; 4587423Sroot } 45931653Smckusick if (memp) 46031653Smckusick free(memp, M_IOCTLOPS); 46144405Skarels return (error); 4627423Sroot } 4637423Sroot 46449227Skarels int selwait, nselcoll; 46517593Skarels 4667423Sroot /* 46712751Ssam * Select system call. 4687423Sroot */ 46954930Storek struct select_args { 47063864Smckusick u_int nd; 47154930Storek fd_set *in, *ou, *ex; 47254930Storek struct timeval *tv; 47354930Storek }; 47442922Smckusick select(p, uap, retval) 47542922Smckusick register struct proc *p; 47654930Storek register struct select_args *uap; 47742922Smckusick int *retval; 47842922Smckusick { 47923523Skarels fd_set ibits[3], obits[3]; 48012751Ssam struct timeval atv; 48163864Smckusick int s, ncoll, error = 0, timo; 48263864Smckusick u_int ni; 48312751Ssam 48426277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 48526277Skarels bzero((caddr_t)obits, sizeof(obits)); 48663864Smckusick if (uap->nd > FD_SETSIZE) 48763864Smckusick return (EINVAL); 48847540Skarels if (uap->nd > p->p_fd->fd_nfiles) 48947540Skarels uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 49063864Smckusick ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask); 49112751Ssam 49212751Ssam #define getbits(name, x) \ 49363864Smckusick if (uap->name && \ 49463864Smckusick (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \ 49563864Smckusick goto done; 49612751Ssam getbits(in, 0); 49712751Ssam getbits(ou, 1); 49812751Ssam getbits(ex, 2); 49912751Ssam #undef getbits 50012751Ssam 50112751Ssam if (uap->tv) { 50240703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 50312751Ssam sizeof (atv)); 50440703Skarels if (error) 50512751Ssam goto done; 50612751Ssam if (itimerfix(&atv)) { 50740703Skarels error = EINVAL; 50812751Ssam goto done; 50912751Ssam } 51054760Storek s = splclock(); 51154760Storek timevaladd(&atv, (struct timeval *)&time); 51240703Skarels timo = hzto(&atv); 51358254Smckusick /* 51458254Smckusick * Avoid inadvertently sleeping forever. 51558254Smckusick */ 51658254Smckusick if (timo == 0) 51758254Smckusick timo = 1; 51854276Sbostic splx(s); 51940703Skarels } else 52040703Skarels timo = 0; 52112751Ssam retry: 52212751Ssam ncoll = nselcoll; 52364583Sbostic p->p_flag |= P_SELECT; 52447540Skarels error = selscan(p, ibits, obits, uap->nd, retval); 52542922Smckusick if (error || *retval) 52612751Ssam goto done; 52717934Skarels s = splhigh(); 52812971Ssam /* this should be timercmp(&time, &atv, >=) */ 52912971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 53012971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 53112751Ssam splx(s); 53212751Ssam goto done; 53312751Ssam } 53464583Sbostic if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { 53512751Ssam splx(s); 53612751Ssam goto retry; 53712751Ssam } 53864583Sbostic p->p_flag &= ~P_SELECT; 53940703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 54012751Ssam splx(s); 54140703Skarels if (error == 0) 54240703Skarels goto retry; 54312751Ssam done: 54464583Sbostic p->p_flag &= ~P_SELECT; 54540703Skarels /* select is not restarted after signals... */ 54640703Skarels if (error == ERESTART) 54740703Skarels error = EINTR; 54840703Skarels if (error == EWOULDBLOCK) 54940703Skarels error = 0; 55012751Ssam #define putbits(name, x) \ 55163864Smckusick if (uap->name && \ 55263864Smckusick (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \ 55363864Smckusick error = error2; 55440703Skarels if (error == 0) { 55563864Smckusick int error2; 55663864Smckusick 55721106Skarels putbits(in, 0); 55821106Skarels putbits(ou, 1); 55921106Skarels putbits(ex, 2); 56012751Ssam #undef putbits 56121106Skarels } 56244405Skarels return (error); 56312751Ssam } 56412751Ssam 56547540Skarels selscan(p, ibits, obits, nfd, retval) 56647540Skarels struct proc *p; 56723523Skarels fd_set *ibits, *obits; 56842922Smckusick int nfd, *retval; 56912751Ssam { 57047540Skarels register struct filedesc *fdp = p->p_fd; 57152481Storek register int msk, i, j, fd; 57223523Skarels register fd_mask bits; 57312751Ssam struct file *fp; 57452481Storek int n = 0; 57552481Storek static int flag[3] = { FREAD, FWRITE, 0 }; 57612751Ssam 57752481Storek for (msk = 0; msk < 3; msk++) { 57823523Skarels for (i = 0; i < nfd; i += NFDBITS) { 57952481Storek bits = ibits[msk].fds_bits[i/NFDBITS]; 58052481Storek while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 58117593Skarels bits &= ~(1 << j); 58252481Storek fp = fdp->fd_ofiles[fd]; 58352481Storek if (fp == NULL) 58452481Storek return (EBADF); 58552481Storek if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 58652481Storek FD_SET(fd, &obits[msk]); 58717593Skarels n++; 58817593Skarels } 58912751Ssam } 59012751Ssam } 59112751Ssam } 59242922Smckusick *retval = n; 59352481Storek return (0); 59412751Ssam } 59512751Ssam 5967423Sroot /*ARGSUSED*/ 59747540Skarels seltrue(dev, flag, p) 59812751Ssam dev_t dev; 59912751Ssam int flag; 60047540Skarels struct proc *p; 6017423Sroot { 6027423Sroot 60312751Ssam return (1); 6047423Sroot } 6058103Sroot 60652525Smckusick /* 60752525Smckusick * Record a select request. 60852525Smckusick */ 60952525Smckusick void 61052525Smckusick selrecord(selector, sip) 61152525Smckusick struct proc *selector; 61252525Smckusick struct selinfo *sip; 6138103Sroot { 61452525Smckusick struct proc *p; 61552525Smckusick pid_t mypid; 6168103Sroot 61752525Smckusick mypid = selector->p_pid; 61852525Smckusick if (sip->si_pid == mypid) 61952525Smckusick return; 62052525Smckusick if (sip->si_pid && (p = pfind(sip->si_pid)) && 62152525Smckusick p->p_wchan == (caddr_t)&selwait) 62252525Smckusick sip->si_flags |= SI_COLL; 62352525Smckusick else 62452525Smckusick sip->si_pid = mypid; 62552525Smckusick } 62652525Smckusick 62752525Smckusick /* 62852525Smckusick * Do a wakeup when a selectable event occurs. 62952525Smckusick */ 63052525Smckusick void 63152525Smckusick selwakeup(sip) 63252525Smckusick register struct selinfo *sip; 63352525Smckusick { 63452525Smckusick register struct proc *p; 63552525Smckusick int s; 63652525Smckusick 63752525Smckusick if (sip->si_pid == 0) 63852525Smckusick return; 63952525Smckusick if (sip->si_flags & SI_COLL) { 64012751Ssam nselcoll++; 64152525Smckusick sip->si_flags &= ~SI_COLL; 64212751Ssam wakeup((caddr_t)&selwait); 64312751Ssam } 64452922Smckusick p = pfind(sip->si_pid); 64552922Smckusick sip->si_pid = 0; 64652922Smckusick if (p != NULL) { 64752525Smckusick s = splhigh(); 64817270Skarels if (p->p_wchan == (caddr_t)&selwait) { 64917270Skarels if (p->p_stat == SSLEEP) 65064538Sbostic setrunnable(p); 65117270Skarels else 65217270Skarels unsleep(p); 65364583Sbostic } else if (p->p_flag & P_SELECT) 65464583Sbostic p->p_flag &= ~P_SELECT; 65512751Ssam splx(s); 65612751Ssam } 6578103Sroot } 658