123384Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423384Smckusick * 544444Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*58254Smckusick * @(#)sys_generic.c 7.38 (Berkeley) 02/26/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 { 2954930Storek int fdes; 3054930Storek char *cbuf; 3154930Storek unsigned count; 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 4847540Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 4947974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 5037728Smckusick (fp->f_flag & FREAD) == 0) 5144405Skarels return (EBADF); 527820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 537820Sroot aiov.iov_len = uap->count; 547820Sroot auio.uio_iov = &aiov; 557820Sroot auio.uio_iovcnt = 1; 5637728Smckusick auio.uio_resid = uap->count; 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 6737728Smckusick cnt = uap->count; 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) 7543448Smckusick ktrgenio(p->p_tracep, uap->fdes, 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; 8754930Storek unsigned 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; 10144939Skarels unsigned iovlen; 10237728Smckusick #ifdef KTRACE 10337728Smckusick struct iovec *ktriov = NULL; 10437728Smckusick #endif 1057820Sroot 10647540Skarels if (((unsigned)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 { 17554930Storek int fdes; 17654930Storek char *cbuf; 17754930Storek unsigned count; 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 19347540Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 19447974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 19537728Smckusick (fp->f_flag & FWRITE) == 0) 19644405Skarels return (EBADF); 19737728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 19837728Smckusick aiov.iov_len = uap->count; 1997820Sroot auio.uio_iov = &aiov; 2007820Sroot auio.uio_iovcnt = 1; 20137728Smckusick auio.uio_resid = uap->count; 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 21237728Smckusick cnt = uap->count; 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) 22342922Smckusick ktrgenio(p->p_tracep, uap->fdes, 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 { 23454930Storek int fdes; 23554930Storek struct iovec *iovp; 23654930Storek unsigned 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; 25044939Skarels unsigned iovlen; 25137728Smckusick #ifdef KTRACE 25237728Smckusick struct iovec *ktriov = NULL; 25337728Smckusick #endif 2547820Sroot 25547540Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 25647974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == 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) 31142922Smckusick ktrgenio(p->p_tracep, uap->fdes, 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 { 32754930Storek int fdes; 32854930Storek int cmd; 32954930Storek caddr_t cmarg; 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 34747540Skarels if ((unsigned)uap->fdes >= fdp->fd_nfiles || 34847974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 34944405Skarels return (EBADF); 35040703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 35144405Skarels return (EBADF); 3527624Ssam com = uap->cmd; 3537624Ssam 3547624Ssam if (com == FIOCLEX) { 35547974Skarels fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE; 35644405Skarels return (0); 3577423Sroot } 3587624Ssam if (com == FIONCLEX) { 35947974Skarels fdp->fd_ofileflags[uap->fdes] &= ~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) { 37740703Skarels error = copyin(uap->cmarg, data, (u_int)size); 37840703Skarels if (error) { 37931653Smckusick if (memp) 38031653Smckusick free(memp, M_IOCTLOPS); 38144405Skarels return (error); 38231653Smckusick } 38310601Ssam } else 38410601Ssam *(caddr_t *)data = uap->cmarg; 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) 39211284Ssam *(caddr_t *)data = uap->cmarg; 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) 45040703Skarels error = copyout(data, uap->cmarg, (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 { 46454930Storek 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; 47540703Skarels int s, ncoll, ni, error = 0, timo; 47612751Ssam 47726277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 47826277Skarels bzero((caddr_t)obits, sizeof(obits)); 47947540Skarels if (uap->nd > p->p_fd->fd_nfiles) 48047540Skarels uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 48123523Skarels ni = howmany(uap->nd, NFDBITS); 48212751Ssam 48312751Ssam #define getbits(name, x) \ 48412751Ssam if (uap->name) { \ 48540703Skarels error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 48626277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 48740703Skarels if (error) \ 48812751Ssam goto done; \ 48917593Skarels } 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); 507*58254Smckusick /* 508*58254Smckusick * Avoid inadvertently sleeping forever. 509*58254Smckusick */ 510*58254Smckusick if (timo == 0) 511*58254Smckusick 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) \ 54512751Ssam if (uap->name) { \ 54640703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 54726277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 54840703Skarels if (error2) \ 54940703Skarels error = error2; \ 55012751Ssam } 55140703Skarels if (error == 0) { 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) 64517270Skarels setrun(p); 64617270Skarels else 64717270Skarels unsleep(p); 64817270Skarels } else if (p->p_flag & SSEL) 64912751Ssam p->p_flag &= ~SSEL; 65012751Ssam splx(s); 65112751Ssam } 6528103Sroot } 653