123384Smckusick /* 2*37728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3*37728Smckusick * All rights reserved. 423384Smckusick * 5*37728Smckusick * Redistribution and use in source and binary forms are permitted 6*37728Smckusick * provided that the above copyright notice and this paragraph are 7*37728Smckusick * duplicated in all such forms and that any documentation, 8*37728Smckusick * advertising materials, and other materials related to such 9*37728Smckusick * distribution and use acknowledge that the software was developed 10*37728Smckusick * by the University of California, Berkeley. The name of the 11*37728Smckusick * University may not be used to endorse or promote products derived 12*37728Smckusick * from this software without specific prior written permission. 13*37728Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*37728Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*37728Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*37728Smckusick * 17*37728Smckusick * @(#)sys_generic.c 7.10 (Berkeley) 05/09/89 1823384Smckusick */ 197423Sroot 2017094Sbloom #include "param.h" 2117094Sbloom #include "systm.h" 22*37728Smckusick #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; 44*37728Smckusick register struct file *fp; 457746Sroot struct uio auio; 467746Sroot struct iovec aiov; 47*37728Smckusick long cnt, error = 0; 48*37728Smckusick #ifdef KTRACE 49*37728Smckusick struct iovec ktriov; 50*37728Smckusick #endif 517423Sroot 52*37728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 53*37728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 54*37728Smckusick (fp->f_flag & FREAD) == 0) 55*37728Smckusick RETURN (EBADF); 56*37728Smckusick if (uap->count < 0) 57*37728Smckusick 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; 62*37728Smckusick auio.uio_resid = uap->count; 63*37728Smckusick auio.uio_rw = UIO_READ; 64*37728Smckusick auio.uio_segflg = UIO_USERSPACE; 65*37728Smckusick #ifdef KTRACE 66*37728Smckusick /* 67*37728Smckusick * if tracing, save a copy of iovec 68*37728Smckusick */ 69*37728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 70*37728Smckusick ktriov = aiov; 71*37728Smckusick #endif 72*37728Smckusick cnt = uap->count; 73*37728Smckusick if (setjmp(&u.u_qsave)) { 74*37728Smckusick if (auio.uio_resid == cnt) { 75*37728Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 76*37728Smckusick error = EINTR; 77*37728Smckusick else 78*37728Smckusick u.u_eosys = RESTARTSYS; 79*37728Smckusick } 80*37728Smckusick } else 81*37728Smckusick error = (*fp->f_ops->fo_read)(fp, &auio, u.u_cred); 82*37728Smckusick cnt -= auio.uio_resid; 83*37728Smckusick #ifdef KTRACE 84*37728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 85*37728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, ktriov, cnt); 86*37728Smckusick #endif 87*37728Smckusick u.u_r.r_val1 = cnt; 88*37728Smckusick 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; 98*37728Smckusick register struct file *fp; 997820Sroot struct uio auio; 100*37728Smckusick register struct iovec *iov; 101*37728Smckusick struct iovec aiov[UIO_SMALLIOV]; 102*37728Smckusick long i, cnt, error = 0; 103*37728Smckusick #ifdef KTRACE 104*37728Smckusick struct iovec *ktriov = NULL; 105*37728Smckusick #endif 1067820Sroot 107*37728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 108*37728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 109*37728Smckusick (fp->f_flag & FREAD) == 0) 110*37728Smckusick RETURN (EBADF); 11137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 112*37728Smckusick if (uap->iovcnt > UIO_MAXIOV) 113*37728Smckusick 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; 120*37728Smckusick auio.uio_rw = UIO_READ; 121*37728Smckusick auio.uio_segflg = UIO_USERSPACE; 122*37728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 123*37728Smckusick uap->iovcnt * sizeof (struct iovec))) 12437127Skarels goto done; 125*37728Smckusick auio.uio_resid = 0; 126*37728Smckusick for (i = 0; i < uap->iovcnt; i++) { 127*37728Smckusick if (iov->iov_len < 0) { 128*37728Smckusick error = EINVAL; 129*37728Smckusick goto done; 130*37728Smckusick } 131*37728Smckusick auio.uio_resid += iov->iov_len; 132*37728Smckusick if (auio.uio_resid < 0) { 133*37728Smckusick error = EINVAL; 134*37728Smckusick goto done; 135*37728Smckusick } 136*37728Smckusick iov++; 137*37728Smckusick } 138*37728Smckusick #ifdef KTRACE 139*37728Smckusick /* 140*37728Smckusick * if tracing, save a copy of iovec 141*37728Smckusick */ 142*37728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) { 143*37728Smckusick int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 144*37728Smckusick 145*37728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 146*37728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 147*37728Smckusick } 148*37728Smckusick #endif 149*37728Smckusick cnt = auio.uio_resid; 150*37728Smckusick if (setjmp(&u.u_qsave)) { 151*37728Smckusick if (auio.uio_resid == cnt) { 152*37728Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 153*37728Smckusick error = EINTR; 154*37728Smckusick else 155*37728Smckusick u.u_eosys = RESTARTSYS; 156*37728Smckusick } 157*37728Smckusick } else 158*37728Smckusick error = (*fp->f_ops->fo_read)(fp, &auio, u.u_cred); 159*37728Smckusick cnt -= auio.uio_resid; 160*37728Smckusick #ifdef KTRACE 161*37728Smckusick if (ktriov != NULL) { 162*37728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, ktriov, cnt); 163*37728Smckusick FREE(ktriov, M_TEMP); 164*37728Smckusick } 165*37728Smckusick #endif 166*37728Smckusick u.u_r.r_val1 = cnt; 16737127Skarels done: 168*37728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 16937127Skarels FREE(iov, M_IOV); 170*37728Smckusick 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; 183*37728Smckusick register struct file *fp; 1847820Sroot struct uio auio; 1857820Sroot struct iovec aiov; 186*37728Smckusick long cnt, error = 0; 187*37728Smckusick #ifdef KTRACE 188*37728Smckusick struct iovec ktriov; 189*37728Smckusick #endif 1907423Sroot 191*37728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 192*37728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 193*37728Smckusick (fp->f_flag & FWRITE) == 0) 194*37728Smckusick RETURN (EBADF); 195*37728Smckusick if (uap->count < 0) 196*37728Smckusick RETURN (EINVAL); 197*37728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 198*37728Smckusick aiov.iov_len = uap->count; 1997820Sroot auio.uio_iov = &aiov; 2007820Sroot auio.uio_iovcnt = 1; 201*37728Smckusick auio.uio_resid = uap->count; 202*37728Smckusick auio.uio_rw = UIO_WRITE; 203*37728Smckusick auio.uio_segflg = UIO_USERSPACE; 204*37728Smckusick #ifdef KTRACE 205*37728Smckusick /* 206*37728Smckusick * if tracing, save a copy of iovec 207*37728Smckusick */ 208*37728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 209*37728Smckusick ktriov = aiov; 210*37728Smckusick #endif 211*37728Smckusick cnt = uap->count; 212*37728Smckusick if (setjmp(&u.u_qsave)) { 213*37728Smckusick if (auio.uio_resid == cnt) { 214*37728Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 215*37728Smckusick error = EINTR; 216*37728Smckusick else 217*37728Smckusick u.u_eosys = RESTARTSYS; 218*37728Smckusick } 219*37728Smckusick } else 220*37728Smckusick error = (*fp->f_ops->fo_write)(fp, &auio, u.u_cred); 221*37728Smckusick cnt -= auio.uio_resid; 222*37728Smckusick #ifdef KTRACE 223*37728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 224*37728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 225*37728Smckusick ktriov, cnt); 226*37728Smckusick #endif 227*37728Smckusick u.u_r.r_val1 = cnt; 228*37728Smckusick 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; 238*37728Smckusick register struct file *fp; 2397820Sroot struct uio auio; 240*37728Smckusick register struct iovec *iov; 241*37728Smckusick struct iovec aiov[UIO_SMALLIOV]; 242*37728Smckusick long i, cnt, error = 0; 243*37728Smckusick #ifdef KTRACE 244*37728Smckusick struct iovec *ktriov = NULL; 245*37728Smckusick #endif 2467820Sroot 247*37728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 248*37728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 249*37728Smckusick (fp->f_flag & FWRITE) == 0) 250*37728Smckusick RETURN (EBADF); 25137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 252*37728Smckusick if (uap->iovcnt > UIO_MAXIOV) 253*37728Smckusick 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; 260*37728Smckusick auio.uio_rw = UIO_WRITE; 261*37728Smckusick auio.uio_segflg = UIO_USERSPACE; 262*37728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 263*37728Smckusick uap->iovcnt * sizeof (struct iovec))) 26437127Skarels goto done; 265*37728Smckusick auio.uio_resid = 0; 266*37728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2677820Sroot if (iov->iov_len < 0) { 268*37728Smckusick error = EINVAL; 269*37728Smckusick goto done; 2707820Sroot } 271*37728Smckusick auio.uio_resid += iov->iov_len; 272*37728Smckusick if (auio.uio_resid < 0) { 273*37728Smckusick error = EINVAL; 274*37728Smckusick goto done; 2757820Sroot } 27613270Ssam iov++; 2777820Sroot } 27837127Skarels #ifdef KTRACE 279*37728Smckusick /* 280*37728Smckusick * if tracing, save a copy of iovec 281*37728Smckusick */ 28237127Skarels if (KTRPOINT(u.u_procp, KTR_GENIO)) { 283*37728Smckusick int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 28437127Skarels 28537127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 286*37728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 28737127Skarels } 28837127Skarels #endif 289*37728Smckusick cnt = auio.uio_resid; 29018309Smckusick if (setjmp(&u.u_qsave)) { 291*37728Smckusick if (auio.uio_resid == cnt) { 29221009Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 293*37728Smckusick error = EINTR; 29418309Smckusick else 29518309Smckusick u.u_eosys = RESTARTSYS; 29618309Smckusick } 29712751Ssam } else 298*37728Smckusick error = (*fp->f_ops->fo_write)(fp, &auio, u.u_cred); 299*37728Smckusick cnt -= auio.uio_resid; 30037127Skarels #ifdef KTRACE 30137127Skarels if (ktriov != NULL) { 302*37728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 303*37728Smckusick ktriov, cnt); 30437127Skarels FREE(ktriov, M_TEMP); 30537127Skarels } 30637127Skarels #endif 307*37728Smckusick u.u_r.r_val1 = cnt; 308*37728Smckusick done: 309*37728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 310*37728Smckusick FREE(iov, M_IOV); 311*37728Smckusick 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; 324*37728Smckusick } *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 332*37728Smckusick if ((unsigned)uap->fdes >= NOFILE || 333*37728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 334*37728Smckusick 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