123384Smckusick /* 2*37127Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 323384Smckusick * All rights reserved. The Berkeley software License Agreement 423384Smckusick * specifies the terms and conditions for redistribution. 523384Smckusick * 6*37127Skarels * @(#)sys_generic.c 7.9 (Berkeley) 03/10/89 723384Smckusick */ 87423Sroot 917094Sbloom #include "param.h" 1017094Sbloom #include "systm.h" 1117094Sbloom #include "dir.h" 1217094Sbloom #include "user.h" 1317094Sbloom #include "ioctl.h" 1417094Sbloom #include "file.h" 1517094Sbloom #include "proc.h" 1617094Sbloom #include "uio.h" 1717094Sbloom #include "kernel.h" 1817094Sbloom #include "stat.h" 1931653Smckusick #include "malloc.h" 20*37127Skarels #ifdef KTRACE 21*37127Skarels #include "ktrace.h" 22*37127Skarels #endif 237423Sroot 247423Sroot /* 257423Sroot * Read system call. 267423Sroot */ 277423Sroot read() 287423Sroot { 297423Sroot register struct a { 307423Sroot int fdes; 317423Sroot char *cbuf; 327423Sroot unsigned count; 337820Sroot } *uap = (struct a *)u.u_ap; 347746Sroot struct uio auio; 357746Sroot struct iovec aiov; 367423Sroot 377820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 387820Sroot aiov.iov_len = uap->count; 397820Sroot auio.uio_iov = &aiov; 407820Sroot auio.uio_iovcnt = 1; 417820Sroot rwuio(&auio, UIO_READ); 427820Sroot } 437820Sroot 447820Sroot readv() 457820Sroot { 467820Sroot register struct a { 477820Sroot int fdes; 487820Sroot struct iovec *iovp; 4926474Skarels unsigned iovcnt; 507820Sroot } *uap = (struct a *)u.u_ap; 517820Sroot struct uio auio; 52*37127Skarels struct iovec aiov[UIO_SMALLIOV], *iov; 537820Sroot 54*37127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 55*37127Skarels if (uap->iovcnt > UIO_MAXIOV) { 56*37127Skarels u.u_error = EINVAL; 57*37127Skarels return; 58*37127Skarels } 59*37127Skarels MALLOC(iov, struct iovec *, 60*37127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 61*37127Skarels if (iov == NULL) { 62*37127Skarels u.u_error = ENOMEM; 63*37127Skarels return; 64*37127Skarels } 65*37127Skarels } else 66*37127Skarels iov = aiov; 67*37127Skarels auio.uio_iov = iov; 687820Sroot auio.uio_iovcnt = uap->iovcnt; 69*37127Skarels u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)auio.uio_iov, 7026474Skarels uap->iovcnt * sizeof (struct iovec)); 719999Ssam if (u.u_error) 72*37127Skarels goto done; 737820Sroot rwuio(&auio, UIO_READ); 74*37127Skarels done: 75*37127Skarels if (iov != aiov) 76*37127Skarels FREE(iov, M_IOV); 777423Sroot } 787423Sroot 797423Sroot /* 807423Sroot * Write system call 817423Sroot */ 827423Sroot write() 837423Sroot { 847423Sroot register struct a { 857423Sroot int fdes; 867423Sroot char *cbuf; 8726474Skarels unsigned count; 887820Sroot } *uap = (struct a *)u.u_ap; 897820Sroot struct uio auio; 907820Sroot struct iovec aiov; 917423Sroot 927820Sroot auio.uio_iov = &aiov; 937820Sroot auio.uio_iovcnt = 1; 947820Sroot aiov.iov_base = uap->cbuf; 957820Sroot aiov.iov_len = uap->count; 967820Sroot rwuio(&auio, UIO_WRITE); 977820Sroot } 987820Sroot 997820Sroot writev() 1007820Sroot { 1017820Sroot register struct a { 1027820Sroot int fdes; 1037820Sroot struct iovec *iovp; 10426474Skarels unsigned iovcnt; 1057820Sroot } *uap = (struct a *)u.u_ap; 1067820Sroot struct uio auio; 107*37127Skarels struct iovec aiov[UIO_SMALLIOV], *iov; 1087820Sroot 109*37127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 110*37127Skarels if (uap->iovcnt > UIO_MAXIOV) { 111*37127Skarels u.u_error = EINVAL; 112*37127Skarels return; 113*37127Skarels } 114*37127Skarels MALLOC(iov, struct iovec *, 115*37127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 116*37127Skarels if (iov == NULL) { 117*37127Skarels u.u_error = ENOMEM; 118*37127Skarels return; 119*37127Skarels } 120*37127Skarels } else 121*37127Skarels iov = aiov; 122*37127Skarels auio.uio_iov = iov; 1237820Sroot auio.uio_iovcnt = uap->iovcnt; 124*37127Skarels u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)auio.uio_iov, 12526474Skarels uap->iovcnt * sizeof (struct iovec)); 1269999Ssam if (u.u_error) 127*37127Skarels goto done; 1287820Sroot rwuio(&auio, UIO_WRITE); 129*37127Skarels done: 130*37127Skarels if (iov != aiov) 131*37127Skarels FREE(iov, M_IOV); 1327820Sroot } 1337820Sroot 1347820Sroot rwuio(uio, rw) 1357820Sroot register struct uio *uio; 1367820Sroot enum uio_rw rw; 1377820Sroot { 1387820Sroot struct a { 1397820Sroot int fdes; 1407820Sroot }; 1417820Sroot register struct file *fp; 1427820Sroot register struct iovec *iov; 1437820Sroot int i, count; 144*37127Skarels #ifdef KTRACE 145*37127Skarels struct iovec *ktriov = NULL; 146*37127Skarels #endif 1477820Sroot 148*37127Skarels 1497820Sroot GETF(fp, ((struct a *)u.u_ap)->fdes); 1507820Sroot if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) { 1517423Sroot u.u_error = EBADF; 1527423Sroot return; 1537423Sroot } 1547820Sroot uio->uio_resid = 0; 15516702Smckusick uio->uio_segflg = UIO_USERSPACE; 1567820Sroot iov = uio->uio_iov; 1577820Sroot for (i = 0; i < uio->uio_iovcnt; i++) { 1587820Sroot if (iov->iov_len < 0) { 1597820Sroot u.u_error = EINVAL; 1607820Sroot return; 1617820Sroot } 1627820Sroot uio->uio_resid += iov->iov_len; 1637820Sroot if (uio->uio_resid < 0) { 1647820Sroot u.u_error = EINVAL; 1657820Sroot return; 1667820Sroot } 16713270Ssam iov++; 1687820Sroot } 1697820Sroot count = uio->uio_resid; 170*37127Skarels #ifdef KTRACE 171*37127Skarels /* if tracing, save a copy of iovec */ 172*37127Skarels if (KTRPOINT(u.u_procp, KTR_GENIO)) { 173*37127Skarels int iovlen = uio->uio_iovcnt * sizeof (struct iovec); 174*37127Skarels 175*37127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 176*37127Skarels if (ktriov != NULL) 177*37127Skarels bcopy((caddr_t)uio->uio_iov, (caddr_t)ktriov, iovlen); 178*37127Skarels } 179*37127Skarels #endif 18018309Smckusick if (setjmp(&u.u_qsave)) { 18118309Smckusick if (uio->uio_resid == count) { 18221009Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 18318309Smckusick u.u_error = EINTR; 18418309Smckusick else 18518309Smckusick u.u_eosys = RESTARTSYS; 18618309Smckusick } 18712751Ssam } else 18812751Ssam u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 1897820Sroot u.u_r.r_val1 = count - uio->uio_resid; 190*37127Skarels #ifdef KTRACE 191*37127Skarels if (ktriov != NULL) { 192*37127Skarels ktrgenio(u.u_procp->p_tracep, ((struct a *)u.u_ap)->fdes, 193*37127Skarels rw, ktriov, u.u_r.r_val1); 194*37127Skarels FREE(ktriov, M_TEMP); 195*37127Skarels } 196*37127Skarels #endif 1977423Sroot } 1987423Sroot 1997423Sroot /* 2007423Sroot * Ioctl system call 2017423Sroot */ 2027423Sroot ioctl() 2037423Sroot { 2047423Sroot register struct file *fp; 2057624Ssam struct a { 2067423Sroot int fdes; 2077423Sroot int cmd; 2087423Sroot caddr_t cmarg; 2097423Sroot } *uap; 2107820Sroot register int com; 2117820Sroot register u_int size; 21231653Smckusick caddr_t memp = 0; 21330530Skarels #define STK_PARAMS 128 21433480Skarels char stkbuf[STK_PARAMS]; 21533480Skarels caddr_t data = stkbuf; 2167423Sroot 2177423Sroot uap = (struct a *)u.u_ap; 21817004Smckusick GETF(fp, uap->fdes); 2197423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 2207423Sroot u.u_error = EBADF; 2217423Sroot return; 2227423Sroot } 2237624Ssam com = uap->cmd; 2247624Ssam 2257624Ssam if (com == FIOCLEX) { 2269592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 2277423Sroot return; 2287423Sroot } 2297624Ssam if (com == FIONCLEX) { 2309592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 2317423Sroot return; 2327423Sroot } 2337624Ssam 2347624Ssam /* 2357624Ssam * Interpret high order word to find 2367624Ssam * amount of data to be copied to/from the 2377624Ssam * user's address space. 2387624Ssam */ 23930530Skarels size = IOCPARM_LEN(com); 24030530Skarels if (size > IOCPARM_MAX) { 241*37127Skarels u.u_error = ENOTTY; 2427423Sroot return; 2437423Sroot } 24433480Skarels if (size > sizeof (stkbuf)) { 245*37127Skarels memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS, 24634473Smckusick M_WAITOK); 24731653Smckusick data = memp; 24830530Skarels } 24910601Ssam if (com&IOC_IN) { 25010601Ssam if (size) { 251*37127Skarels u.u_error = copyin(uap->cmarg, data, (u_int)size); 25231653Smckusick if (u.u_error) { 25331653Smckusick if (memp) 25431653Smckusick free(memp, M_IOCTLOPS); 25510601Ssam return; 25631653Smckusick } 25710601Ssam } else 25810601Ssam *(caddr_t *)data = uap->cmarg; 25910601Ssam } else if ((com&IOC_OUT) && size) 26010601Ssam /* 261*37127Skarels * Zero the buffer so the user always 262*37127Skarels * gets back something deterministic. 26310601Ssam */ 26430530Skarels bzero(data, size); 26511284Ssam else if (com&IOC_VOID) 26611284Ssam *(caddr_t *)data = uap->cmarg; 2677423Sroot 26812751Ssam switch (com) { 2697624Ssam 27012751Ssam case FIONBIO: 27112751Ssam u.u_error = fset(fp, FNDELAY, *(int *)data); 27230530Skarels break; 27312751Ssam 27412751Ssam case FIOASYNC: 27512751Ssam u.u_error = fset(fp, FASYNC, *(int *)data); 27630530Skarels break; 27712751Ssam 27812751Ssam case FIOSETOWN: 27912751Ssam u.u_error = fsetown(fp, *(int *)data); 28030530Skarels break; 28112751Ssam 28212751Ssam case FIOGETOWN: 28312751Ssam u.u_error = fgetown(fp, (int *)data); 28430530Skarels break; 28530530Skarels default: 28630530Skarels if (setjmp(&u.u_qsave)) 28730530Skarels u.u_error = EINTR; 28830530Skarels else 28930530Skarels u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 29030530Skarels /* 29130530Skarels * Copy any data to user, size was 29230530Skarels * already set and checked above. 29330530Skarels */ 29430530Skarels if (u.u_error == 0 && (com&IOC_OUT) && size) 29530530Skarels u.u_error = copyout(data, uap->cmarg, (u_int)size); 29630530Skarels break; 2977423Sroot } 29831653Smckusick if (memp) 29931653Smckusick free(memp, M_IOCTLOPS); 3007423Sroot } 3017423Sroot 30212751Ssam int unselect(); 30312751Ssam int nselcoll; 30417593Skarels 3057423Sroot /* 30612751Ssam * Select system call. 3077423Sroot */ 30812751Ssam select() 30912751Ssam { 31012751Ssam register struct uap { 31112751Ssam int nd; 31223523Skarels fd_set *in, *ou, *ex; 31312751Ssam struct timeval *tv; 31412751Ssam } *uap = (struct uap *)u.u_ap; 31523523Skarels fd_set ibits[3], obits[3]; 31612751Ssam struct timeval atv; 31717593Skarels int s, ncoll, ni; 31812751Ssam label_t lqsave; 31912751Ssam 32026277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 32126277Skarels bzero((caddr_t)obits, sizeof(obits)); 32212751Ssam if (uap->nd > NOFILE) 32312751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 32423523Skarels ni = howmany(uap->nd, NFDBITS); 32512751Ssam 32612751Ssam #define getbits(name, x) \ 32712751Ssam if (uap->name) { \ 32823523Skarels u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 32926277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 33012751Ssam if (u.u_error) \ 33112751Ssam goto done; \ 33217593Skarels } 33312751Ssam getbits(in, 0); 33412751Ssam getbits(ou, 1); 33512751Ssam getbits(ex, 2); 33612751Ssam #undef getbits 33712751Ssam 33812751Ssam if (uap->tv) { 33912751Ssam u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 34012751Ssam sizeof (atv)); 34112751Ssam if (u.u_error) 34212751Ssam goto done; 34312751Ssam if (itimerfix(&atv)) { 34412751Ssam u.u_error = EINVAL; 34512751Ssam goto done; 34612751Ssam } 34717934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 34812751Ssam } 34912751Ssam retry: 35012751Ssam ncoll = nselcoll; 35112751Ssam u.u_procp->p_flag |= SSEL; 35217593Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 35312751Ssam if (u.u_error || u.u_r.r_val1) 35412751Ssam goto done; 35517934Skarels s = splhigh(); 35612971Ssam /* this should be timercmp(&time, &atv, >=) */ 35712971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 35812971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 35912751Ssam splx(s); 36012751Ssam goto done; 36112751Ssam } 36212751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 36312751Ssam splx(s); 36412751Ssam goto retry; 36512751Ssam } 36612751Ssam u.u_procp->p_flag &= ~SSEL; 36712751Ssam if (uap->tv) { 36812751Ssam lqsave = u.u_qsave; 36912751Ssam if (setjmp(&u.u_qsave)) { 37012751Ssam untimeout(unselect, (caddr_t)u.u_procp); 37112751Ssam u.u_error = EINTR; 37212751Ssam splx(s); 37312751Ssam goto done; 37412751Ssam } 37512751Ssam timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 37612751Ssam } 37712751Ssam sleep((caddr_t)&selwait, PZERO+1); 37812751Ssam if (uap->tv) { 37912751Ssam u.u_qsave = lqsave; 38012751Ssam untimeout(unselect, (caddr_t)u.u_procp); 38112751Ssam } 38212751Ssam splx(s); 38312751Ssam goto retry; 38412751Ssam done: 38533712Skarels u.u_procp->p_flag &= ~SSEL; 38612751Ssam #define putbits(name, x) \ 38712751Ssam if (uap->name) { \ 38823523Skarels int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 38926277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 39012751Ssam if (error) \ 39112751Ssam u.u_error = error; \ 39212751Ssam } 39326070Skarels if (u.u_error == 0) { 39421106Skarels putbits(in, 0); 39521106Skarels putbits(ou, 1); 39621106Skarels putbits(ex, 2); 39712751Ssam #undef putbits 39821106Skarels } 39912751Ssam } 40012751Ssam 40112751Ssam unselect(p) 40212751Ssam register struct proc *p; 40312751Ssam { 40417934Skarels register int s = splhigh(); 40512751Ssam 40612751Ssam switch (p->p_stat) { 40712751Ssam 40812751Ssam case SSLEEP: 40912751Ssam setrun(p); 41012751Ssam break; 41112751Ssam 41212751Ssam case SSTOP: 41312751Ssam unsleep(p); 41412751Ssam break; 41512751Ssam } 41612751Ssam splx(s); 41712751Ssam } 41812751Ssam 41917593Skarels selscan(ibits, obits, nfd) 42023523Skarels fd_set *ibits, *obits; 42112751Ssam { 42223523Skarels register int which, i, j; 42323523Skarels register fd_mask bits; 42412751Ssam int flag; 42512751Ssam struct file *fp; 42612751Ssam int n = 0; 42712751Ssam 42812751Ssam for (which = 0; which < 3; which++) { 42912751Ssam switch (which) { 43012751Ssam 43112751Ssam case 0: 43212751Ssam flag = FREAD; break; 43312751Ssam 43412751Ssam case 1: 43512751Ssam flag = FWRITE; break; 43612751Ssam 43712751Ssam case 2: 43812751Ssam flag = 0; break; 43912751Ssam } 44023523Skarels for (i = 0; i < nfd; i += NFDBITS) { 44123523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 44217593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 44317593Skarels bits &= ~(1 << j); 44417593Skarels fp = u.u_ofile[i + j]; 44517593Skarels if (fp == NULL) { 44617593Skarels u.u_error = EBADF; 44717593Skarels break; 44817593Skarels } 44917593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 45023523Skarels FD_SET(i + j, &obits[which]); 45117593Skarels n++; 45217593Skarels } 45312751Ssam } 45412751Ssam } 45512751Ssam } 45612751Ssam return (n); 45712751Ssam } 45812751Ssam 4597423Sroot /*ARGSUSED*/ 46012751Ssam seltrue(dev, flag) 46112751Ssam dev_t dev; 46212751Ssam int flag; 4637423Sroot { 4647423Sroot 46512751Ssam return (1); 4667423Sroot } 4678103Sroot 46812751Ssam selwakeup(p, coll) 46912751Ssam register struct proc *p; 47012751Ssam int coll; 4718103Sroot { 4728103Sroot 47312751Ssam if (coll) { 47412751Ssam nselcoll++; 47512751Ssam wakeup((caddr_t)&selwait); 47612751Ssam } 47712751Ssam if (p) { 47817934Skarels int s = splhigh(); 47917270Skarels if (p->p_wchan == (caddr_t)&selwait) { 48017270Skarels if (p->p_stat == SSLEEP) 48117270Skarels setrun(p); 48217270Skarels else 48317270Skarels unsleep(p); 48417270Skarels } else if (p->p_flag & SSEL) 48512751Ssam p->p_flag &= ~SSEL; 48612751Ssam splx(s); 48712751Ssam } 4888103Sroot } 489