123384Smckusick /* 263865Sbostic * Copyright (c) 1982, 1986, 1989, 1993 363865Sbostic * The Regents of the University of California. All rights reserved. 423384Smckusick * 544444Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*64538Sbostic * @(#)sys_generic.c 8.3 (Berkeley) 09/21/93 823384Smckusick */ 97423Sroot 1056517Sbostic #include <sys/param.h> 1156517Sbostic #include <sys/systm.h> 1256517Sbostic #include <sys/filedesc.h> 1356517Sbostic #include <sys/ioctl.h> 1456517Sbostic #include <sys/file.h> 1556517Sbostic #include <sys/proc.h> 1656517Sbostic #include <sys/socketvar.h> 1756517Sbostic #include <sys/uio.h> 1856517Sbostic #include <sys/kernel.h> 1956517Sbostic #include <sys/stat.h> 2056517Sbostic #include <sys/malloc.h> 2137127Skarels #ifdef KTRACE 2256517Sbostic #include <sys/ktrace.h> 2337127Skarels #endif 247423Sroot 257423Sroot /* 267423Sroot * Read system call. 277423Sroot */ 2854930Storek struct read_args { 2964409Sbostic int fd; 3064409Sbostic char *buf; 3164409Sbostic u_int nbyte; 3254930Storek }; 3345122Sbostic /* ARGSUSED */ 3442922Smckusick read(p, uap, retval) 3542922Smckusick struct proc *p; 3654930Storek register struct read_args *uap; 3742922Smckusick int *retval; 3842922Smckusick { 3937728Smckusick register struct file *fp; 4045914Smckusick register struct filedesc *fdp = p->p_fd; 417746Sroot struct uio auio; 427746Sroot struct iovec aiov; 4337728Smckusick long cnt, error = 0; 4437728Smckusick #ifdef KTRACE 4537728Smckusick struct iovec ktriov; 4637728Smckusick #endif 477423Sroot 4864409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 4964409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 5037728Smckusick (fp->f_flag & FREAD) == 0) 5144405Skarels return (EBADF); 5264409Sbostic aiov.iov_base = (caddr_t)uap->buf; 5364409Sbostic aiov.iov_len = uap->nbyte; 547820Sroot auio.uio_iov = &aiov; 557820Sroot auio.uio_iovcnt = 1; 5664409Sbostic auio.uio_resid = uap->nbyte; 5737728Smckusick auio.uio_rw = UIO_READ; 5837728Smckusick auio.uio_segflg = UIO_USERSPACE; 5948027Smckusick auio.uio_procp = p; 6037728Smckusick #ifdef KTRACE 6137728Smckusick /* 6237728Smckusick * if tracing, save a copy of iovec 6337728Smckusick */ 6442922Smckusick if (KTRPOINT(p, KTR_GENIO)) 6537728Smckusick ktriov = aiov; 6637728Smckusick #endif 6764409Sbostic cnt = uap->nbyte; 6840703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 6940703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 7040703Skarels error == EINTR || error == EWOULDBLOCK)) 7140703Skarels error = 0; 7237728Smckusick cnt -= auio.uio_resid; 7337728Smckusick #ifdef KTRACE 7442922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 7564409Sbostic ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error); 7637728Smckusick #endif 7742922Smckusick *retval = cnt; 7844405Skarels return (error); 797820Sroot } 807820Sroot 8142922Smckusick /* 8242922Smckusick * Scatter read system call. 8342922Smckusick */ 8454930Storek struct readv_args { 8554930Storek int fdes; 8654930Storek struct iovec *iovp; 8764409Sbostic u_int iovcnt; 8854930Storek }; 8942922Smckusick readv(p, uap, retval) 9042922Smckusick struct proc *p; 9154930Storek register struct readv_args *uap; 9242922Smckusick int *retval; 9342922Smckusick { 9437728Smckusick register struct file *fp; 9545914Smckusick register struct filedesc *fdp = p->p_fd; 967820Sroot struct uio auio; 9737728Smckusick register struct iovec *iov; 9852481Storek struct iovec *needfree; 9937728Smckusick struct iovec aiov[UIO_SMALLIOV]; 10037728Smckusick long i, cnt, error = 0; 10164409Sbostic u_int iovlen; 10237728Smckusick #ifdef KTRACE 10337728Smckusick struct iovec *ktriov = NULL; 10437728Smckusick #endif 1057820Sroot 10664409Sbostic if (((u_int)uap->fdes) >= fdp->fd_nfiles || 10747974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 10837728Smckusick (fp->f_flag & FREAD) == 0) 10944405Skarels return (EBADF); 11044939Skarels /* note: can't use iovlen until iovcnt is validated */ 11144939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 11237127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 11337728Smckusick if (uap->iovcnt > UIO_MAXIOV) 11444405Skarels return (EINVAL); 11544939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 11652481Storek needfree = iov; 11752481Storek } else { 11837127Skarels iov = aiov; 11952481Storek needfree = NULL; 12052481Storek } 12137127Skarels auio.uio_iov = iov; 1227820Sroot auio.uio_iovcnt = uap->iovcnt; 12337728Smckusick auio.uio_rw = UIO_READ; 12437728Smckusick auio.uio_segflg = UIO_USERSPACE; 12548027Smckusick auio.uio_procp = p; 12644939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 12737127Skarels goto done; 12837728Smckusick auio.uio_resid = 0; 12937728Smckusick for (i = 0; i < uap->iovcnt; i++) { 13037728Smckusick if (iov->iov_len < 0) { 13137728Smckusick error = EINVAL; 13237728Smckusick goto done; 13337728Smckusick } 13437728Smckusick auio.uio_resid += iov->iov_len; 13537728Smckusick if (auio.uio_resid < 0) { 13637728Smckusick error = EINVAL; 13737728Smckusick goto done; 13837728Smckusick } 13937728Smckusick iov++; 14037728Smckusick } 14137728Smckusick #ifdef KTRACE 14237728Smckusick /* 14337728Smckusick * if tracing, save a copy of iovec 14437728Smckusick */ 14542922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 14637728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 14737728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 14837728Smckusick } 14937728Smckusick #endif 15037728Smckusick cnt = auio.uio_resid; 15140703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 15240703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 15340703Skarels error == EINTR || error == EWOULDBLOCK)) 15440703Skarels error = 0; 15537728Smckusick cnt -= auio.uio_resid; 15637728Smckusick #ifdef KTRACE 15737728Smckusick if (ktriov != NULL) { 15841178Smarc if (error == 0) 15943448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 16043448Smckusick cnt, error); 16137728Smckusick FREE(ktriov, M_TEMP); 16237728Smckusick } 16337728Smckusick #endif 16442922Smckusick *retval = cnt; 16537127Skarels done: 16652481Storek if (needfree) 16752481Storek FREE(needfree, M_IOV); 16844405Skarels return (error); 1697423Sroot } 1707423Sroot 1717423Sroot /* 1727423Sroot * Write system call 1737423Sroot */ 17454930Storek struct write_args { 17564409Sbostic int fd; 17664409Sbostic char *buf; 17764409Sbostic u_int nbyte; 17854930Storek }; 17942922Smckusick write(p, uap, retval) 18042922Smckusick struct proc *p; 18154930Storek register struct write_args *uap; 18242922Smckusick int *retval; 18342922Smckusick { 18437728Smckusick register struct file *fp; 18545914Smckusick register struct filedesc *fdp = p->p_fd; 1867820Sroot struct uio auio; 1877820Sroot struct iovec aiov; 18837728Smckusick long cnt, error = 0; 18937728Smckusick #ifdef KTRACE 19037728Smckusick struct iovec ktriov; 19137728Smckusick #endif 1927423Sroot 19364409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 19464409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 19537728Smckusick (fp->f_flag & FWRITE) == 0) 19644405Skarels return (EBADF); 19764409Sbostic aiov.iov_base = (caddr_t)uap->buf; 19864409Sbostic aiov.iov_len = uap->nbyte; 1997820Sroot auio.uio_iov = &aiov; 2007820Sroot auio.uio_iovcnt = 1; 20164409Sbostic auio.uio_resid = uap->nbyte; 20237728Smckusick auio.uio_rw = UIO_WRITE; 20337728Smckusick auio.uio_segflg = UIO_USERSPACE; 20448027Smckusick auio.uio_procp = p; 20537728Smckusick #ifdef KTRACE 20637728Smckusick /* 20737728Smckusick * if tracing, save a copy of iovec 20837728Smckusick */ 20942922Smckusick if (KTRPOINT(p, KTR_GENIO)) 21037728Smckusick ktriov = aiov; 21137728Smckusick #endif 21264409Sbostic cnt = uap->nbyte; 21340703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 21440703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 21540703Skarels error == EINTR || error == EWOULDBLOCK)) 21640703Skarels error = 0; 21740703Skarels if (error == EPIPE) 21842922Smckusick psignal(p, SIGPIPE); 21940703Skarels } 22037728Smckusick cnt -= auio.uio_resid; 22137728Smckusick #ifdef KTRACE 22242922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 22364409Sbostic ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 22443448Smckusick &ktriov, cnt, error); 22537728Smckusick #endif 22642922Smckusick *retval = cnt; 22744405Skarels return (error); 2287820Sroot } 2297820Sroot 23042922Smckusick /* 23142922Smckusick * Gather write system call 23242922Smckusick */ 23354930Storek struct writev_args { 23464409Sbostic int fd; 23554930Storek struct iovec *iovp; 23664409Sbostic u_int iovcnt; 23754930Storek }; 23842922Smckusick writev(p, uap, retval) 23942922Smckusick struct proc *p; 24054930Storek register struct writev_args *uap; 24142922Smckusick int *retval; 24242922Smckusick { 24337728Smckusick register struct file *fp; 24445914Smckusick register struct filedesc *fdp = p->p_fd; 2457820Sroot struct uio auio; 24637728Smckusick register struct iovec *iov; 24752481Storek struct iovec *needfree; 24837728Smckusick struct iovec aiov[UIO_SMALLIOV]; 24937728Smckusick long i, cnt, error = 0; 25064409Sbostic u_int iovlen; 25137728Smckusick #ifdef KTRACE 25237728Smckusick struct iovec *ktriov = NULL; 25337728Smckusick #endif 2547820Sroot 25564409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 25664409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 25737728Smckusick (fp->f_flag & FWRITE) == 0) 25844405Skarels return (EBADF); 25944939Skarels /* note: can't use iovlen until iovcnt is validated */ 26044939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 26137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 26237728Smckusick if (uap->iovcnt > UIO_MAXIOV) 26344405Skarels return (EINVAL); 26444939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 26552481Storek needfree = iov; 26652481Storek } else { 26737127Skarels iov = aiov; 26852481Storek needfree = NULL; 26952481Storek } 27037127Skarels auio.uio_iov = iov; 2717820Sroot auio.uio_iovcnt = uap->iovcnt; 27237728Smckusick auio.uio_rw = UIO_WRITE; 27337728Smckusick auio.uio_segflg = UIO_USERSPACE; 27448027Smckusick auio.uio_procp = p; 27544939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 27637127Skarels goto done; 27737728Smckusick auio.uio_resid = 0; 27837728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2797820Sroot if (iov->iov_len < 0) { 28037728Smckusick error = EINVAL; 28137728Smckusick goto done; 2827820Sroot } 28337728Smckusick auio.uio_resid += iov->iov_len; 28437728Smckusick if (auio.uio_resid < 0) { 28537728Smckusick error = EINVAL; 28637728Smckusick goto done; 2877820Sroot } 28813270Ssam iov++; 2897820Sroot } 29037127Skarels #ifdef KTRACE 29137728Smckusick /* 29237728Smckusick * if tracing, save a copy of iovec 29337728Smckusick */ 29442922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 29537127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 29637728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 29737127Skarels } 29837127Skarels #endif 29937728Smckusick cnt = auio.uio_resid; 30040703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 30140703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 30240703Skarels error == EINTR || error == EWOULDBLOCK)) 30340703Skarels error = 0; 30440703Skarels if (error == EPIPE) 30542922Smckusick psignal(p, SIGPIPE); 30640703Skarels } 30737728Smckusick cnt -= auio.uio_resid; 30837127Skarels #ifdef KTRACE 30937127Skarels if (ktriov != NULL) { 31041178Smarc if (error == 0) 31164409Sbostic ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 31243448Smckusick ktriov, cnt, error); 31337127Skarels FREE(ktriov, M_TEMP); 31437127Skarels } 31537127Skarels #endif 31642922Smckusick *retval = cnt; 31737728Smckusick done: 31852481Storek if (needfree) 31952481Storek FREE(needfree, M_IOV); 32044405Skarels return (error); 3217423Sroot } 3227423Sroot 3237423Sroot /* 3247423Sroot * Ioctl system call 3257423Sroot */ 32654930Storek struct ioctl_args { 32764409Sbostic int fd; 32864409Sbostic int com; 32964409Sbostic caddr_t data; 33054930Storek }; 33142922Smckusick /* ARGSUSED */ 33242922Smckusick ioctl(p, uap, retval) 33342922Smckusick struct proc *p; 33454930Storek register struct ioctl_args *uap; 33542922Smckusick int *retval; 33642922Smckusick { 33742922Smckusick register struct file *fp; 338*64538Sbostic register struct filedesc *fdp; 33940703Skarels register int com, error; 3407820Sroot register u_int size; 341*64538Sbostic caddr_t data, memp; 342*64538Sbostic int tmp; 34330530Skarels #define STK_PARAMS 128 34433480Skarels char stkbuf[STK_PARAMS]; 3457423Sroot 346*64538Sbostic fdp = p->p_fd; 34764409Sbostic if ((u_int)uap->fd >= fdp->fd_nfiles || 34864409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL) 34944405Skarels return (EBADF); 350*64538Sbostic 351*64538Sbostic if ((fp->f_flag & (FREAD | FWRITE)) == 0) 35244405Skarels return (EBADF); 3537624Ssam 354*64538Sbostic switch (com = uap->com) { 355*64538Sbostic case FIONCLEX: 356*64538Sbostic fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE; 357*64538Sbostic return (0); 358*64538Sbostic case FIOCLEX: 35964409Sbostic fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE; 36044405Skarels return (0); 3617423Sroot } 3627624Ssam 3637624Ssam /* 364*64538Sbostic * Interpret high order word to find amount of data to be 365*64538Sbostic * copied to/from the user's address space. 3667624Ssam */ 36730530Skarels size = IOCPARM_LEN(com); 36840703Skarels if (size > IOCPARM_MAX) 36944405Skarels return (ENOTTY); 370*64538Sbostic memp = NULL; 37133480Skarels if (size > sizeof (stkbuf)) { 37243383Smckusick memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 37331653Smckusick data = memp; 374*64538Sbostic } else 375*64538Sbostic data = stkbuf; 37610601Ssam if (com&IOC_IN) { 37710601Ssam if (size) { 37864409Sbostic error = copyin(uap->data, data, (u_int)size); 37940703Skarels if (error) { 38031653Smckusick if (memp) 38131653Smckusick free(memp, M_IOCTLOPS); 38244405Skarels return (error); 38331653Smckusick } 38410601Ssam } else 38564409Sbostic *(caddr_t *)data = uap->data; 38610601Ssam } else if ((com&IOC_OUT) && size) 38710601Ssam /* 38837127Skarels * Zero the buffer so the user always 38937127Skarels * gets back something deterministic. 39010601Ssam */ 39130530Skarels bzero(data, size); 39211284Ssam else if (com&IOC_VOID) 39364409Sbostic *(caddr_t *)data = uap->data; 3947423Sroot 39512751Ssam switch (com) { 3967624Ssam 39712751Ssam case FIONBIO: 39848027Smckusick if (tmp = *(int *)data) 39949941Smckusick fp->f_flag |= FNONBLOCK; 40048027Smckusick else 40149941Smckusick fp->f_flag &= ~FNONBLOCK; 40248027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 40330530Skarels break; 40412751Ssam 40512751Ssam case FIOASYNC: 40648027Smckusick if (tmp = *(int *)data) 40748027Smckusick fp->f_flag |= FASYNC; 40848027Smckusick else 40948027Smckusick fp->f_flag &= ~FASYNC; 41048027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 41130530Skarels break; 41212751Ssam 41312751Ssam case FIOSETOWN: 41448027Smckusick tmp = *(int *)data; 41548027Smckusick if (fp->f_type == DTYPE_SOCKET) { 41648027Smckusick ((struct socket *)fp->f_data)->so_pgid = tmp; 41748027Smckusick error = 0; 41848027Smckusick break; 41948027Smckusick } 42048027Smckusick if (tmp <= 0) { 42148027Smckusick tmp = -tmp; 42248027Smckusick } else { 42348027Smckusick struct proc *p1 = pfind(tmp); 42448027Smckusick if (p1 == 0) { 42548027Smckusick error = ESRCH; 42648027Smckusick break; 42748027Smckusick } 42848027Smckusick tmp = p1->p_pgrp->pg_id; 42948027Smckusick } 43048027Smckusick error = (*fp->f_ops->fo_ioctl) 43148027Smckusick (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); 43230530Skarels break; 43312751Ssam 43412751Ssam case FIOGETOWN: 43548027Smckusick if (fp->f_type == DTYPE_SOCKET) { 43648027Smckusick error = 0; 43748027Smckusick *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 43848027Smckusick break; 43948027Smckusick } 44048027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); 44148027Smckusick *(int *)data = -*(int *)data; 44230530Skarels break; 44348027Smckusick 44430530Skarels default: 44547540Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 44630530Skarels /* 44730530Skarels * Copy any data to user, size was 44830530Skarels * already set and checked above. 44930530Skarels */ 45040703Skarels if (error == 0 && (com&IOC_OUT) && size) 45164409Sbostic error = copyout(data, uap->data, (u_int)size); 45230530Skarels break; 4537423Sroot } 45431653Smckusick if (memp) 45531653Smckusick free(memp, M_IOCTLOPS); 45644405Skarels return (error); 4577423Sroot } 4587423Sroot 45949227Skarels int selwait, nselcoll; 46017593Skarels 4617423Sroot /* 46212751Ssam * Select system call. 4637423Sroot */ 46454930Storek struct select_args { 46563864Smckusick u_int nd; 46654930Storek fd_set *in, *ou, *ex; 46754930Storek struct timeval *tv; 46854930Storek }; 46942922Smckusick select(p, uap, retval) 47042922Smckusick register struct proc *p; 47154930Storek register struct select_args *uap; 47242922Smckusick int *retval; 47342922Smckusick { 47423523Skarels fd_set ibits[3], obits[3]; 47512751Ssam struct timeval atv; 47663864Smckusick int s, ncoll, error = 0, timo; 47763864Smckusick u_int ni; 47812751Ssam 47926277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 48026277Skarels bzero((caddr_t)obits, sizeof(obits)); 48163864Smckusick if (uap->nd > FD_SETSIZE) 48263864Smckusick return (EINVAL); 48347540Skarels if (uap->nd > p->p_fd->fd_nfiles) 48447540Skarels uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 48563864Smckusick ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask); 48612751Ssam 48712751Ssam #define getbits(name, x) \ 48863864Smckusick if (uap->name && \ 48963864Smckusick (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \ 49063864Smckusick goto done; 49112751Ssam getbits(in, 0); 49212751Ssam getbits(ou, 1); 49312751Ssam getbits(ex, 2); 49412751Ssam #undef getbits 49512751Ssam 49612751Ssam if (uap->tv) { 49740703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 49812751Ssam sizeof (atv)); 49940703Skarels if (error) 50012751Ssam goto done; 50112751Ssam if (itimerfix(&atv)) { 50240703Skarels error = EINVAL; 50312751Ssam goto done; 50412751Ssam } 50554760Storek s = splclock(); 50654760Storek timevaladd(&atv, (struct timeval *)&time); 50740703Skarels timo = hzto(&atv); 50858254Smckusick /* 50958254Smckusick * Avoid inadvertently sleeping forever. 51058254Smckusick */ 51158254Smckusick if (timo == 0) 51258254Smckusick timo = 1; 51354276Sbostic splx(s); 51440703Skarels } else 51540703Skarels timo = 0; 51612751Ssam retry: 51712751Ssam ncoll = nselcoll; 51842922Smckusick p->p_flag |= SSEL; 51947540Skarels error = selscan(p, ibits, obits, uap->nd, retval); 52042922Smckusick if (error || *retval) 52112751Ssam goto done; 52217934Skarels s = splhigh(); 52312971Ssam /* this should be timercmp(&time, &atv, >=) */ 52412971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 52512971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 52612751Ssam splx(s); 52712751Ssam goto done; 52812751Ssam } 52942922Smckusick if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { 53012751Ssam splx(s); 53112751Ssam goto retry; 53212751Ssam } 53342922Smckusick p->p_flag &= ~SSEL; 53440703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 53512751Ssam splx(s); 53640703Skarels if (error == 0) 53740703Skarels goto retry; 53812751Ssam done: 53942922Smckusick p->p_flag &= ~SSEL; 54040703Skarels /* select is not restarted after signals... */ 54140703Skarels if (error == ERESTART) 54240703Skarels error = EINTR; 54340703Skarels if (error == EWOULDBLOCK) 54440703Skarels error = 0; 54512751Ssam #define putbits(name, x) \ 54663864Smckusick if (uap->name && \ 54763864Smckusick (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \ 54863864Smckusick error = error2; 54940703Skarels if (error == 0) { 55063864Smckusick int error2; 55163864Smckusick 55221106Skarels putbits(in, 0); 55321106Skarels putbits(ou, 1); 55421106Skarels putbits(ex, 2); 55512751Ssam #undef putbits 55621106Skarels } 55744405Skarels return (error); 55812751Ssam } 55912751Ssam 56047540Skarels selscan(p, ibits, obits, nfd, retval) 56147540Skarels struct proc *p; 56223523Skarels fd_set *ibits, *obits; 56342922Smckusick int nfd, *retval; 56412751Ssam { 56547540Skarels register struct filedesc *fdp = p->p_fd; 56652481Storek register int msk, i, j, fd; 56723523Skarels register fd_mask bits; 56812751Ssam struct file *fp; 56952481Storek int n = 0; 57052481Storek static int flag[3] = { FREAD, FWRITE, 0 }; 57112751Ssam 57252481Storek for (msk = 0; msk < 3; msk++) { 57323523Skarels for (i = 0; i < nfd; i += NFDBITS) { 57452481Storek bits = ibits[msk].fds_bits[i/NFDBITS]; 57552481Storek while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 57617593Skarels bits &= ~(1 << j); 57752481Storek fp = fdp->fd_ofiles[fd]; 57852481Storek if (fp == NULL) 57952481Storek return (EBADF); 58052481Storek if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 58152481Storek FD_SET(fd, &obits[msk]); 58217593Skarels n++; 58317593Skarels } 58412751Ssam } 58512751Ssam } 58612751Ssam } 58742922Smckusick *retval = n; 58852481Storek return (0); 58912751Ssam } 59012751Ssam 5917423Sroot /*ARGSUSED*/ 59247540Skarels seltrue(dev, flag, p) 59312751Ssam dev_t dev; 59412751Ssam int flag; 59547540Skarels struct proc *p; 5967423Sroot { 5977423Sroot 59812751Ssam return (1); 5997423Sroot } 6008103Sroot 60152525Smckusick /* 60252525Smckusick * Record a select request. 60352525Smckusick */ 60452525Smckusick void 60552525Smckusick selrecord(selector, sip) 60652525Smckusick struct proc *selector; 60752525Smckusick struct selinfo *sip; 6088103Sroot { 60952525Smckusick struct proc *p; 61052525Smckusick pid_t mypid; 6118103Sroot 61252525Smckusick mypid = selector->p_pid; 61352525Smckusick if (sip->si_pid == mypid) 61452525Smckusick return; 61552525Smckusick if (sip->si_pid && (p = pfind(sip->si_pid)) && 61652525Smckusick p->p_wchan == (caddr_t)&selwait) 61752525Smckusick sip->si_flags |= SI_COLL; 61852525Smckusick else 61952525Smckusick sip->si_pid = mypid; 62052525Smckusick } 62152525Smckusick 62252525Smckusick /* 62352525Smckusick * Do a wakeup when a selectable event occurs. 62452525Smckusick */ 62552525Smckusick void 62652525Smckusick selwakeup(sip) 62752525Smckusick register struct selinfo *sip; 62852525Smckusick { 62952525Smckusick register struct proc *p; 63052525Smckusick int s; 63152525Smckusick 63252525Smckusick if (sip->si_pid == 0) 63352525Smckusick return; 63452525Smckusick if (sip->si_flags & SI_COLL) { 63512751Ssam nselcoll++; 63652525Smckusick sip->si_flags &= ~SI_COLL; 63712751Ssam wakeup((caddr_t)&selwait); 63812751Ssam } 63952922Smckusick p = pfind(sip->si_pid); 64052922Smckusick sip->si_pid = 0; 64152922Smckusick if (p != NULL) { 64252525Smckusick s = splhigh(); 64317270Skarels if (p->p_wchan == (caddr_t)&selwait) { 64417270Skarels if (p->p_stat == SSLEEP) 645*64538Sbostic setrunnable(p); 64617270Skarels else 64717270Skarels unsleep(p); 64817270Skarels } else if (p->p_flag & SSEL) 64912751Ssam p->p_flag &= ~SSEL; 65012751Ssam splx(s); 65112751Ssam } 6528103Sroot } 653