123384Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423384Smckusick * 537728Smckusick * Redistribution and use in source and binary forms are permitted 637728Smckusick * provided that the above copyright notice and this paragraph are 737728Smckusick * duplicated in all such forms and that any documentation, 837728Smckusick * advertising materials, and other materials related to such 937728Smckusick * distribution and use acknowledge that the software was developed 1037728Smckusick * by the University of California, Berkeley. The name of the 1137728Smckusick * University may not be used to endorse or promote products derived 1237728Smckusick * from this software without specific prior written permission. 1337728Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437728Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537728Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637728Smckusick * 17*38141Smckusick * @(#)sys_generic.c 7.11 (Berkeley) 05/27/89 1823384Smckusick */ 197423Sroot 2017094Sbloom #include "param.h" 2117094Sbloom #include "systm.h" 2237728Smckusick #include "syscontext.h" 2317094Sbloom #include "ioctl.h" 2417094Sbloom #include "file.h" 2517094Sbloom #include "proc.h" 2617094Sbloom #include "uio.h" 2717094Sbloom #include "kernel.h" 2817094Sbloom #include "stat.h" 2931653Smckusick #include "malloc.h" 3037127Skarels #ifdef KTRACE 3137127Skarels #include "ktrace.h" 3237127Skarels #endif 337423Sroot 347423Sroot /* 357423Sroot * Read system call. 367423Sroot */ 377423Sroot read() 387423Sroot { 397423Sroot register struct a { 407423Sroot int fdes; 417423Sroot char *cbuf; 427423Sroot unsigned count; 437820Sroot } *uap = (struct a *)u.u_ap; 4437728Smckusick register struct file *fp; 457746Sroot struct uio auio; 467746Sroot struct iovec aiov; 4737728Smckusick long cnt, error = 0; 4837728Smckusick #ifdef KTRACE 4937728Smckusick struct iovec ktriov; 5037728Smckusick #endif 517423Sroot 5237728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 5337728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 5437728Smckusick (fp->f_flag & FREAD) == 0) 5537728Smckusick RETURN (EBADF); 5637728Smckusick if (uap->count < 0) 5737728Smckusick RETURN (EINVAL); 587820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 597820Sroot aiov.iov_len = uap->count; 607820Sroot auio.uio_iov = &aiov; 617820Sroot auio.uio_iovcnt = 1; 6237728Smckusick auio.uio_resid = uap->count; 6337728Smckusick auio.uio_rw = UIO_READ; 6437728Smckusick auio.uio_segflg = UIO_USERSPACE; 6537728Smckusick #ifdef KTRACE 6637728Smckusick /* 6737728Smckusick * if tracing, save a copy of iovec 6837728Smckusick */ 6937728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 7037728Smckusick ktriov = aiov; 7137728Smckusick #endif 7237728Smckusick cnt = uap->count; 7337728Smckusick if (setjmp(&u.u_qsave)) { 7437728Smckusick if (auio.uio_resid == cnt) { 7537728Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 7637728Smckusick error = EINTR; 7737728Smckusick else 7837728Smckusick u.u_eosys = RESTARTSYS; 7937728Smckusick } 8037728Smckusick } else 81*38141Smckusick error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred); 8237728Smckusick cnt -= auio.uio_resid; 8337728Smckusick #ifdef KTRACE 8437728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 8537728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, ktriov, cnt); 8637728Smckusick #endif 8737728Smckusick u.u_r.r_val1 = cnt; 8837728Smckusick RETURN (error); 897820Sroot } 907820Sroot 917820Sroot readv() 927820Sroot { 937820Sroot register struct a { 947820Sroot int fdes; 957820Sroot struct iovec *iovp; 9626474Skarels unsigned iovcnt; 977820Sroot } *uap = (struct a *)u.u_ap; 9837728Smckusick register struct file *fp; 997820Sroot struct uio auio; 10037728Smckusick register struct iovec *iov; 10137728Smckusick struct iovec aiov[UIO_SMALLIOV]; 10237728Smckusick long i, cnt, error = 0; 10337728Smckusick #ifdef KTRACE 10437728Smckusick struct iovec *ktriov = NULL; 10537728Smckusick #endif 1067820Sroot 10737728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 10837728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 10937728Smckusick (fp->f_flag & FREAD) == 0) 11037728Smckusick RETURN (EBADF); 11137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 11237728Smckusick if (uap->iovcnt > UIO_MAXIOV) 11337728Smckusick RETURN (EINVAL); 11437127Skarels MALLOC(iov, struct iovec *, 11537127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 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; 12237728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 12337728Smckusick uap->iovcnt * sizeof (struct iovec))) 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 */ 14237728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) { 14337728Smckusick int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 14437728Smckusick 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; 15037728Smckusick if (setjmp(&u.u_qsave)) { 15137728Smckusick if (auio.uio_resid == cnt) { 15237728Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 15337728Smckusick error = EINTR; 15437728Smckusick else 15537728Smckusick u.u_eosys = RESTARTSYS; 15637728Smckusick } 15737728Smckusick } else 158*38141Smckusick error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred); 15937728Smckusick cnt -= auio.uio_resid; 16037728Smckusick #ifdef KTRACE 16137728Smckusick if (ktriov != NULL) { 16237728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, ktriov, cnt); 16337728Smckusick FREE(ktriov, M_TEMP); 16437728Smckusick } 16537728Smckusick #endif 16637728Smckusick u.u_r.r_val1 = cnt; 16737127Skarels done: 16837728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 16937127Skarels FREE(iov, M_IOV); 17037728Smckusick RETURN (error); 1717423Sroot } 1727423Sroot 1737423Sroot /* 1747423Sroot * Write system call 1757423Sroot */ 1767423Sroot write() 1777423Sroot { 1787423Sroot register struct a { 1797423Sroot int fdes; 1807423Sroot char *cbuf; 18126474Skarels unsigned count; 1827820Sroot } *uap = (struct a *)u.u_ap; 18337728Smckusick register struct file *fp; 1847820Sroot struct uio auio; 1857820Sroot struct iovec aiov; 18637728Smckusick long cnt, error = 0; 18737728Smckusick #ifdef KTRACE 18837728Smckusick struct iovec ktriov; 18937728Smckusick #endif 1907423Sroot 19137728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 19237728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 19337728Smckusick (fp->f_flag & FWRITE) == 0) 19437728Smckusick RETURN (EBADF); 19537728Smckusick if (uap->count < 0) 19637728Smckusick RETURN (EINVAL); 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; 20437728Smckusick #ifdef KTRACE 20537728Smckusick /* 20637728Smckusick * if tracing, save a copy of iovec 20737728Smckusick */ 20837728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 20937728Smckusick ktriov = aiov; 21037728Smckusick #endif 21137728Smckusick cnt = uap->count; 21237728Smckusick if (setjmp(&u.u_qsave)) { 21337728Smckusick if (auio.uio_resid == cnt) { 21437728Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 21537728Smckusick error = EINTR; 21637728Smckusick else 21737728Smckusick u.u_eosys = RESTARTSYS; 21837728Smckusick } 21937728Smckusick } else 220*38141Smckusick error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred); 22137728Smckusick cnt -= auio.uio_resid; 22237728Smckusick #ifdef KTRACE 22337728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 22437728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 22537728Smckusick ktriov, cnt); 22637728Smckusick #endif 22737728Smckusick u.u_r.r_val1 = cnt; 22837728Smckusick RETURN (error); 2297820Sroot } 2307820Sroot 2317820Sroot writev() 2327820Sroot { 2337820Sroot register struct a { 2347820Sroot int fdes; 2357820Sroot struct iovec *iovp; 23626474Skarels unsigned iovcnt; 2377820Sroot } *uap = (struct a *)u.u_ap; 23837728Smckusick register struct file *fp; 2397820Sroot struct uio auio; 24037728Smckusick register struct iovec *iov; 24137728Smckusick struct iovec aiov[UIO_SMALLIOV]; 24237728Smckusick long i, cnt, error = 0; 24337728Smckusick #ifdef KTRACE 24437728Smckusick struct iovec *ktriov = NULL; 24537728Smckusick #endif 2467820Sroot 24737728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 24837728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 24937728Smckusick (fp->f_flag & FWRITE) == 0) 25037728Smckusick RETURN (EBADF); 25137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 25237728Smckusick if (uap->iovcnt > UIO_MAXIOV) 25337728Smckusick RETURN (EINVAL); 25437127Skarels MALLOC(iov, struct iovec *, 25537127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 25637127Skarels } else 25737127Skarels iov = aiov; 25837127Skarels auio.uio_iov = iov; 2597820Sroot auio.uio_iovcnt = uap->iovcnt; 26037728Smckusick auio.uio_rw = UIO_WRITE; 26137728Smckusick auio.uio_segflg = UIO_USERSPACE; 26237728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 26337728Smckusick uap->iovcnt * sizeof (struct iovec))) 26437127Skarels goto done; 26537728Smckusick auio.uio_resid = 0; 26637728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2677820Sroot if (iov->iov_len < 0) { 26837728Smckusick error = EINVAL; 26937728Smckusick goto done; 2707820Sroot } 27137728Smckusick auio.uio_resid += iov->iov_len; 27237728Smckusick if (auio.uio_resid < 0) { 27337728Smckusick error = EINVAL; 27437728Smckusick goto done; 2757820Sroot } 27613270Ssam iov++; 2777820Sroot } 27837127Skarels #ifdef KTRACE 27937728Smckusick /* 28037728Smckusick * if tracing, save a copy of iovec 28137728Smckusick */ 28237127Skarels if (KTRPOINT(u.u_procp, KTR_GENIO)) { 28337728Smckusick int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 28437127Skarels 28537127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 28637728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 28737127Skarels } 28837127Skarels #endif 28937728Smckusick cnt = auio.uio_resid; 29018309Smckusick if (setjmp(&u.u_qsave)) { 29137728Smckusick if (auio.uio_resid == cnt) { 29221009Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 29337728Smckusick error = EINTR; 29418309Smckusick else 29518309Smckusick u.u_eosys = RESTARTSYS; 29618309Smckusick } 29712751Ssam } else 298*38141Smckusick error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred); 29937728Smckusick cnt -= auio.uio_resid; 30037127Skarels #ifdef KTRACE 30137127Skarels if (ktriov != NULL) { 30237728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 30337728Smckusick ktriov, cnt); 30437127Skarels FREE(ktriov, M_TEMP); 30537127Skarels } 30637127Skarels #endif 30737728Smckusick u.u_r.r_val1 = cnt; 30837728Smckusick done: 30937728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 31037728Smckusick FREE(iov, M_IOV); 31137728Smckusick RETURN (error); 3127423Sroot } 3137423Sroot 3147423Sroot /* 3157423Sroot * Ioctl system call 3167423Sroot */ 3177423Sroot ioctl() 3187423Sroot { 3197423Sroot register struct file *fp; 3207624Ssam struct a { 3217423Sroot int fdes; 3227423Sroot int cmd; 3237423Sroot caddr_t cmarg; 32437728Smckusick } *uap = (struct a *)u.u_ap; 3257820Sroot register int com; 3267820Sroot register u_int size; 32731653Smckusick caddr_t memp = 0; 32830530Skarels #define STK_PARAMS 128 32933480Skarels char stkbuf[STK_PARAMS]; 33033480Skarels caddr_t data = stkbuf; 3317423Sroot 33237728Smckusick if ((unsigned)uap->fdes >= NOFILE || 33337728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 33437728Smckusick RETURN (EBADF); 3357423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 3367423Sroot u.u_error = EBADF; 3377423Sroot return; 3387423Sroot } 3397624Ssam com = uap->cmd; 3407624Ssam 3417624Ssam if (com == FIOCLEX) { 3429592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 3437423Sroot return; 3447423Sroot } 3457624Ssam if (com == FIONCLEX) { 3469592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 3477423Sroot return; 3487423Sroot } 3497624Ssam 3507624Ssam /* 3517624Ssam * Interpret high order word to find 3527624Ssam * amount of data to be copied to/from the 3537624Ssam * user's address space. 3547624Ssam */ 35530530Skarels size = IOCPARM_LEN(com); 35630530Skarels if (size > IOCPARM_MAX) { 35737127Skarels u.u_error = ENOTTY; 3587423Sroot return; 3597423Sroot } 36033480Skarels if (size > sizeof (stkbuf)) { 36137127Skarels memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS, 36234473Smckusick M_WAITOK); 36331653Smckusick data = memp; 36430530Skarels } 36510601Ssam if (com&IOC_IN) { 36610601Ssam if (size) { 36737127Skarels u.u_error = copyin(uap->cmarg, data, (u_int)size); 36831653Smckusick if (u.u_error) { 36931653Smckusick if (memp) 37031653Smckusick free(memp, M_IOCTLOPS); 37110601Ssam return; 37231653Smckusick } 37310601Ssam } else 37410601Ssam *(caddr_t *)data = uap->cmarg; 37510601Ssam } else if ((com&IOC_OUT) && size) 37610601Ssam /* 37737127Skarels * Zero the buffer so the user always 37837127Skarels * gets back something deterministic. 37910601Ssam */ 38030530Skarels bzero(data, size); 38111284Ssam else if (com&IOC_VOID) 38211284Ssam *(caddr_t *)data = uap->cmarg; 3837423Sroot 38412751Ssam switch (com) { 3857624Ssam 38612751Ssam case FIONBIO: 38712751Ssam u.u_error = fset(fp, FNDELAY, *(int *)data); 38830530Skarels break; 38912751Ssam 39012751Ssam case FIOASYNC: 39112751Ssam u.u_error = fset(fp, FASYNC, *(int *)data); 39230530Skarels break; 39312751Ssam 39412751Ssam case FIOSETOWN: 39512751Ssam u.u_error = fsetown(fp, *(int *)data); 39630530Skarels break; 39712751Ssam 39812751Ssam case FIOGETOWN: 39912751Ssam u.u_error = fgetown(fp, (int *)data); 40030530Skarels break; 40130530Skarels default: 40230530Skarels if (setjmp(&u.u_qsave)) 40330530Skarels u.u_error = EINTR; 40430530Skarels else 40530530Skarels u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 40630530Skarels /* 40730530Skarels * Copy any data to user, size was 40830530Skarels * already set and checked above. 40930530Skarels */ 41030530Skarels if (u.u_error == 0 && (com&IOC_OUT) && size) 41130530Skarels u.u_error = copyout(data, uap->cmarg, (u_int)size); 41230530Skarels break; 4137423Sroot } 41431653Smckusick if (memp) 41531653Smckusick free(memp, M_IOCTLOPS); 4167423Sroot } 4177423Sroot 41812751Ssam int unselect(); 41912751Ssam int nselcoll; 42017593Skarels 4217423Sroot /* 42212751Ssam * Select system call. 4237423Sroot */ 42412751Ssam select() 42512751Ssam { 42612751Ssam register struct uap { 42712751Ssam int nd; 42823523Skarels fd_set *in, *ou, *ex; 42912751Ssam struct timeval *tv; 43012751Ssam } *uap = (struct uap *)u.u_ap; 43123523Skarels fd_set ibits[3], obits[3]; 43212751Ssam struct timeval atv; 43317593Skarels int s, ncoll, ni; 43412751Ssam label_t lqsave; 43512751Ssam 43626277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 43726277Skarels bzero((caddr_t)obits, sizeof(obits)); 43812751Ssam if (uap->nd > NOFILE) 43912751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 44023523Skarels ni = howmany(uap->nd, NFDBITS); 44112751Ssam 44212751Ssam #define getbits(name, x) \ 44312751Ssam if (uap->name) { \ 44423523Skarels u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 44526277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 44612751Ssam if (u.u_error) \ 44712751Ssam goto done; \ 44817593Skarels } 44912751Ssam getbits(in, 0); 45012751Ssam getbits(ou, 1); 45112751Ssam getbits(ex, 2); 45212751Ssam #undef getbits 45312751Ssam 45412751Ssam if (uap->tv) { 45512751Ssam u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 45612751Ssam sizeof (atv)); 45712751Ssam if (u.u_error) 45812751Ssam goto done; 45912751Ssam if (itimerfix(&atv)) { 46012751Ssam u.u_error = EINVAL; 46112751Ssam goto done; 46212751Ssam } 46317934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 46412751Ssam } 46512751Ssam retry: 46612751Ssam ncoll = nselcoll; 46712751Ssam u.u_procp->p_flag |= SSEL; 46817593Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 46912751Ssam if (u.u_error || u.u_r.r_val1) 47012751Ssam goto done; 47117934Skarels s = splhigh(); 47212971Ssam /* this should be timercmp(&time, &atv, >=) */ 47312971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 47412971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 47512751Ssam splx(s); 47612751Ssam goto done; 47712751Ssam } 47812751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 47912751Ssam splx(s); 48012751Ssam goto retry; 48112751Ssam } 48212751Ssam u.u_procp->p_flag &= ~SSEL; 48312751Ssam if (uap->tv) { 48412751Ssam lqsave = u.u_qsave; 48512751Ssam if (setjmp(&u.u_qsave)) { 48612751Ssam untimeout(unselect, (caddr_t)u.u_procp); 48712751Ssam u.u_error = EINTR; 48812751Ssam splx(s); 48912751Ssam goto done; 49012751Ssam } 49112751Ssam timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 49212751Ssam } 49312751Ssam sleep((caddr_t)&selwait, PZERO+1); 49412751Ssam if (uap->tv) { 49512751Ssam u.u_qsave = lqsave; 49612751Ssam untimeout(unselect, (caddr_t)u.u_procp); 49712751Ssam } 49812751Ssam splx(s); 49912751Ssam goto retry; 50012751Ssam done: 50133712Skarels u.u_procp->p_flag &= ~SSEL; 50212751Ssam #define putbits(name, x) \ 50312751Ssam if (uap->name) { \ 50423523Skarels int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 50526277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 50612751Ssam if (error) \ 50712751Ssam u.u_error = error; \ 50812751Ssam } 50926070Skarels if (u.u_error == 0) { 51021106Skarels putbits(in, 0); 51121106Skarels putbits(ou, 1); 51221106Skarels putbits(ex, 2); 51312751Ssam #undef putbits 51421106Skarels } 51512751Ssam } 51612751Ssam 51712751Ssam unselect(p) 51812751Ssam register struct proc *p; 51912751Ssam { 52017934Skarels register int s = splhigh(); 52112751Ssam 52212751Ssam switch (p->p_stat) { 52312751Ssam 52412751Ssam case SSLEEP: 52512751Ssam setrun(p); 52612751Ssam break; 52712751Ssam 52812751Ssam case SSTOP: 52912751Ssam unsleep(p); 53012751Ssam break; 53112751Ssam } 53212751Ssam splx(s); 53312751Ssam } 53412751Ssam 53517593Skarels selscan(ibits, obits, nfd) 53623523Skarels fd_set *ibits, *obits; 53712751Ssam { 53823523Skarels register int which, i, j; 53923523Skarels register fd_mask bits; 54012751Ssam int flag; 54112751Ssam struct file *fp; 54212751Ssam int n = 0; 54312751Ssam 54412751Ssam for (which = 0; which < 3; which++) { 54512751Ssam switch (which) { 54612751Ssam 54712751Ssam case 0: 54812751Ssam flag = FREAD; break; 54912751Ssam 55012751Ssam case 1: 55112751Ssam flag = FWRITE; break; 55212751Ssam 55312751Ssam case 2: 55412751Ssam flag = 0; break; 55512751Ssam } 55623523Skarels for (i = 0; i < nfd; i += NFDBITS) { 55723523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 55817593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 55917593Skarels bits &= ~(1 << j); 56017593Skarels fp = u.u_ofile[i + j]; 56117593Skarels if (fp == NULL) { 56217593Skarels u.u_error = EBADF; 56317593Skarels break; 56417593Skarels } 56517593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 56623523Skarels FD_SET(i + j, &obits[which]); 56717593Skarels n++; 56817593Skarels } 56912751Ssam } 57012751Ssam } 57112751Ssam } 57212751Ssam return (n); 57312751Ssam } 57412751Ssam 5757423Sroot /*ARGSUSED*/ 57612751Ssam seltrue(dev, flag) 57712751Ssam dev_t dev; 57812751Ssam int flag; 5797423Sroot { 5807423Sroot 58112751Ssam return (1); 5827423Sroot } 5838103Sroot 58412751Ssam selwakeup(p, coll) 58512751Ssam register struct proc *p; 58612751Ssam int coll; 5878103Sroot { 5888103Sroot 58912751Ssam if (coll) { 59012751Ssam nselcoll++; 59112751Ssam wakeup((caddr_t)&selwait); 59212751Ssam } 59312751Ssam if (p) { 59417934Skarels int s = splhigh(); 59517270Skarels if (p->p_wchan == (caddr_t)&selwait) { 59617270Skarels if (p->p_stat == SSLEEP) 59717270Skarels setrun(p); 59817270Skarels else 59917270Skarels unsleep(p); 60017270Skarels } else if (p->p_flag & SSEL) 60112751Ssam p->p_flag &= ~SSEL; 60212751Ssam splx(s); 60312751Ssam } 6048103Sroot } 605