1*21009Smckusick /* sys_generic.c 6.9 85/05/22 */ 27423Sroot 317094Sbloom #include "param.h" 417094Sbloom #include "systm.h" 517094Sbloom #include "dir.h" 617094Sbloom #include "user.h" 717094Sbloom #include "ioctl.h" 817094Sbloom #include "file.h" 917094Sbloom #include "proc.h" 1017094Sbloom #include "uio.h" 1117094Sbloom #include "kernel.h" 1217094Sbloom #include "stat.h" 137423Sroot 147423Sroot /* 157423Sroot * Read system call. 167423Sroot */ 177423Sroot read() 187423Sroot { 197423Sroot register struct a { 207423Sroot int fdes; 217423Sroot char *cbuf; 227423Sroot unsigned count; 237820Sroot } *uap = (struct a *)u.u_ap; 247746Sroot struct uio auio; 257746Sroot struct iovec aiov; 267423Sroot 277820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 287820Sroot aiov.iov_len = uap->count; 297820Sroot auio.uio_iov = &aiov; 307820Sroot auio.uio_iovcnt = 1; 317820Sroot rwuio(&auio, UIO_READ); 327820Sroot } 337820Sroot 347820Sroot readv() 357820Sroot { 367820Sroot register struct a { 377820Sroot int fdes; 387820Sroot struct iovec *iovp; 397820Sroot int iovcnt; 407820Sroot } *uap = (struct a *)u.u_ap; 417820Sroot struct uio auio; 427820Sroot struct iovec aiov[16]; /* XXX */ 437820Sroot 447820Sroot if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 457423Sroot u.u_error = EINVAL; 467423Sroot return; 477423Sroot } 487820Sroot auio.uio_iov = aiov; 497820Sroot auio.uio_iovcnt = uap->iovcnt; 509999Ssam u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 519999Ssam (unsigned)(uap->iovcnt * sizeof (struct iovec))); 529999Ssam if (u.u_error) 537423Sroot return; 547820Sroot rwuio(&auio, UIO_READ); 557423Sroot } 567423Sroot 577423Sroot /* 587423Sroot * Write system call 597423Sroot */ 607423Sroot write() 617423Sroot { 627423Sroot register struct a { 637423Sroot int fdes; 647423Sroot char *cbuf; 657820Sroot int count; 667820Sroot } *uap = (struct a *)u.u_ap; 677820Sroot struct uio auio; 687820Sroot struct iovec aiov; 697423Sroot 707820Sroot auio.uio_iov = &aiov; 717820Sroot auio.uio_iovcnt = 1; 727820Sroot aiov.iov_base = uap->cbuf; 737820Sroot aiov.iov_len = uap->count; 747820Sroot rwuio(&auio, UIO_WRITE); 757820Sroot } 767820Sroot 777820Sroot writev() 787820Sroot { 797820Sroot register struct a { 807820Sroot int fdes; 817820Sroot struct iovec *iovp; 827820Sroot int iovcnt; 837820Sroot } *uap = (struct a *)u.u_ap; 847820Sroot struct uio auio; 857820Sroot struct iovec aiov[16]; /* XXX */ 867820Sroot 877820Sroot if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 887423Sroot u.u_error = EINVAL; 897423Sroot return; 907423Sroot } 917820Sroot auio.uio_iov = aiov; 927820Sroot auio.uio_iovcnt = uap->iovcnt; 939999Ssam u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 949999Ssam (unsigned)(uap->iovcnt * sizeof (struct iovec))); 959999Ssam if (u.u_error) 967820Sroot return; 977820Sroot rwuio(&auio, UIO_WRITE); 987820Sroot } 997820Sroot 1007820Sroot rwuio(uio, rw) 1017820Sroot register struct uio *uio; 1027820Sroot enum uio_rw rw; 1037820Sroot { 1047820Sroot struct a { 1057820Sroot int fdes; 1067820Sroot }; 1077820Sroot register struct file *fp; 1087820Sroot register struct iovec *iov; 1097820Sroot int i, count; 1107820Sroot 1117820Sroot GETF(fp, ((struct a *)u.u_ap)->fdes); 1127820Sroot if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) { 1137423Sroot u.u_error = EBADF; 1147423Sroot return; 1157423Sroot } 1167820Sroot uio->uio_resid = 0; 11716702Smckusick uio->uio_segflg = UIO_USERSPACE; 1187820Sroot iov = uio->uio_iov; 1197820Sroot for (i = 0; i < uio->uio_iovcnt; i++) { 1207820Sroot if (iov->iov_len < 0) { 1217820Sroot u.u_error = EINVAL; 1227820Sroot return; 1237820Sroot } 1247820Sroot uio->uio_resid += iov->iov_len; 1257820Sroot if (uio->uio_resid < 0) { 1267820Sroot u.u_error = EINVAL; 1277820Sroot return; 1287820Sroot } 12913270Ssam iov++; 1307820Sroot } 1317820Sroot count = uio->uio_resid; 13212751Ssam uio->uio_offset = fp->f_offset; 13318309Smckusick if (setjmp(&u.u_qsave)) { 13418309Smckusick if (uio->uio_resid == count) { 135*21009Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 13618309Smckusick u.u_error = EINTR; 13718309Smckusick else 13818309Smckusick u.u_eosys = RESTARTSYS; 13918309Smckusick } 14012751Ssam } else 14112751Ssam u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 1427820Sroot u.u_r.r_val1 = count - uio->uio_resid; 14312751Ssam fp->f_offset += u.u_r.r_val1; 1447423Sroot } 1457423Sroot 1467423Sroot /* 1477423Sroot * Ioctl system call 1487423Sroot */ 1497423Sroot ioctl() 1507423Sroot { 1517423Sroot register struct file *fp; 1527624Ssam struct a { 1537423Sroot int fdes; 1547423Sroot int cmd; 1557423Sroot caddr_t cmarg; 1567423Sroot } *uap; 1577820Sroot register int com; 1587820Sroot register u_int size; 1597624Ssam char data[IOCPARM_MASK+1]; 1607423Sroot 1617423Sroot uap = (struct a *)u.u_ap; 16217004Smckusick GETF(fp, uap->fdes); 1637423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 1647423Sroot u.u_error = EBADF; 1657423Sroot return; 1667423Sroot } 1677624Ssam com = uap->cmd; 1687624Ssam 16913228Ssam #if defined(vax) && defined(COMPAT) 1707624Ssam /* 1717624Ssam * Map old style ioctl's into new for the 1727624Ssam * sake of backwards compatibility (sigh). 1737624Ssam */ 1747624Ssam if ((com&~0xffff) == 0) { 1757624Ssam com = mapioctl(com); 1767624Ssam if (com == 0) { 1777624Ssam u.u_error = EINVAL; 1787624Ssam return; 1797624Ssam } 1807624Ssam } 1817624Ssam #endif 1827624Ssam if (com == FIOCLEX) { 1839592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 1847423Sroot return; 1857423Sroot } 1867624Ssam if (com == FIONCLEX) { 1879592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 1887423Sroot return; 1897423Sroot } 1907624Ssam 1917624Ssam /* 1927624Ssam * Interpret high order word to find 1937624Ssam * amount of data to be copied to/from the 1947624Ssam * user's address space. 1957624Ssam */ 1967624Ssam size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 1977624Ssam if (size > sizeof (data)) { 1987624Ssam u.u_error = EFAULT; 1997423Sroot return; 2007423Sroot } 20110601Ssam if (com&IOC_IN) { 20210601Ssam if (size) { 20310601Ssam u.u_error = 20410601Ssam copyin(uap->cmarg, (caddr_t)data, (u_int)size); 20510601Ssam if (u.u_error) 20610601Ssam return; 20710601Ssam } else 20810601Ssam *(caddr_t *)data = uap->cmarg; 20910601Ssam } else if ((com&IOC_OUT) && size) 21010601Ssam /* 21110601Ssam * Zero the buffer on the stack so the user 21210601Ssam * always gets back something deterministic. 21310601Ssam */ 2147624Ssam bzero((caddr_t)data, size); 21511284Ssam else if (com&IOC_VOID) 21611284Ssam *(caddr_t *)data = uap->cmarg; 2177423Sroot 21812751Ssam switch (com) { 2197624Ssam 22012751Ssam case FIONBIO: 22112751Ssam u.u_error = fset(fp, FNDELAY, *(int *)data); 22212751Ssam return; 22312751Ssam 22412751Ssam case FIOASYNC: 22512751Ssam u.u_error = fset(fp, FASYNC, *(int *)data); 22612751Ssam return; 22712751Ssam 22812751Ssam case FIOSETOWN: 22912751Ssam u.u_error = fsetown(fp, *(int *)data); 23012751Ssam return; 23112751Ssam 23212751Ssam case FIOGETOWN: 23312751Ssam u.u_error = fgetown(fp, (int *)data); 23412751Ssam return; 2357423Sroot } 23612751Ssam u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 2377624Ssam /* 2387624Ssam * Copy any data to user, size was 2397624Ssam * already set and checked above. 2407624Ssam */ 2419999Ssam if (u.u_error == 0 && (com&IOC_OUT) && size) 2429999Ssam u.u_error = copyout(data, uap->cmarg, (u_int)size); 2437423Sroot } 2447423Sroot 24512751Ssam int unselect(); 24612751Ssam int nselcoll; 24717593Skarels 2487423Sroot /* 24917593Skarels * Select uses bit masks of file descriptors in ints. 25017593Skarels * These macros manipulate such bit fields (the filesystem macros use chars). 25117593Skarels */ 25217593Skarels #define NBI (sizeof(int) * NBBY) /* bits per int */ 25317593Skarels #define NI howmany(NOFILE, NBI) 25417593Skarels #define tbit(p, n) ((p)[(n)/NBI] & (1 << ((n) % NBI))) 25517593Skarels #define sbit(p, n) ((p)[(n)/NBI] |= (1 << ((n) % NBI))) 25617593Skarels #define cbit(p, n) ((p)[(n)/NBI] &= ~(1 << ((n) % NBI))) 25717593Skarels 25817593Skarels /* 25912751Ssam * Select system call. 2607423Sroot */ 26112751Ssam select() 26212751Ssam { 26312751Ssam register struct uap { 26412751Ssam int nd; 26517593Skarels int *in, *ou, *ex; 26612751Ssam struct timeval *tv; 26712751Ssam } *uap = (struct uap *)u.u_ap; 26817593Skarels int ibits[3][NI], obits[3][NI]; 26912751Ssam struct timeval atv; 27017593Skarels int s, ncoll, ni; 27112751Ssam label_t lqsave; 27212751Ssam 27317593Skarels bzero(ibits, sizeof(ibits)); 27417593Skarels bzero(obits, sizeof(obits)); 27512751Ssam if (uap->nd > NOFILE) 27612751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 27717593Skarels ni = howmany(uap->nd, NBI); 27812751Ssam 27912751Ssam #define getbits(name, x) \ 28012751Ssam if (uap->name) { \ 28117593Skarels u.u_error = copyin((caddr_t)uap->name, (caddr_t)ibits[x], \ 28217593Skarels ni * sizeof(int)); \ 28312751Ssam if (u.u_error) \ 28412751Ssam goto done; \ 28517593Skarels } 28612751Ssam getbits(in, 0); 28712751Ssam getbits(ou, 1); 28812751Ssam getbits(ex, 2); 28912751Ssam #undef getbits 29012751Ssam 29112751Ssam if (uap->tv) { 29212751Ssam u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 29312751Ssam sizeof (atv)); 29412751Ssam if (u.u_error) 29512751Ssam goto done; 29612751Ssam if (itimerfix(&atv)) { 29712751Ssam u.u_error = EINVAL; 29812751Ssam goto done; 29912751Ssam } 30017934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 30112751Ssam } 30212751Ssam retry: 30312751Ssam ncoll = nselcoll; 30412751Ssam u.u_procp->p_flag |= SSEL; 30517593Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 30612751Ssam if (u.u_error || u.u_r.r_val1) 30712751Ssam goto done; 30817934Skarels s = splhigh(); 30912971Ssam /* this should be timercmp(&time, &atv, >=) */ 31012971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 31112971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 31212751Ssam splx(s); 31312751Ssam goto done; 31412751Ssam } 31512751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 31612751Ssam u.u_procp->p_flag &= ~SSEL; 31712751Ssam splx(s); 31812751Ssam goto retry; 31912751Ssam } 32012751Ssam u.u_procp->p_flag &= ~SSEL; 32112751Ssam if (uap->tv) { 32212751Ssam lqsave = u.u_qsave; 32312751Ssam if (setjmp(&u.u_qsave)) { 32412751Ssam untimeout(unselect, (caddr_t)u.u_procp); 32512751Ssam u.u_error = EINTR; 32612751Ssam splx(s); 32712751Ssam goto done; 32812751Ssam } 32912751Ssam timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 33012751Ssam } 33112751Ssam sleep((caddr_t)&selwait, PZERO+1); 33212751Ssam if (uap->tv) { 33312751Ssam u.u_qsave = lqsave; 33412751Ssam untimeout(unselect, (caddr_t)u.u_procp); 33512751Ssam } 33612751Ssam splx(s); 33712751Ssam goto retry; 33812751Ssam done: 33912751Ssam #define putbits(name, x) \ 34012751Ssam if (uap->name) { \ 34117593Skarels int error = copyout((caddr_t)obits[x], (caddr_t)uap->name, \ 34217593Skarels ni * sizeof(int)); \ 34312751Ssam if (error) \ 34412751Ssam u.u_error = error; \ 34512751Ssam } 34612751Ssam putbits(in, 0); 34712751Ssam putbits(ou, 1); 34812751Ssam putbits(ex, 2); 34912751Ssam #undef putbits 35012751Ssam } 35112751Ssam 35212751Ssam unselect(p) 35312751Ssam register struct proc *p; 35412751Ssam { 35517934Skarels register int s = splhigh(); 35612751Ssam 35712751Ssam switch (p->p_stat) { 35812751Ssam 35912751Ssam case SSLEEP: 36012751Ssam setrun(p); 36112751Ssam break; 36212751Ssam 36312751Ssam case SSTOP: 36412751Ssam unsleep(p); 36512751Ssam break; 36612751Ssam } 36712751Ssam splx(s); 36812751Ssam } 36912751Ssam 37017593Skarels selscan(ibits, obits, nfd) 37117593Skarels int (*ibits)[NI], (*obits)[NI]; 37212751Ssam { 37317593Skarels register int which, bits, i, j; 37412751Ssam int flag; 37512751Ssam struct file *fp; 37612751Ssam int n = 0; 37712751Ssam 37812751Ssam for (which = 0; which < 3; which++) { 37912751Ssam switch (which) { 38012751Ssam 38112751Ssam case 0: 38212751Ssam flag = FREAD; break; 38312751Ssam 38412751Ssam case 1: 38512751Ssam flag = FWRITE; break; 38612751Ssam 38712751Ssam case 2: 38812751Ssam flag = 0; break; 38912751Ssam } 39017593Skarels for (i = 0; i < nfd; i += NBI) { 39117593Skarels bits = ibits[which][i/NBI]; 39217593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 39317593Skarels bits &= ~(1 << j); 39417593Skarels fp = u.u_ofile[i + j]; 39517593Skarels if (fp == NULL) { 39617593Skarels u.u_error = EBADF; 39717593Skarels break; 39817593Skarels } 39917593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 40017593Skarels sbit(obits[which], i + j); 40117593Skarels n++; 40217593Skarels } 40312751Ssam } 40412751Ssam } 40512751Ssam } 40612751Ssam return (n); 40712751Ssam } 40812751Ssam 4097423Sroot /*ARGSUSED*/ 41012751Ssam seltrue(dev, flag) 41112751Ssam dev_t dev; 41212751Ssam int flag; 4137423Sroot { 4147423Sroot 41512751Ssam return (1); 4167423Sroot } 4178103Sroot 41812751Ssam selwakeup(p, coll) 41912751Ssam register struct proc *p; 42012751Ssam int coll; 4218103Sroot { 4228103Sroot 42312751Ssam if (coll) { 42412751Ssam nselcoll++; 42512751Ssam wakeup((caddr_t)&selwait); 42612751Ssam } 42712751Ssam if (p) { 42817934Skarels int s = splhigh(); 42917270Skarels if (p->p_wchan == (caddr_t)&selwait) { 43017270Skarels if (p->p_stat == SSLEEP) 43117270Skarels setrun(p); 43217270Skarels else 43317270Skarels unsleep(p); 43417270Skarels } else if (p->p_flag & SSEL) 43512751Ssam p->p_flag &= ~SSEL; 43612751Ssam splx(s); 43712751Ssam } 4388103Sroot } 439