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*64409Sbostic * @(#)sys_generic.c 8.2 (Berkeley) 09/05/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 { 29*64409Sbostic int fd; 30*64409Sbostic char *buf; 31*64409Sbostic 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 48*64409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 49*64409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 5037728Smckusick (fp->f_flag & FREAD) == 0) 5144405Skarels return (EBADF); 52*64409Sbostic aiov.iov_base = (caddr_t)uap->buf; 53*64409Sbostic aiov.iov_len = uap->nbyte; 547820Sroot auio.uio_iov = &aiov; 557820Sroot auio.uio_iovcnt = 1; 56*64409Sbostic 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 67*64409Sbostic 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) 75*64409Sbostic 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; 87*64409Sbostic 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; 101*64409Sbostic u_int iovlen; 10237728Smckusick #ifdef KTRACE 10337728Smckusick struct iovec *ktriov = NULL; 10437728Smckusick #endif 1057820Sroot 106*64409Sbostic 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 { 175*64409Sbostic int fd; 176*64409Sbostic char *buf; 177*64409Sbostic 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 193*64409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 194*64409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL || 19537728Smckusick (fp->f_flag & FWRITE) == 0) 19644405Skarels return (EBADF); 197*64409Sbostic aiov.iov_base = (caddr_t)uap->buf; 198*64409Sbostic aiov.iov_len = uap->nbyte; 1997820Sroot auio.uio_iov = &aiov; 2007820Sroot auio.uio_iovcnt = 1; 201*64409Sbostic 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 212*64409Sbostic 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) 223*64409Sbostic 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 { 234*64409Sbostic int fd; 23554930Storek struct iovec *iovp; 236*64409Sbostic 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; 250*64409Sbostic u_int iovlen; 25137728Smckusick #ifdef KTRACE 25237728Smckusick struct iovec *ktriov = NULL; 25337728Smckusick #endif 2547820Sroot 255*64409Sbostic if (((u_int)uap->fd) >= fdp->fd_nfiles || 256*64409Sbostic (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) 311*64409Sbostic 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 { 327*64409Sbostic int fd; 328*64409Sbostic int com; 329*64409Sbostic 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; 33845914Smckusick register struct filedesc *fdp = p->p_fd; 33940703Skarels register int com, error; 3407820Sroot register u_int size; 34131653Smckusick caddr_t memp = 0; 34230530Skarels #define STK_PARAMS 128 34333480Skarels char stkbuf[STK_PARAMS]; 34433480Skarels caddr_t data = stkbuf; 34548027Smckusick int tmp; 3467423Sroot 347*64409Sbostic if ((u_int)uap->fd >= fdp->fd_nfiles || 348*64409Sbostic (fp = fdp->fd_ofiles[uap->fd]) == NULL) 34944405Skarels return (EBADF); 35040703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 35144405Skarels return (EBADF); 352*64409Sbostic com = uap->com; 3537624Ssam 3547624Ssam if (com == FIOCLEX) { 355*64409Sbostic fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE; 35644405Skarels return (0); 3577423Sroot } 3587624Ssam if (com == FIONCLEX) { 359*64409Sbostic fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE; 36044405Skarels return (0); 3617423Sroot } 3627624Ssam 3637624Ssam /* 3647624Ssam * Interpret high order word to find 3657624Ssam * amount of data to be copied to/from the 3667624Ssam * user's address space. 3677624Ssam */ 36830530Skarels size = IOCPARM_LEN(com); 36940703Skarels if (size > IOCPARM_MAX) 37044405Skarels return (ENOTTY); 37133480Skarels if (size > sizeof (stkbuf)) { 37243383Smckusick memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 37331653Smckusick data = memp; 37430530Skarels } 37510601Ssam if (com&IOC_IN) { 37610601Ssam if (size) { 377*64409Sbostic error = copyin(uap->data, data, (u_int)size); 37840703Skarels if (error) { 37931653Smckusick if (memp) 38031653Smckusick free(memp, M_IOCTLOPS); 38144405Skarels return (error); 38231653Smckusick } 38310601Ssam } else 384*64409Sbostic *(caddr_t *)data = uap->data; 38510601Ssam } else if ((com&IOC_OUT) && size) 38610601Ssam /* 38737127Skarels * Zero the buffer so the user always 38837127Skarels * gets back something deterministic. 38910601Ssam */ 39030530Skarels bzero(data, size); 39111284Ssam else if (com&IOC_VOID) 392*64409Sbostic *(caddr_t *)data = uap->data; 3937423Sroot 39412751Ssam switch (com) { 3957624Ssam 39612751Ssam case FIONBIO: 39748027Smckusick if (tmp = *(int *)data) 39849941Smckusick fp->f_flag |= FNONBLOCK; 39948027Smckusick else 40049941Smckusick fp->f_flag &= ~FNONBLOCK; 40148027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 40230530Skarels break; 40312751Ssam 40412751Ssam case FIOASYNC: 40548027Smckusick if (tmp = *(int *)data) 40648027Smckusick fp->f_flag |= FASYNC; 40748027Smckusick else 40848027Smckusick fp->f_flag &= ~FASYNC; 40948027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 41030530Skarels break; 41112751Ssam 41212751Ssam case FIOSETOWN: 41348027Smckusick tmp = *(int *)data; 41448027Smckusick if (fp->f_type == DTYPE_SOCKET) { 41548027Smckusick ((struct socket *)fp->f_data)->so_pgid = tmp; 41648027Smckusick error = 0; 41748027Smckusick break; 41848027Smckusick } 41948027Smckusick if (tmp <= 0) { 42048027Smckusick tmp = -tmp; 42148027Smckusick } else { 42248027Smckusick struct proc *p1 = pfind(tmp); 42348027Smckusick if (p1 == 0) { 42448027Smckusick error = ESRCH; 42548027Smckusick break; 42648027Smckusick } 42748027Smckusick tmp = p1->p_pgrp->pg_id; 42848027Smckusick } 42948027Smckusick error = (*fp->f_ops->fo_ioctl) 43048027Smckusick (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); 43130530Skarels break; 43212751Ssam 43312751Ssam case FIOGETOWN: 43448027Smckusick if (fp->f_type == DTYPE_SOCKET) { 43548027Smckusick error = 0; 43648027Smckusick *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 43748027Smckusick break; 43848027Smckusick } 43948027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); 44048027Smckusick *(int *)data = -*(int *)data; 44130530Skarels break; 44248027Smckusick 44330530Skarels default: 44447540Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 44530530Skarels /* 44630530Skarels * Copy any data to user, size was 44730530Skarels * already set and checked above. 44830530Skarels */ 44940703Skarels if (error == 0 && (com&IOC_OUT) && size) 450*64409Sbostic error = copyout(data, uap->data, (u_int)size); 45130530Skarels break; 4527423Sroot } 45331653Smckusick if (memp) 45431653Smckusick free(memp, M_IOCTLOPS); 45544405Skarels return (error); 4567423Sroot } 4577423Sroot 45849227Skarels int selwait, nselcoll; 45917593Skarels 4607423Sroot /* 46112751Ssam * Select system call. 4627423Sroot */ 46354930Storek struct select_args { 46463864Smckusick u_int nd; 46554930Storek fd_set *in, *ou, *ex; 46654930Storek struct timeval *tv; 46754930Storek }; 46842922Smckusick select(p, uap, retval) 46942922Smckusick register struct proc *p; 47054930Storek register struct select_args *uap; 47142922Smckusick int *retval; 47242922Smckusick { 47323523Skarels fd_set ibits[3], obits[3]; 47412751Ssam struct timeval atv; 47563864Smckusick int s, ncoll, error = 0, timo; 47663864Smckusick u_int ni; 47712751Ssam 47826277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 47926277Skarels bzero((caddr_t)obits, sizeof(obits)); 48063864Smckusick if (uap->nd > FD_SETSIZE) 48163864Smckusick return (EINVAL); 48247540Skarels if (uap->nd > p->p_fd->fd_nfiles) 48347540Skarels uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 48463864Smckusick ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask); 48512751Ssam 48612751Ssam #define getbits(name, x) \ 48763864Smckusick if (uap->name && \ 48863864Smckusick (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \ 48963864Smckusick goto done; 49012751Ssam getbits(in, 0); 49112751Ssam getbits(ou, 1); 49212751Ssam getbits(ex, 2); 49312751Ssam #undef getbits 49412751Ssam 49512751Ssam if (uap->tv) { 49640703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 49712751Ssam sizeof (atv)); 49840703Skarels if (error) 49912751Ssam goto done; 50012751Ssam if (itimerfix(&atv)) { 50140703Skarels error = EINVAL; 50212751Ssam goto done; 50312751Ssam } 50454760Storek s = splclock(); 50554760Storek timevaladd(&atv, (struct timeval *)&time); 50640703Skarels timo = hzto(&atv); 50758254Smckusick /* 50858254Smckusick * Avoid inadvertently sleeping forever. 50958254Smckusick */ 51058254Smckusick if (timo == 0) 51158254Smckusick timo = 1; 51254276Sbostic splx(s); 51340703Skarels } else 51440703Skarels timo = 0; 51512751Ssam retry: 51612751Ssam ncoll = nselcoll; 51742922Smckusick p->p_flag |= SSEL; 51847540Skarels error = selscan(p, ibits, obits, uap->nd, retval); 51942922Smckusick if (error || *retval) 52012751Ssam goto done; 52117934Skarels s = splhigh(); 52212971Ssam /* this should be timercmp(&time, &atv, >=) */ 52312971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 52412971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 52512751Ssam splx(s); 52612751Ssam goto done; 52712751Ssam } 52842922Smckusick if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { 52912751Ssam splx(s); 53012751Ssam goto retry; 53112751Ssam } 53242922Smckusick p->p_flag &= ~SSEL; 53340703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 53412751Ssam splx(s); 53540703Skarels if (error == 0) 53640703Skarels goto retry; 53712751Ssam done: 53842922Smckusick p->p_flag &= ~SSEL; 53940703Skarels /* select is not restarted after signals... */ 54040703Skarels if (error == ERESTART) 54140703Skarels error = EINTR; 54240703Skarels if (error == EWOULDBLOCK) 54340703Skarels error = 0; 54412751Ssam #define putbits(name, x) \ 54563864Smckusick if (uap->name && \ 54663864Smckusick (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \ 54763864Smckusick error = error2; 54840703Skarels if (error == 0) { 54963864Smckusick int error2; 55063864Smckusick 55121106Skarels putbits(in, 0); 55221106Skarels putbits(ou, 1); 55321106Skarels putbits(ex, 2); 55412751Ssam #undef putbits 55521106Skarels } 55644405Skarels return (error); 55712751Ssam } 55812751Ssam 55947540Skarels selscan(p, ibits, obits, nfd, retval) 56047540Skarels struct proc *p; 56123523Skarels fd_set *ibits, *obits; 56242922Smckusick int nfd, *retval; 56312751Ssam { 56447540Skarels register struct filedesc *fdp = p->p_fd; 56552481Storek register int msk, i, j, fd; 56623523Skarels register fd_mask bits; 56712751Ssam struct file *fp; 56852481Storek int n = 0; 56952481Storek static int flag[3] = { FREAD, FWRITE, 0 }; 57012751Ssam 57152481Storek for (msk = 0; msk < 3; msk++) { 57223523Skarels for (i = 0; i < nfd; i += NFDBITS) { 57352481Storek bits = ibits[msk].fds_bits[i/NFDBITS]; 57452481Storek while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 57517593Skarels bits &= ~(1 << j); 57652481Storek fp = fdp->fd_ofiles[fd]; 57752481Storek if (fp == NULL) 57852481Storek return (EBADF); 57952481Storek if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 58052481Storek FD_SET(fd, &obits[msk]); 58117593Skarels n++; 58217593Skarels } 58312751Ssam } 58412751Ssam } 58512751Ssam } 58642922Smckusick *retval = n; 58752481Storek return (0); 58812751Ssam } 58912751Ssam 5907423Sroot /*ARGSUSED*/ 59147540Skarels seltrue(dev, flag, p) 59212751Ssam dev_t dev; 59312751Ssam int flag; 59447540Skarels struct proc *p; 5957423Sroot { 5967423Sroot 59712751Ssam return (1); 5987423Sroot } 5998103Sroot 60052525Smckusick /* 60152525Smckusick * Record a select request. 60252525Smckusick */ 60352525Smckusick void 60452525Smckusick selrecord(selector, sip) 60552525Smckusick struct proc *selector; 60652525Smckusick struct selinfo *sip; 6078103Sroot { 60852525Smckusick struct proc *p; 60952525Smckusick pid_t mypid; 6108103Sroot 61152525Smckusick mypid = selector->p_pid; 61252525Smckusick if (sip->si_pid == mypid) 61352525Smckusick return; 61452525Smckusick if (sip->si_pid && (p = pfind(sip->si_pid)) && 61552525Smckusick p->p_wchan == (caddr_t)&selwait) 61652525Smckusick sip->si_flags |= SI_COLL; 61752525Smckusick else 61852525Smckusick sip->si_pid = mypid; 61952525Smckusick } 62052525Smckusick 62152525Smckusick /* 62252525Smckusick * Do a wakeup when a selectable event occurs. 62352525Smckusick */ 62452525Smckusick void 62552525Smckusick selwakeup(sip) 62652525Smckusick register struct selinfo *sip; 62752525Smckusick { 62852525Smckusick register struct proc *p; 62952525Smckusick int s; 63052525Smckusick 63152525Smckusick if (sip->si_pid == 0) 63252525Smckusick return; 63352525Smckusick if (sip->si_flags & SI_COLL) { 63412751Ssam nselcoll++; 63552525Smckusick sip->si_flags &= ~SI_COLL; 63612751Ssam wakeup((caddr_t)&selwait); 63712751Ssam } 63852922Smckusick p = pfind(sip->si_pid); 63952922Smckusick sip->si_pid = 0; 64052922Smckusick if (p != NULL) { 64152525Smckusick s = splhigh(); 64217270Skarels if (p->p_wchan == (caddr_t)&selwait) { 64317270Skarels if (p->p_stat == SSLEEP) 64417270Skarels setrun(p); 64517270Skarels else 64617270Skarels unsleep(p); 64717270Skarels } else if (p->p_flag & SSEL) 64812751Ssam p->p_flag &= ~SSEL; 64912751Ssam splx(s); 65012751Ssam } 6518103Sroot } 652