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*54930Storek * @(#)sys_generic.c 7.36 (Berkeley) 07/10/92 823384Smckusick */ 97423Sroot 1017094Sbloom #include "param.h" 1117094Sbloom #include "systm.h" 1245914Smckusick #include "filedesc.h" 1317094Sbloom #include "ioctl.h" 1417094Sbloom #include "file.h" 1552525Smckusick #include "proc.h" 1648027Smckusick #include "socketvar.h" 1717094Sbloom #include "uio.h" 1817094Sbloom #include "kernel.h" 1917094Sbloom #include "stat.h" 2031653Smckusick #include "malloc.h" 2137127Skarels #ifdef KTRACE 2237127Skarels #include "ktrace.h" 2337127Skarels #endif 247423Sroot 257423Sroot /* 267423Sroot * Read system call. 277423Sroot */ 28*54930Storek struct read_args { 29*54930Storek int fdes; 30*54930Storek char *cbuf; 31*54930Storek unsigned count; 32*54930Storek }; 3345122Sbostic /* ARGSUSED */ 3442922Smckusick read(p, uap, retval) 3542922Smckusick struct proc *p; 36*54930Storek 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 */ 84*54930Storek struct readv_args { 85*54930Storek int fdes; 86*54930Storek struct iovec *iovp; 87*54930Storek unsigned iovcnt; 88*54930Storek }; 8942922Smckusick readv(p, uap, retval) 9042922Smckusick struct proc *p; 91*54930Storek 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 */ 174*54930Storek struct write_args { 175*54930Storek int fdes; 176*54930Storek char *cbuf; 177*54930Storek unsigned count; 178*54930Storek }; 17942922Smckusick write(p, uap, retval) 18042922Smckusick struct proc *p; 181*54930Storek 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 */ 233*54930Storek struct writev_args { 234*54930Storek int fdes; 235*54930Storek struct iovec *iovp; 236*54930Storek unsigned iovcnt; 237*54930Storek }; 23842922Smckusick writev(p, uap, retval) 23942922Smckusick struct proc *p; 240*54930Storek 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 */ 326*54930Storek struct ioctl_args { 327*54930Storek int fdes; 328*54930Storek int cmd; 329*54930Storek caddr_t cmarg; 330*54930Storek }; 33142922Smckusick /* ARGSUSED */ 33242922Smckusick ioctl(p, uap, retval) 33342922Smckusick struct proc *p; 334*54930Storek 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 */ 463*54930Storek struct select_args { 464*54930Storek int nd; 465*54930Storek fd_set *in, *ou, *ex; 466*54930Storek struct timeval *tv; 467*54930Storek }; 46842922Smckusick select(p, uap, retval) 46942922Smckusick register struct proc *p; 470*54930Storek 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); 50754276Sbostic splx(s); 50840703Skarels } else 50940703Skarels timo = 0; 51012751Ssam retry: 51112751Ssam ncoll = nselcoll; 51242922Smckusick p->p_flag |= SSEL; 51347540Skarels error = selscan(p, ibits, obits, uap->nd, retval); 51442922Smckusick if (error || *retval) 51512751Ssam goto done; 51617934Skarels s = splhigh(); 51712971Ssam /* this should be timercmp(&time, &atv, >=) */ 51812971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 51912971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 52012751Ssam splx(s); 52112751Ssam goto done; 52212751Ssam } 52342922Smckusick if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { 52412751Ssam splx(s); 52512751Ssam goto retry; 52612751Ssam } 52742922Smckusick p->p_flag &= ~SSEL; 52840703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 52912751Ssam splx(s); 53040703Skarels if (error == 0) 53140703Skarels goto retry; 53212751Ssam done: 53342922Smckusick p->p_flag &= ~SSEL; 53440703Skarels /* select is not restarted after signals... */ 53540703Skarels if (error == ERESTART) 53640703Skarels error = EINTR; 53740703Skarels if (error == EWOULDBLOCK) 53840703Skarels error = 0; 53912751Ssam #define putbits(name, x) \ 54012751Ssam if (uap->name) { \ 54140703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 54226277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 54340703Skarels if (error2) \ 54440703Skarels error = error2; \ 54512751Ssam } 54640703Skarels if (error == 0) { 54721106Skarels putbits(in, 0); 54821106Skarels putbits(ou, 1); 54921106Skarels putbits(ex, 2); 55012751Ssam #undef putbits 55121106Skarels } 55244405Skarels return (error); 55312751Ssam } 55412751Ssam 55547540Skarels selscan(p, ibits, obits, nfd, retval) 55647540Skarels struct proc *p; 55723523Skarels fd_set *ibits, *obits; 55842922Smckusick int nfd, *retval; 55912751Ssam { 56047540Skarels register struct filedesc *fdp = p->p_fd; 56152481Storek register int msk, i, j, fd; 56223523Skarels register fd_mask bits; 56312751Ssam struct file *fp; 56452481Storek int n = 0; 56552481Storek static int flag[3] = { FREAD, FWRITE, 0 }; 56612751Ssam 56752481Storek for (msk = 0; msk < 3; msk++) { 56823523Skarels for (i = 0; i < nfd; i += NFDBITS) { 56952481Storek bits = ibits[msk].fds_bits[i/NFDBITS]; 57052481Storek while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 57117593Skarels bits &= ~(1 << j); 57252481Storek fp = fdp->fd_ofiles[fd]; 57352481Storek if (fp == NULL) 57452481Storek return (EBADF); 57552481Storek if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 57652481Storek FD_SET(fd, &obits[msk]); 57717593Skarels n++; 57817593Skarels } 57912751Ssam } 58012751Ssam } 58112751Ssam } 58242922Smckusick *retval = n; 58352481Storek return (0); 58412751Ssam } 58512751Ssam 5867423Sroot /*ARGSUSED*/ 58747540Skarels seltrue(dev, flag, p) 58812751Ssam dev_t dev; 58912751Ssam int flag; 59047540Skarels struct proc *p; 5917423Sroot { 5927423Sroot 59312751Ssam return (1); 5947423Sroot } 5958103Sroot 59652525Smckusick /* 59752525Smckusick * Record a select request. 59852525Smckusick */ 59952525Smckusick void 60052525Smckusick selrecord(selector, sip) 60152525Smckusick struct proc *selector; 60252525Smckusick struct selinfo *sip; 6038103Sroot { 60452525Smckusick struct proc *p; 60552525Smckusick pid_t mypid; 6068103Sroot 60752525Smckusick mypid = selector->p_pid; 60852525Smckusick if (sip->si_pid == mypid) 60952525Smckusick return; 61052525Smckusick if (sip->si_pid && (p = pfind(sip->si_pid)) && 61152525Smckusick p->p_wchan == (caddr_t)&selwait) 61252525Smckusick sip->si_flags |= SI_COLL; 61352525Smckusick else 61452525Smckusick sip->si_pid = mypid; 61552525Smckusick } 61652525Smckusick 61752525Smckusick /* 61852525Smckusick * Do a wakeup when a selectable event occurs. 61952525Smckusick */ 62052525Smckusick void 62152525Smckusick selwakeup(sip) 62252525Smckusick register struct selinfo *sip; 62352525Smckusick { 62452525Smckusick register struct proc *p; 62552525Smckusick int s; 62652525Smckusick 62752525Smckusick if (sip->si_pid == 0) 62852525Smckusick return; 62952525Smckusick if (sip->si_flags & SI_COLL) { 63012751Ssam nselcoll++; 63152525Smckusick sip->si_flags &= ~SI_COLL; 63212751Ssam wakeup((caddr_t)&selwait); 63312751Ssam } 63452922Smckusick p = pfind(sip->si_pid); 63552922Smckusick sip->si_pid = 0; 63652922Smckusick if (p != NULL) { 63752525Smckusick s = splhigh(); 63817270Skarels if (p->p_wchan == (caddr_t)&selwait) { 63917270Skarels if (p->p_stat == SSLEEP) 64017270Skarels setrun(p); 64117270Skarels else 64217270Skarels unsleep(p); 64317270Skarels } else if (p->p_flag & SSEL) 64412751Ssam p->p_flag &= ~SSEL; 64512751Ssam splx(s); 64612751Ssam } 6478103Sroot } 648