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*49941Smckusick * @(#)sys_generic.c 7.30 (Berkeley) 05/30/91 823384Smckusick */ 97423Sroot 1017094Sbloom #include "param.h" 1117094Sbloom #include "systm.h" 1245914Smckusick #include "filedesc.h" 1317094Sbloom #include "ioctl.h" 1417094Sbloom #include "file.h" 1548027Smckusick #include "socketvar.h" 1617094Sbloom #include "proc.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; 9744939Skarels struct iovec *saveiov; 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); 11544939Skarels saveiov = iov; 11637127Skarels } else 11737127Skarels iov = aiov; 11837127Skarels auio.uio_iov = iov; 1197820Sroot auio.uio_iovcnt = uap->iovcnt; 12037728Smckusick auio.uio_rw = UIO_READ; 12137728Smckusick auio.uio_segflg = UIO_USERSPACE; 12248027Smckusick auio.uio_procp = p; 12344939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 12437127Skarels goto done; 12537728Smckusick auio.uio_resid = 0; 12637728Smckusick for (i = 0; i < uap->iovcnt; i++) { 12737728Smckusick if (iov->iov_len < 0) { 12837728Smckusick error = EINVAL; 12937728Smckusick goto done; 13037728Smckusick } 13137728Smckusick auio.uio_resid += iov->iov_len; 13237728Smckusick if (auio.uio_resid < 0) { 13337728Smckusick error = EINVAL; 13437728Smckusick goto done; 13537728Smckusick } 13637728Smckusick iov++; 13737728Smckusick } 13837728Smckusick #ifdef KTRACE 13937728Smckusick /* 14037728Smckusick * if tracing, save a copy of iovec 14137728Smckusick */ 14242922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 14337728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 14437728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 14537728Smckusick } 14637728Smckusick #endif 14737728Smckusick cnt = auio.uio_resid; 14840703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 14940703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 15040703Skarels error == EINTR || error == EWOULDBLOCK)) 15140703Skarels error = 0; 15237728Smckusick cnt -= auio.uio_resid; 15337728Smckusick #ifdef KTRACE 15437728Smckusick if (ktriov != NULL) { 15541178Smarc if (error == 0) 15643448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 15743448Smckusick cnt, error); 15837728Smckusick FREE(ktriov, M_TEMP); 15937728Smckusick } 16037728Smckusick #endif 16142922Smckusick *retval = cnt; 16237127Skarels done: 16337728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 16444939Skarels FREE(saveiov, M_IOV); 16544405Skarels return (error); 1667423Sroot } 1677423Sroot 1687423Sroot /* 1697423Sroot * Write system call 1707423Sroot */ 17142922Smckusick write(p, uap, retval) 17242922Smckusick struct proc *p; 17342922Smckusick register struct args { 1747423Sroot int fdes; 1757423Sroot char *cbuf; 17626474Skarels unsigned count; 17742922Smckusick } *uap; 17842922Smckusick int *retval; 17942922Smckusick { 18037728Smckusick register struct file *fp; 18145914Smckusick register struct filedesc *fdp = p->p_fd; 1827820Sroot struct uio auio; 1837820Sroot struct iovec aiov; 18437728Smckusick long cnt, error = 0; 18537728Smckusick #ifdef KTRACE 18637728Smckusick struct iovec ktriov; 18737728Smckusick #endif 1887423Sroot 18947540Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 19047974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 19137728Smckusick (fp->f_flag & FWRITE) == 0) 19244405Skarels return (EBADF); 19337728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 19437728Smckusick aiov.iov_len = uap->count; 1957820Sroot auio.uio_iov = &aiov; 1967820Sroot auio.uio_iovcnt = 1; 19737728Smckusick auio.uio_resid = uap->count; 19837728Smckusick auio.uio_rw = UIO_WRITE; 19937728Smckusick auio.uio_segflg = UIO_USERSPACE; 20048027Smckusick auio.uio_procp = p; 20137728Smckusick #ifdef KTRACE 20237728Smckusick /* 20337728Smckusick * if tracing, save a copy of iovec 20437728Smckusick */ 20542922Smckusick if (KTRPOINT(p, KTR_GENIO)) 20637728Smckusick ktriov = aiov; 20737728Smckusick #endif 20837728Smckusick cnt = uap->count; 20940703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 21040703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 21140703Skarels error == EINTR || error == EWOULDBLOCK)) 21240703Skarels error = 0; 21340703Skarels if (error == EPIPE) 21442922Smckusick psignal(p, SIGPIPE); 21540703Skarels } 21637728Smckusick cnt -= auio.uio_resid; 21737728Smckusick #ifdef KTRACE 21842922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 21942922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 22043448Smckusick &ktriov, cnt, error); 22137728Smckusick #endif 22242922Smckusick *retval = cnt; 22344405Skarels return (error); 2247820Sroot } 2257820Sroot 22642922Smckusick /* 22742922Smckusick * Gather write system call 22842922Smckusick */ 22942922Smckusick writev(p, uap, retval) 23042922Smckusick struct proc *p; 23142922Smckusick register struct args { 2327820Sroot int fdes; 2337820Sroot struct iovec *iovp; 23426474Skarels unsigned iovcnt; 23542922Smckusick } *uap; 23642922Smckusick int *retval; 23742922Smckusick { 23837728Smckusick register struct file *fp; 23945914Smckusick register struct filedesc *fdp = p->p_fd; 2407820Sroot struct uio auio; 24137728Smckusick register struct iovec *iov; 24244939Skarels struct iovec *saveiov; 24337728Smckusick struct iovec aiov[UIO_SMALLIOV]; 24437728Smckusick long i, cnt, error = 0; 24544939Skarels unsigned iovlen; 24637728Smckusick #ifdef KTRACE 24737728Smckusick struct iovec *ktriov = NULL; 24837728Smckusick #endif 2497820Sroot 25047540Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 25147974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 25237728Smckusick (fp->f_flag & FWRITE) == 0) 25344405Skarels return (EBADF); 25444939Skarels /* note: can't use iovlen until iovcnt is validated */ 25544939Skarels iovlen = uap->iovcnt * sizeof (struct iovec); 25637127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 25737728Smckusick if (uap->iovcnt > UIO_MAXIOV) 25844405Skarels return (EINVAL); 25944939Skarels MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 26044939Skarels saveiov = iov; 26137127Skarels } else 26237127Skarels iov = aiov; 26337127Skarels auio.uio_iov = iov; 2647820Sroot auio.uio_iovcnt = uap->iovcnt; 26537728Smckusick auio.uio_rw = UIO_WRITE; 26637728Smckusick auio.uio_segflg = UIO_USERSPACE; 26748027Smckusick auio.uio_procp = p; 26844939Skarels if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 26937127Skarels goto done; 27037728Smckusick auio.uio_resid = 0; 27137728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2727820Sroot if (iov->iov_len < 0) { 27337728Smckusick error = EINVAL; 27437728Smckusick goto done; 2757820Sroot } 27637728Smckusick auio.uio_resid += iov->iov_len; 27737728Smckusick if (auio.uio_resid < 0) { 27837728Smckusick error = EINVAL; 27937728Smckusick goto done; 2807820Sroot } 28113270Ssam iov++; 2827820Sroot } 28337127Skarels #ifdef KTRACE 28437728Smckusick /* 28537728Smckusick * if tracing, save a copy of iovec 28637728Smckusick */ 28742922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 28837127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 28937728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 29037127Skarels } 29137127Skarels #endif 29237728Smckusick cnt = auio.uio_resid; 29340703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 29440703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 29540703Skarels error == EINTR || error == EWOULDBLOCK)) 29640703Skarels error = 0; 29740703Skarels if (error == EPIPE) 29842922Smckusick psignal(p, SIGPIPE); 29940703Skarels } 30037728Smckusick cnt -= auio.uio_resid; 30137127Skarels #ifdef KTRACE 30237127Skarels if (ktriov != NULL) { 30341178Smarc if (error == 0) 30442922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 30543448Smckusick ktriov, cnt, error); 30637127Skarels FREE(ktriov, M_TEMP); 30737127Skarels } 30837127Skarels #endif 30942922Smckusick *retval = cnt; 31037728Smckusick done: 31137728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 31244939Skarels FREE(saveiov, M_IOV); 31344405Skarels return (error); 3147423Sroot } 3157423Sroot 3167423Sroot /* 3177423Sroot * Ioctl system call 3187423Sroot */ 31942922Smckusick /* ARGSUSED */ 32042922Smckusick ioctl(p, uap, retval) 32142922Smckusick struct proc *p; 32242922Smckusick register struct args { 3237423Sroot int fdes; 3247423Sroot int cmd; 3257423Sroot caddr_t cmarg; 32642922Smckusick } *uap; 32742922Smckusick int *retval; 32842922Smckusick { 32942922Smckusick register struct file *fp; 33045914Smckusick register struct filedesc *fdp = p->p_fd; 33140703Skarels register int com, error; 3327820Sroot register u_int size; 33331653Smckusick caddr_t memp = 0; 33430530Skarels #define STK_PARAMS 128 33533480Skarels char stkbuf[STK_PARAMS]; 33633480Skarels caddr_t data = stkbuf; 33748027Smckusick int tmp; 3387423Sroot 33947540Skarels if ((unsigned)uap->fdes >= fdp->fd_nfiles || 34047974Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 34144405Skarels return (EBADF); 34240703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 34344405Skarels return (EBADF); 3447624Ssam com = uap->cmd; 3457624Ssam 3467624Ssam if (com == FIOCLEX) { 34747974Skarels fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE; 34844405Skarels return (0); 3497423Sroot } 3507624Ssam if (com == FIONCLEX) { 35147974Skarels fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE; 35244405Skarels return (0); 3537423Sroot } 3547624Ssam 3557624Ssam /* 3567624Ssam * Interpret high order word to find 3577624Ssam * amount of data to be copied to/from the 3587624Ssam * user's address space. 3597624Ssam */ 36030530Skarels size = IOCPARM_LEN(com); 36140703Skarels if (size > IOCPARM_MAX) 36244405Skarels return (ENOTTY); 36333480Skarels if (size > sizeof (stkbuf)) { 36443383Smckusick memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 36531653Smckusick data = memp; 36630530Skarels } 36710601Ssam if (com&IOC_IN) { 36810601Ssam if (size) { 36940703Skarels error = copyin(uap->cmarg, data, (u_int)size); 37040703Skarels if (error) { 37131653Smckusick if (memp) 37231653Smckusick free(memp, M_IOCTLOPS); 37344405Skarels return (error); 37431653Smckusick } 37510601Ssam } else 37610601Ssam *(caddr_t *)data = uap->cmarg; 37710601Ssam } else if ((com&IOC_OUT) && size) 37810601Ssam /* 37937127Skarels * Zero the buffer so the user always 38037127Skarels * gets back something deterministic. 38110601Ssam */ 38230530Skarels bzero(data, size); 38311284Ssam else if (com&IOC_VOID) 38411284Ssam *(caddr_t *)data = uap->cmarg; 3857423Sroot 38612751Ssam switch (com) { 3877624Ssam 38812751Ssam case FIONBIO: 38948027Smckusick if (tmp = *(int *)data) 390*49941Smckusick fp->f_flag |= FNONBLOCK; 39148027Smckusick else 392*49941Smckusick fp->f_flag &= ~FNONBLOCK; 39348027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 39430530Skarels break; 39512751Ssam 39612751Ssam case FIOASYNC: 39748027Smckusick if (tmp = *(int *)data) 39848027Smckusick fp->f_flag |= FASYNC; 39948027Smckusick else 40048027Smckusick fp->f_flag &= ~FASYNC; 40148027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 40230530Skarels break; 40312751Ssam 40412751Ssam case FIOSETOWN: 40548027Smckusick tmp = *(int *)data; 40648027Smckusick if (fp->f_type == DTYPE_SOCKET) { 40748027Smckusick ((struct socket *)fp->f_data)->so_pgid = tmp; 40848027Smckusick error = 0; 40948027Smckusick break; 41048027Smckusick } 41148027Smckusick if (tmp <= 0) { 41248027Smckusick tmp = -tmp; 41348027Smckusick } else { 41448027Smckusick struct proc *p1 = pfind(tmp); 41548027Smckusick if (p1 == 0) { 41648027Smckusick error = ESRCH; 41748027Smckusick break; 41848027Smckusick } 41948027Smckusick tmp = p1->p_pgrp->pg_id; 42048027Smckusick } 42148027Smckusick error = (*fp->f_ops->fo_ioctl) 42248027Smckusick (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); 42330530Skarels break; 42412751Ssam 42512751Ssam case FIOGETOWN: 42648027Smckusick if (fp->f_type == DTYPE_SOCKET) { 42748027Smckusick error = 0; 42848027Smckusick *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 42948027Smckusick break; 43048027Smckusick } 43148027Smckusick error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); 43248027Smckusick *(int *)data = -*(int *)data; 43330530Skarels break; 43448027Smckusick 43530530Skarels default: 43647540Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 43730530Skarels /* 43830530Skarels * Copy any data to user, size was 43930530Skarels * already set and checked above. 44030530Skarels */ 44140703Skarels if (error == 0 && (com&IOC_OUT) && size) 44240703Skarels error = copyout(data, uap->cmarg, (u_int)size); 44330530Skarels break; 4447423Sroot } 44531653Smckusick if (memp) 44631653Smckusick free(memp, M_IOCTLOPS); 44744405Skarels return (error); 4487423Sroot } 4497423Sroot 45049227Skarels int selwait, nselcoll; 45117593Skarels 4527423Sroot /* 45312751Ssam * Select system call. 4547423Sroot */ 45542922Smckusick select(p, uap, retval) 45642922Smckusick register struct proc *p; 45742922Smckusick register struct args { 45812751Ssam int nd; 45923523Skarels fd_set *in, *ou, *ex; 46012751Ssam struct timeval *tv; 46142922Smckusick } *uap; 46242922Smckusick int *retval; 46342922Smckusick { 46423523Skarels fd_set ibits[3], obits[3]; 46512751Ssam struct timeval atv; 46640703Skarels int s, ncoll, ni, error = 0, timo; 46712751Ssam 46826277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 46926277Skarels bzero((caddr_t)obits, sizeof(obits)); 47047540Skarels if (uap->nd > p->p_fd->fd_nfiles) 47147540Skarels uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 47223523Skarels ni = howmany(uap->nd, NFDBITS); 47312751Ssam 47412751Ssam #define getbits(name, x) \ 47512751Ssam if (uap->name) { \ 47640703Skarels error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 47726277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 47840703Skarels if (error) \ 47912751Ssam goto done; \ 48017593Skarels } 48112751Ssam getbits(in, 0); 48212751Ssam getbits(ou, 1); 48312751Ssam getbits(ex, 2); 48412751Ssam #undef getbits 48512751Ssam 48612751Ssam if (uap->tv) { 48740703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 48812751Ssam sizeof (atv)); 48940703Skarels if (error) 49012751Ssam goto done; 49112751Ssam if (itimerfix(&atv)) { 49240703Skarels error = EINVAL; 49312751Ssam goto done; 49412751Ssam } 49517934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 49640703Skarels timo = hzto(&atv); 49740703Skarels } else 49840703Skarels timo = 0; 49912751Ssam retry: 50012751Ssam ncoll = nselcoll; 50142922Smckusick p->p_flag |= SSEL; 50247540Skarels error = selscan(p, ibits, obits, uap->nd, retval); 50342922Smckusick if (error || *retval) 50412751Ssam goto done; 50517934Skarels s = splhigh(); 50612971Ssam /* this should be timercmp(&time, &atv, >=) */ 50712971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 50812971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 50912751Ssam splx(s); 51012751Ssam goto done; 51112751Ssam } 51242922Smckusick if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { 51312751Ssam splx(s); 51412751Ssam goto retry; 51512751Ssam } 51642922Smckusick p->p_flag &= ~SSEL; 51740703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 51812751Ssam splx(s); 51940703Skarels if (error == 0) 52040703Skarels goto retry; 52112751Ssam done: 52242922Smckusick p->p_flag &= ~SSEL; 52340703Skarels /* select is not restarted after signals... */ 52440703Skarels if (error == ERESTART) 52540703Skarels error = EINTR; 52640703Skarels if (error == EWOULDBLOCK) 52740703Skarels error = 0; 52812751Ssam #define putbits(name, x) \ 52912751Ssam if (uap->name) { \ 53040703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 53126277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 53240703Skarels if (error2) \ 53340703Skarels error = error2; \ 53412751Ssam } 53540703Skarels if (error == 0) { 53621106Skarels putbits(in, 0); 53721106Skarels putbits(ou, 1); 53821106Skarels putbits(ex, 2); 53912751Ssam #undef putbits 54021106Skarels } 54144405Skarels return (error); 54212751Ssam } 54312751Ssam 54447540Skarels selscan(p, ibits, obits, nfd, retval) 54547540Skarels struct proc *p; 54623523Skarels fd_set *ibits, *obits; 54742922Smckusick int nfd, *retval; 54812751Ssam { 54947540Skarels register struct filedesc *fdp = p->p_fd; 55023523Skarels register int which, i, j; 55123523Skarels register fd_mask bits; 55212751Ssam int flag; 55312751Ssam struct file *fp; 55442922Smckusick int error = 0, n = 0; 55512751Ssam 55612751Ssam for (which = 0; which < 3; which++) { 55712751Ssam switch (which) { 55812751Ssam 55912751Ssam case 0: 56012751Ssam flag = FREAD; break; 56112751Ssam 56212751Ssam case 1: 56312751Ssam flag = FWRITE; break; 56412751Ssam 56512751Ssam case 2: 56612751Ssam flag = 0; break; 56712751Ssam } 56823523Skarels for (i = 0; i < nfd; i += NFDBITS) { 56923523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 57017593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 57117593Skarels bits &= ~(1 << j); 57247974Skarels fp = fdp->fd_ofiles[i + j]; 57317593Skarels if (fp == NULL) { 57442922Smckusick error = EBADF; 57517593Skarels break; 57617593Skarels } 57747540Skarels if ((*fp->f_ops->fo_select)(fp, flag, p)) { 57823523Skarels FD_SET(i + j, &obits[which]); 57917593Skarels n++; 58017593Skarels } 58112751Ssam } 58212751Ssam } 58312751Ssam } 58442922Smckusick *retval = n; 58542922Smckusick return (error); 58612751Ssam } 58712751Ssam 5887423Sroot /*ARGSUSED*/ 58947974Skarels #ifdef __STDC__ 59047974Skarels seltrue(dev_t dev, int which, struct proc *p) 59147974Skarels #else 59247540Skarels seltrue(dev, flag, p) 59312751Ssam dev_t dev; 59412751Ssam int flag; 59547540Skarels struct proc *p; 59647974Skarels #endif 5977423Sroot { 5987423Sroot 59912751Ssam return (1); 6007423Sroot } 6018103Sroot 60212751Ssam selwakeup(p, coll) 60312751Ssam register struct proc *p; 60412751Ssam int coll; 6058103Sroot { 6068103Sroot 60712751Ssam if (coll) { 60812751Ssam nselcoll++; 60912751Ssam wakeup((caddr_t)&selwait); 61012751Ssam } 61112751Ssam if (p) { 61217934Skarels int s = splhigh(); 61317270Skarels if (p->p_wchan == (caddr_t)&selwait) { 61417270Skarels if (p->p_stat == SSLEEP) 61517270Skarels setrun(p); 61617270Skarels else 61717270Skarels unsleep(p); 61817270Skarels } else if (p->p_flag & SSEL) 61912751Ssam p->p_flag &= ~SSEL; 62012751Ssam splx(s); 62112751Ssam } 6228103Sroot } 623