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*54760Storek * @(#)sys_generic.c 7.35 (Berkeley) 07/07/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 */ 2845122Sbostic /* ARGSUSED */ 2942922Smckusick read(p, uap, retval) 3042922Smckusick struct proc *p; 3142922Smckusick register struct args { 327423Sroot int fdes; 337423Sroot char *cbuf; 347423Sroot unsigned count; 3542922Smckusick } *uap; 3642922Smckusick int *retval; 3742922Smckusick { 3837728Smckusick register struct file *fp; 3945914Smckusick register struct filedesc *fdp = p->p_fd; 407746Sroot struct uio auio; 417746Sroot struct iovec aiov; 4237728Smckusick long cnt, error = 0; 4337728Smckusick #ifdef KTRACE 4437728Smckusick struct iovec ktriov; 4537728Smckusick #endif 467423Sroot 4747540Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 4847974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 4937728Smckusick (fp->f_flag & FREAD) == 0) 5044405Skarels return (EBADF); 517820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 527820Sroot aiov.iov_len = uap->count; 537820Sroot auio.uio_iov = &aiov; 547820Sroot auio.uio_iovcnt = 1; 5537728Smckusick auio.uio_resid = uap->count; 5637728Smckusick auio.uio_rw = UIO_READ; 5737728Smckusick auio.uio_segflg = UIO_USERSPACE; 5848027Smckusick auio.uio_procp = p; 5937728Smckusick #ifdef KTRACE 6037728Smckusick /* 6137728Smckusick * if tracing, save a copy of iovec 6237728Smckusick */ 6342922Smckusick if (KTRPOINT(p, KTR_GENIO)) 6437728Smckusick ktriov = aiov; 6537728Smckusick #endif 6637728Smckusick cnt = uap->count; 6740703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 6840703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 6940703Skarels error == EINTR || error == EWOULDBLOCK)) 7040703Skarels error = 0; 7137728Smckusick cnt -= auio.uio_resid; 7237728Smckusick #ifdef KTRACE 7342922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 7443448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error); 7537728Smckusick #endif 7642922Smckusick *retval = cnt; 7744405Skarels return (error); 787820Sroot } 797820Sroot 8042922Smckusick /* 8142922Smckusick * Scatter read system call. 8242922Smckusick */ 8345122Sbostic /* ARGSUSED */ 8442922Smckusick readv(p, uap, retval) 8542922Smckusick struct proc *p; 8642922Smckusick register struct args { 877820Sroot int fdes; 887820Sroot struct iovec *iovp; 8926474Skarels unsigned iovcnt; 9042922Smckusick } *uap; 9142922Smckusick int *retval; 9242922Smckusick { 9337728Smckusick register struct file *fp; 9445914Smckusick register struct filedesc *fdp = p->p_fd; 957820Sroot struct uio auio; 9637728Smckusick register struct iovec *iov; 9752481Storek struct iovec *needfree; 9837728Smckusick struct iovec aiov[UIO_SMALLIOV]; 9937728Smckusick long i, cnt, error = 0; 10044939Skarels unsigned iovlen; 10137728Smckusick #ifdef KTRACE 10237728Smckusick struct iovec *ktriov = NULL; 10337728Smckusick #endif 1047820Sroot 10547540Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 10647974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 10737728Smckusick (fp->f_flag & FREAD) == 0) 10844405Skarels return (EBADF); 10944939Skarels /* note: can't use iovlen until iovcnt is validated */ 11044939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 11137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 11237728Smckusick if (uap->iovcnt > UIO_MAXIOV) 11344405Skarels return (EINVAL); 11444939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 11552481Storek needfree = iov; 11652481Storek } else { 11737127Skarels iov = aiov; 11852481Storek needfree = NULL; 11952481Storek } 12037127Skarels auio.uio_iov = iov; 1217820Sroot auio.uio_iovcnt = uap->iovcnt; 12237728Smckusick auio.uio_rw = UIO_READ; 12337728Smckusick auio.uio_segflg = UIO_USERSPACE; 12448027Smckusick auio.uio_procp = p; 12544939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 12637127Skarels goto done; 12737728Smckusick auio.uio_resid = 0; 12837728Smckusick for (i = 0; i < uap->iovcnt; i++) { 12937728Smckusick if (iov->iov_len < 0) { 13037728Smckusick error = EINVAL; 13137728Smckusick goto done; 13237728Smckusick } 13337728Smckusick auio.uio_resid += iov->iov_len; 13437728Smckusick if (auio.uio_resid < 0) { 13537728Smckusick error = EINVAL; 13637728Smckusick goto done; 13737728Smckusick } 13837728Smckusick iov++; 13937728Smckusick } 14037728Smckusick #ifdef KTRACE 14137728Smckusick /* 14237728Smckusick * if tracing, save a copy of iovec 14337728Smckusick */ 14442922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 14537728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 14637728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 14737728Smckusick } 14837728Smckusick #endif 14937728Smckusick cnt = auio.uio_resid; 15040703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 15140703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 15240703Skarels error == EINTR || error == EWOULDBLOCK)) 15340703Skarels error = 0; 15437728Smckusick cnt -= auio.uio_resid; 15537728Smckusick #ifdef KTRACE 15637728Smckusick if (ktriov != NULL) { 15741178Smarc if (error == 0) 15843448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 15943448Smckusick cnt, error); 16037728Smckusick FREE(ktriov, M_TEMP); 16137728Smckusick } 16237728Smckusick #endif 16342922Smckusick *retval = cnt; 16437127Skarels done: 16552481Storek if (needfree) 16652481Storek FREE(needfree, M_IOV); 16744405Skarels return (error); 1687423Sroot } 1697423Sroot 1707423Sroot /* 1717423Sroot * Write system call 1727423Sroot */ 17342922Smckusick write(p, uap, retval) 17442922Smckusick struct proc *p; 17542922Smckusick register struct args { 1767423Sroot int fdes; 1777423Sroot char *cbuf; 17826474Skarels unsigned count; 17942922Smckusick } *uap; 18042922Smckusick int *retval; 18142922Smckusick { 18237728Smckusick register struct file *fp; 18345914Smckusick register struct filedesc *fdp = p->p_fd; 1847820Sroot struct uio auio; 1857820Sroot struct iovec aiov; 18637728Smckusick long cnt, error = 0; 18737728Smckusick #ifdef KTRACE 18837728Smckusick struct iovec ktriov; 18937728Smckusick #endif 1907423Sroot 19147540Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 19247974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 19337728Smckusick (fp->f_flag & FWRITE) == 0) 19444405Skarels return (EBADF); 19537728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 19637728Smckusick aiov.iov_len = uap->count; 1977820Sroot auio.uio_iov = &aiov; 1987820Sroot auio.uio_iovcnt = 1; 19937728Smckusick auio.uio_resid = uap->count; 20037728Smckusick auio.uio_rw = UIO_WRITE; 20137728Smckusick auio.uio_segflg = UIO_USERSPACE; 20248027Smckusick auio.uio_procp = p; 20337728Smckusick #ifdef KTRACE 20437728Smckusick /* 20537728Smckusick * if tracing, save a copy of iovec 20637728Smckusick */ 20742922Smckusick if (KTRPOINT(p, KTR_GENIO)) 20837728Smckusick ktriov = aiov; 20937728Smckusick #endif 21037728Smckusick cnt = uap->count; 21140703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 21240703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 21340703Skarels error == EINTR || error == EWOULDBLOCK)) 21440703Skarels error = 0; 21540703Skarels if (error == EPIPE) 21642922Smckusick psignal(p, SIGPIPE); 21740703Skarels } 21837728Smckusick cnt -= auio.uio_resid; 21937728Smckusick #ifdef KTRACE 22042922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 22142922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 22243448Smckusick &ktriov, cnt, error); 22337728Smckusick #endif 22442922Smckusick *retval = cnt; 22544405Skarels return (error); 2267820Sroot } 2277820Sroot 22842922Smckusick /* 22942922Smckusick * Gather write system call 23042922Smckusick */ 23142922Smckusick writev(p, uap, retval) 23242922Smckusick struct proc *p; 23342922Smckusick register struct args { 2347820Sroot int fdes; 2357820Sroot struct iovec *iovp; 23626474Skarels unsigned iovcnt; 23742922Smckusick } *uap; 23842922Smckusick int *retval; 23942922Smckusick { 24037728Smckusick register struct file *fp; 24145914Smckusick register struct filedesc *fdp = p->p_fd; 2427820Sroot struct uio auio; 24337728Smckusick register struct iovec *iov; 24452481Storek struct iovec *needfree; 24537728Smckusick struct iovec aiov[UIO_SMALLIOV]; 24637728Smckusick long i, cnt, error = 0; 24744939Skarels unsigned iovlen; 24837728Smckusick #ifdef KTRACE 24937728Smckusick struct iovec *ktriov = NULL; 25037728Smckusick #endif 2517820Sroot 25247540Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 25347974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 25437728Smckusick (fp->f_flag & FWRITE) == 0) 25544405Skarels return (EBADF); 25644939Skarels /* note: can't use iovlen until iovcnt is validated */ 25744939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 25837127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 25937728Smckusick if (uap->iovcnt > UIO_MAXIOV) 26044405Skarels return (EINVAL); 26144939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 26252481Storek needfree = iov; 26352481Storek } else { 26437127Skarels iov = aiov; 26552481Storek needfree = NULL; 26652481Storek } 26737127Skarels auio.uio_iov = iov; 2687820Sroot auio.uio_iovcnt = uap->iovcnt; 26937728Smckusick auio.uio_rw = UIO_WRITE; 27037728Smckusick auio.uio_segflg = UIO_USERSPACE; 27148027Smckusick auio.uio_procp = p; 27244939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 27337127Skarels goto done; 27437728Smckusick auio.uio_resid = 0; 27537728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2767820Sroot if (iov->iov_len < 0) { 27737728Smckusick error = EINVAL; 27837728Smckusick goto done; 2797820Sroot } 28037728Smckusick auio.uio_resid += iov->iov_len; 28137728Smckusick if (auio.uio_resid < 0) { 28237728Smckusick error = EINVAL; 28337728Smckusick goto done; 2847820Sroot } 28513270Ssam iov++; 2867820Sroot } 28737127Skarels #ifdef KTRACE 28837728Smckusick /* 28937728Smckusick * if tracing, save a copy of iovec 29037728Smckusick */ 29142922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 29237127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 29337728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 29437127Skarels } 29537127Skarels #endif 29637728Smckusick cnt = auio.uio_resid; 29740703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 29840703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 29940703Skarels error == EINTR || error == EWOULDBLOCK)) 30040703Skarels error = 0; 30140703Skarels if (error == EPIPE) 30242922Smckusick psignal(p, SIGPIPE); 30340703Skarels } 30437728Smckusick cnt -= auio.uio_resid; 30537127Skarels #ifdef KTRACE 30637127Skarels if (ktriov != NULL) { 30741178Smarc if (error == 0) 30842922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 30943448Smckusick ktriov, cnt, error); 31037127Skarels FREE(ktriov, M_TEMP); 31137127Skarels } 31237127Skarels #endif 31342922Smckusick *retval = cnt; 31437728Smckusick done: 31552481Storek if (needfree) 31652481Storek FREE(needfree, M_IOV); 31744405Skarels return (error); 3187423Sroot } 3197423Sroot 3207423Sroot /* 3217423Sroot * Ioctl system call 3227423Sroot */ 32342922Smckusick /* ARGSUSED */ 32442922Smckusick ioctl(p, uap, retval) 32542922Smckusick struct proc *p; 32642922Smckusick register struct args { 3277423Sroot int fdes; 3287423Sroot int cmd; 3297423Sroot caddr_t cmarg; 33042922Smckusick } *uap; 33142922Smckusick int *retval; 33242922Smckusick { 33342922Smckusick register struct file *fp; 33445914Smckusick register struct filedesc *fdp = p->p_fd; 33540703Skarels register int com, error; 3367820Sroot register u_int size; 33731653Smckusick caddr_t memp = 0; 33830530Skarels #define STK_PARAMS 128 33933480Skarels char stkbuf[STK_PARAMS]; 34033480Skarels caddr_t data = stkbuf; 34148027Smckusick int tmp; 3427423Sroot 34347540Skarels if ((unsigned)uap->fdes >= fdp->fd_nfiles || 34447974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 34544405Skarels return (EBADF); 34640703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 34744405Skarels return (EBADF); 3487624Ssam com = uap->cmd; 3497624Ssam 3507624Ssam if (com == FIOCLEX) { 35147974Skarels fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE; 35244405Skarels return (0); 3537423Sroot } 3547624Ssam if (com == FIONCLEX) { 35547974Skarels fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE; 35644405Skarels return (0); 3577423Sroot } 3587624Ssam 3597624Ssam /* 3607624Ssam * Interpret high order word to find 3617624Ssam * amount of data to be copied to/from the 3627624Ssam * user's address space. 3637624Ssam */ 36430530Skarels size = IOCPARM_LEN(com); 36540703Skarels if (size > IOCPARM_MAX) 36644405Skarels return (ENOTTY); 36733480Skarels if (size > sizeof (stkbuf)) { 36843383Smckusick memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 36931653Smckusick data = memp; 37030530Skarels } 37110601Ssam if (com&IOC_IN) { 37210601Ssam if (size) { 37340703Skarels error = copyin(uap->cmarg, data, (u_int)size); 37440703Skarels if (error) { 37531653Smckusick if (memp) 37631653Smckusick free(memp, M_IOCTLOPS); 37744405Skarels return (error); 37831653Smckusick } 37910601Ssam } else 38010601Ssam *(caddr_t *)data = uap->cmarg; 38110601Ssam } else if ((com&IOC_OUT) && size) 38210601Ssam /* 38337127Skarels * Zero the buffer so the user always 38437127Skarels * gets back something deterministic. 38510601Ssam */ 38630530Skarels bzero(data, size); 38711284Ssam else if (com&IOC_VOID) 38811284Ssam *(caddr_t *)data = uap->cmarg; 3897423Sroot 39012751Ssam switch (com) { 3917624Ssam 39212751Ssam case FIONBIO: 39348027Smckusick if (tmp = *(int *)data) 39449941Smckusick fp->f_flag |= FNONBLOCK; 39548027Smckusick else 39649941Smckusick fp->f_flag &= ~FNONBLOCK; 39748027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 39830530Skarels break; 39912751Ssam 40012751Ssam case FIOASYNC: 40148027Smckusick if (tmp = *(int *)data) 40248027Smckusick fp->f_flag |= FASYNC; 40348027Smckusick else 40448027Smckusick fp->f_flag &= ~FASYNC; 40548027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 40630530Skarels break; 40712751Ssam 40812751Ssam case FIOSETOWN: 40948027Smckusick tmp = *(int *)data; 41048027Smckusick if (fp->f_type == DTYPE_SOCKET) { 41148027Smckusick ((struct socket *)fp->f_data)->so_pgid = tmp; 41248027Smckusick error = 0; 41348027Smckusick break; 41448027Smckusick } 41548027Smckusick if (tmp <= 0) { 41648027Smckusick tmp = -tmp; 41748027Smckusick } else { 41848027Smckusick struct proc *p1 = pfind(tmp); 41948027Smckusick if (p1 == 0) { 42048027Smckusick error = ESRCH; 42148027Smckusick break; 42248027Smckusick } 42348027Smckusick tmp = p1->p_pgrp->pg_id; 42448027Smckusick } 42548027Smckusick error = (*fp->f_ops->fo_ioctl) 42648027Smckusick (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); 42730530Skarels break; 42812751Ssam 42912751Ssam case FIOGETOWN: 43048027Smckusick if (fp->f_type == DTYPE_SOCKET) { 43148027Smckusick error = 0; 43248027Smckusick *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 43348027Smckusick break; 43448027Smckusick } 43548027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); 43648027Smckusick *(int *)data = -*(int *)data; 43730530Skarels break; 43848027Smckusick 43930530Skarels default: 44047540Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 44130530Skarels /* 44230530Skarels * Copy any data to user, size was 44330530Skarels * already set and checked above. 44430530Skarels */ 44540703Skarels if (error == 0 && (com&IOC_OUT) && size) 44640703Skarels error = copyout(data, uap->cmarg, (u_int)size); 44730530Skarels break; 4487423Sroot } 44931653Smckusick if (memp) 45031653Smckusick free(memp, M_IOCTLOPS); 45144405Skarels return (error); 4527423Sroot } 4537423Sroot 45449227Skarels int selwait, nselcoll; 45517593Skarels 4567423Sroot /* 45712751Ssam * Select system call. 4587423Sroot */ 45942922Smckusick select(p, uap, retval) 46042922Smckusick register struct proc *p; 46142922Smckusick register struct args { 46212751Ssam int nd; 46323523Skarels fd_set *in, *ou, *ex; 46412751Ssam struct timeval *tv; 46542922Smckusick } *uap; 46642922Smckusick int *retval; 46742922Smckusick { 46823523Skarels fd_set ibits[3], obits[3]; 46912751Ssam struct timeval atv; 47040703Skarels int s, ncoll, ni, error = 0, timo; 47112751Ssam 47226277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 47326277Skarels bzero((caddr_t)obits, sizeof(obits)); 47447540Skarels if (uap->nd > p->p_fd->fd_nfiles) 47547540Skarels uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 47623523Skarels ni = howmany(uap->nd, NFDBITS); 47712751Ssam 47812751Ssam #define getbits(name, x) \ 47912751Ssam if (uap->name) { \ 48040703Skarels error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 48126277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 48240703Skarels if (error) \ 48312751Ssam goto done; \ 48417593Skarels } 48512751Ssam getbits(in, 0); 48612751Ssam getbits(ou, 1); 48712751Ssam getbits(ex, 2); 48812751Ssam #undef getbits 48912751Ssam 49012751Ssam if (uap->tv) { 49140703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 49212751Ssam sizeof (atv)); 49340703Skarels if (error) 49412751Ssam goto done; 49512751Ssam if (itimerfix(&atv)) { 49640703Skarels error = EINVAL; 49712751Ssam goto done; 49812751Ssam } 499*54760Storek s = splclock(); 500*54760Storek timevaladd(&atv, (struct timeval *)&time); 50140703Skarels timo = hzto(&atv); 50254276Sbostic splx(s); 50340703Skarels } else 50440703Skarels timo = 0; 50512751Ssam retry: 50612751Ssam ncoll = nselcoll; 50742922Smckusick p->p_flag |= SSEL; 50847540Skarels error = selscan(p, ibits, obits, uap->nd, retval); 50942922Smckusick if (error || *retval) 51012751Ssam goto done; 51117934Skarels s = splhigh(); 51212971Ssam /* this should be timercmp(&time, &atv, >=) */ 51312971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 51412971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 51512751Ssam splx(s); 51612751Ssam goto done; 51712751Ssam } 51842922Smckusick if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { 51912751Ssam splx(s); 52012751Ssam goto retry; 52112751Ssam } 52242922Smckusick p->p_flag &= ~SSEL; 52340703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 52412751Ssam splx(s); 52540703Skarels if (error == 0) 52640703Skarels goto retry; 52712751Ssam done: 52842922Smckusick p->p_flag &= ~SSEL; 52940703Skarels /* select is not restarted after signals... */ 53040703Skarels if (error == ERESTART) 53140703Skarels error = EINTR; 53240703Skarels if (error == EWOULDBLOCK) 53340703Skarels error = 0; 53412751Ssam #define putbits(name, x) \ 53512751Ssam if (uap->name) { \ 53640703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 53726277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 53840703Skarels if (error2) \ 53940703Skarels error = error2; \ 54012751Ssam } 54140703Skarels if (error == 0) { 54221106Skarels putbits(in, 0); 54321106Skarels putbits(ou, 1); 54421106Skarels putbits(ex, 2); 54512751Ssam #undef putbits 54621106Skarels } 54744405Skarels return (error); 54812751Ssam } 54912751Ssam 55047540Skarels selscan(p, ibits, obits, nfd, retval) 55147540Skarels struct proc *p; 55223523Skarels fd_set *ibits, *obits; 55342922Smckusick int nfd, *retval; 55412751Ssam { 55547540Skarels register struct filedesc *fdp = p->p_fd; 55652481Storek register int msk, i, j, fd; 55723523Skarels register fd_mask bits; 55812751Ssam struct file *fp; 55952481Storek int n = 0; 56052481Storek static int flag[3] = { FREAD, FWRITE, 0 }; 56112751Ssam 56252481Storek for (msk = 0; msk < 3; msk++) { 56323523Skarels for (i = 0; i < nfd; i += NFDBITS) { 56452481Storek bits = ibits[msk].fds_bits[i/NFDBITS]; 56552481Storek while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 56617593Skarels bits &= ~(1 << j); 56752481Storek fp = fdp->fd_ofiles[fd]; 56852481Storek if (fp == NULL) 56952481Storek return (EBADF); 57052481Storek if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 57152481Storek FD_SET(fd, &obits[msk]); 57217593Skarels n++; 57317593Skarels } 57412751Ssam } 57512751Ssam } 57612751Ssam } 57742922Smckusick *retval = n; 57852481Storek return (0); 57912751Ssam } 58012751Ssam 5817423Sroot /*ARGSUSED*/ 58247974Skarels #ifdef __STDC__ 58347974Skarels seltrue(dev_t dev, int which, struct proc *p) 58447974Skarels #else 58547540Skarels seltrue(dev, flag, p) 58612751Ssam dev_t dev; 58712751Ssam int flag; 58847540Skarels struct proc *p; 58947974Skarels #endif 5907423Sroot { 5917423Sroot 59212751Ssam return (1); 5937423Sroot } 5948103Sroot 59552525Smckusick /* 59652525Smckusick * Record a select request. 59752525Smckusick */ 59852525Smckusick void 59952525Smckusick selrecord(selector, sip) 60052525Smckusick struct proc *selector; 60152525Smckusick struct selinfo *sip; 6028103Sroot { 60352525Smckusick struct proc *p; 60452525Smckusick pid_t mypid; 6058103Sroot 60652525Smckusick mypid = selector->p_pid; 60752525Smckusick if (sip->si_pid == mypid) 60852525Smckusick return; 60952525Smckusick if (sip->si_pid && (p = pfind(sip->si_pid)) && 61052525Smckusick p->p_wchan == (caddr_t)&selwait) 61152525Smckusick sip->si_flags |= SI_COLL; 61252525Smckusick else 61352525Smckusick sip->si_pid = mypid; 61452525Smckusick } 61552525Smckusick 61652525Smckusick /* 61752525Smckusick * Do a wakeup when a selectable event occurs. 61852525Smckusick */ 61952525Smckusick void 62052525Smckusick selwakeup(sip) 62152525Smckusick register struct selinfo *sip; 62252525Smckusick { 62352525Smckusick register struct proc *p; 62452525Smckusick int s; 62552525Smckusick 62652525Smckusick if (sip->si_pid == 0) 62752525Smckusick return; 62852525Smckusick if (sip->si_flags & SI_COLL) { 62912751Ssam nselcoll++; 63052525Smckusick sip->si_flags &= ~SI_COLL; 63112751Ssam wakeup((caddr_t)&selwait); 63212751Ssam } 63352922Smckusick p = pfind(sip->si_pid); 63452922Smckusick sip->si_pid = 0; 63552922Smckusick if (p != NULL) { 63652525Smckusick s = splhigh(); 63717270Skarels if (p->p_wchan == (caddr_t)&selwait) { 63817270Skarels if (p->p_stat == SSLEEP) 63917270Skarels setrun(p); 64017270Skarels else 64117270Skarels unsleep(p); 64217270Skarels } else if (p->p_flag & SSEL) 64312751Ssam p->p_flag &= ~SSEL; 64412751Ssam splx(s); 64512751Ssam } 6468103Sroot } 647