1*23384Smckusick /* 2*23384Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23384Smckusick * All rights reserved. The Berkeley software License Agreement 4*23384Smckusick * specifies the terms and conditions for redistribution. 5*23384Smckusick * 6*23384Smckusick * @(#)sys_generic.c 6.11 (Berkeley) 06/08/85 7*23384Smckusick */ 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" 197423Sroot 207423Sroot /* 217423Sroot * Read system call. 227423Sroot */ 237423Sroot read() 247423Sroot { 257423Sroot register struct a { 267423Sroot int fdes; 277423Sroot char *cbuf; 287423Sroot unsigned count; 297820Sroot } *uap = (struct a *)u.u_ap; 307746Sroot struct uio auio; 317746Sroot struct iovec aiov; 327423Sroot 337820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 347820Sroot aiov.iov_len = uap->count; 357820Sroot auio.uio_iov = &aiov; 367820Sroot auio.uio_iovcnt = 1; 377820Sroot rwuio(&auio, UIO_READ); 387820Sroot } 397820Sroot 407820Sroot readv() 417820Sroot { 427820Sroot register struct a { 437820Sroot int fdes; 447820Sroot struct iovec *iovp; 457820Sroot int iovcnt; 467820Sroot } *uap = (struct a *)u.u_ap; 477820Sroot struct uio auio; 487820Sroot struct iovec aiov[16]; /* XXX */ 497820Sroot 507820Sroot if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 517423Sroot u.u_error = EINVAL; 527423Sroot return; 537423Sroot } 547820Sroot auio.uio_iov = aiov; 557820Sroot auio.uio_iovcnt = uap->iovcnt; 569999Ssam u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 579999Ssam (unsigned)(uap->iovcnt * sizeof (struct iovec))); 589999Ssam if (u.u_error) 597423Sroot return; 607820Sroot rwuio(&auio, UIO_READ); 617423Sroot } 627423Sroot 637423Sroot /* 647423Sroot * Write system call 657423Sroot */ 667423Sroot write() 677423Sroot { 687423Sroot register struct a { 697423Sroot int fdes; 707423Sroot char *cbuf; 717820Sroot int count; 727820Sroot } *uap = (struct a *)u.u_ap; 737820Sroot struct uio auio; 747820Sroot struct iovec aiov; 757423Sroot 767820Sroot auio.uio_iov = &aiov; 777820Sroot auio.uio_iovcnt = 1; 787820Sroot aiov.iov_base = uap->cbuf; 797820Sroot aiov.iov_len = uap->count; 807820Sroot rwuio(&auio, UIO_WRITE); 817820Sroot } 827820Sroot 837820Sroot writev() 847820Sroot { 857820Sroot register struct a { 867820Sroot int fdes; 877820Sroot struct iovec *iovp; 887820Sroot int iovcnt; 897820Sroot } *uap = (struct a *)u.u_ap; 907820Sroot struct uio auio; 917820Sroot struct iovec aiov[16]; /* XXX */ 927820Sroot 937820Sroot if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 947423Sroot u.u_error = EINVAL; 957423Sroot return; 967423Sroot } 977820Sroot auio.uio_iov = aiov; 987820Sroot auio.uio_iovcnt = uap->iovcnt; 999999Ssam u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 1009999Ssam (unsigned)(uap->iovcnt * sizeof (struct iovec))); 1019999Ssam if (u.u_error) 1027820Sroot return; 1037820Sroot rwuio(&auio, UIO_WRITE); 1047820Sroot } 1057820Sroot 1067820Sroot rwuio(uio, rw) 1077820Sroot register struct uio *uio; 1087820Sroot enum uio_rw rw; 1097820Sroot { 1107820Sroot struct a { 1117820Sroot int fdes; 1127820Sroot }; 1137820Sroot register struct file *fp; 1147820Sroot register struct iovec *iov; 1157820Sroot int i, count; 1167820Sroot 1177820Sroot GETF(fp, ((struct a *)u.u_ap)->fdes); 1187820Sroot if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) { 1197423Sroot u.u_error = EBADF; 1207423Sroot return; 1217423Sroot } 1227820Sroot uio->uio_resid = 0; 12316702Smckusick uio->uio_segflg = UIO_USERSPACE; 1247820Sroot iov = uio->uio_iov; 1257820Sroot for (i = 0; i < uio->uio_iovcnt; i++) { 1267820Sroot if (iov->iov_len < 0) { 1277820Sroot u.u_error = EINVAL; 1287820Sroot return; 1297820Sroot } 1307820Sroot uio->uio_resid += iov->iov_len; 1317820Sroot if (uio->uio_resid < 0) { 1327820Sroot u.u_error = EINVAL; 1337820Sroot return; 1347820Sroot } 13513270Ssam iov++; 1367820Sroot } 1377820Sroot count = uio->uio_resid; 13812751Ssam uio->uio_offset = fp->f_offset; 13918309Smckusick if (setjmp(&u.u_qsave)) { 14018309Smckusick if (uio->uio_resid == count) { 14121009Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 14218309Smckusick u.u_error = EINTR; 14318309Smckusick else 14418309Smckusick u.u_eosys = RESTARTSYS; 14518309Smckusick } 14612751Ssam } else 14712751Ssam u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 1487820Sroot u.u_r.r_val1 = count - uio->uio_resid; 14912751Ssam fp->f_offset += u.u_r.r_val1; 1507423Sroot } 1517423Sroot 1527423Sroot /* 1537423Sroot * Ioctl system call 1547423Sroot */ 1557423Sroot ioctl() 1567423Sroot { 1577423Sroot register struct file *fp; 1587624Ssam struct a { 1597423Sroot int fdes; 1607423Sroot int cmd; 1617423Sroot caddr_t cmarg; 1627423Sroot } *uap; 1637820Sroot register int com; 1647820Sroot register u_int size; 1657624Ssam char data[IOCPARM_MASK+1]; 1667423Sroot 1677423Sroot uap = (struct a *)u.u_ap; 16817004Smckusick GETF(fp, uap->fdes); 1697423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 1707423Sroot u.u_error = EBADF; 1717423Sroot return; 1727423Sroot } 1737624Ssam com = uap->cmd; 1747624Ssam 17513228Ssam #if defined(vax) && defined(COMPAT) 1767624Ssam /* 1777624Ssam * Map old style ioctl's into new for the 1787624Ssam * sake of backwards compatibility (sigh). 1797624Ssam */ 1807624Ssam if ((com&~0xffff) == 0) { 1817624Ssam com = mapioctl(com); 1827624Ssam if (com == 0) { 1837624Ssam u.u_error = EINVAL; 1847624Ssam return; 1857624Ssam } 1867624Ssam } 1877624Ssam #endif 1887624Ssam if (com == FIOCLEX) { 1899592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 1907423Sroot return; 1917423Sroot } 1927624Ssam if (com == FIONCLEX) { 1939592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 1947423Sroot return; 1957423Sroot } 1967624Ssam 1977624Ssam /* 1987624Ssam * Interpret high order word to find 1997624Ssam * amount of data to be copied to/from the 2007624Ssam * user's address space. 2017624Ssam */ 2027624Ssam size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 2037624Ssam if (size > sizeof (data)) { 2047624Ssam u.u_error = EFAULT; 2057423Sroot return; 2067423Sroot } 20710601Ssam if (com&IOC_IN) { 20810601Ssam if (size) { 20910601Ssam u.u_error = 21010601Ssam copyin(uap->cmarg, (caddr_t)data, (u_int)size); 21110601Ssam if (u.u_error) 21210601Ssam return; 21310601Ssam } else 21410601Ssam *(caddr_t *)data = uap->cmarg; 21510601Ssam } else if ((com&IOC_OUT) && size) 21610601Ssam /* 21710601Ssam * Zero the buffer on the stack so the user 21810601Ssam * always gets back something deterministic. 21910601Ssam */ 2207624Ssam bzero((caddr_t)data, size); 22111284Ssam else if (com&IOC_VOID) 22211284Ssam *(caddr_t *)data = uap->cmarg; 2237423Sroot 22412751Ssam switch (com) { 2257624Ssam 22612751Ssam case FIONBIO: 22712751Ssam u.u_error = fset(fp, FNDELAY, *(int *)data); 22812751Ssam return; 22912751Ssam 23012751Ssam case FIOASYNC: 23112751Ssam u.u_error = fset(fp, FASYNC, *(int *)data); 23212751Ssam return; 23312751Ssam 23412751Ssam case FIOSETOWN: 23512751Ssam u.u_error = fsetown(fp, *(int *)data); 23612751Ssam return; 23712751Ssam 23812751Ssam case FIOGETOWN: 23912751Ssam u.u_error = fgetown(fp, (int *)data); 24012751Ssam return; 2417423Sroot } 24212751Ssam u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 2437624Ssam /* 2447624Ssam * Copy any data to user, size was 2457624Ssam * already set and checked above. 2467624Ssam */ 2479999Ssam if (u.u_error == 0 && (com&IOC_OUT) && size) 2489999Ssam u.u_error = copyout(data, uap->cmarg, (u_int)size); 2497423Sroot } 2507423Sroot 25112751Ssam int unselect(); 25212751Ssam int nselcoll; 25317593Skarels 2547423Sroot /* 25517593Skarels * Select uses bit masks of file descriptors in ints. 25617593Skarels * These macros manipulate such bit fields (the filesystem macros use chars). 25717593Skarels */ 25817593Skarels #define NBI (sizeof(int) * NBBY) /* bits per int */ 25917593Skarels #define NI howmany(NOFILE, NBI) 26017593Skarels #define tbit(p, n) ((p)[(n)/NBI] & (1 << ((n) % NBI))) 26117593Skarels #define sbit(p, n) ((p)[(n)/NBI] |= (1 << ((n) % NBI))) 26217593Skarels #define cbit(p, n) ((p)[(n)/NBI] &= ~(1 << ((n) % NBI))) 26317593Skarels 26417593Skarels /* 26512751Ssam * Select system call. 2667423Sroot */ 26712751Ssam select() 26812751Ssam { 26912751Ssam register struct uap { 27012751Ssam int nd; 27117593Skarels int *in, *ou, *ex; 27212751Ssam struct timeval *tv; 27312751Ssam } *uap = (struct uap *)u.u_ap; 27417593Skarels int ibits[3][NI], obits[3][NI]; 27512751Ssam struct timeval atv; 27617593Skarels int s, ncoll, ni; 27712751Ssam label_t lqsave; 27812751Ssam 27917593Skarels bzero(ibits, sizeof(ibits)); 28017593Skarels bzero(obits, sizeof(obits)); 28112751Ssam if (uap->nd > NOFILE) 28212751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 28317593Skarels ni = howmany(uap->nd, NBI); 28412751Ssam 28512751Ssam #define getbits(name, x) \ 28612751Ssam if (uap->name) { \ 28717593Skarels u.u_error = copyin((caddr_t)uap->name, (caddr_t)ibits[x], \ 28817593Skarels ni * sizeof(int)); \ 28912751Ssam if (u.u_error) \ 29012751Ssam goto done; \ 29117593Skarels } 29212751Ssam getbits(in, 0); 29312751Ssam getbits(ou, 1); 29412751Ssam getbits(ex, 2); 29512751Ssam #undef getbits 29612751Ssam 29712751Ssam if (uap->tv) { 29812751Ssam u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 29912751Ssam sizeof (atv)); 30012751Ssam if (u.u_error) 30112751Ssam goto done; 30212751Ssam if (itimerfix(&atv)) { 30312751Ssam u.u_error = EINVAL; 30412751Ssam goto done; 30512751Ssam } 30617934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 30712751Ssam } 30812751Ssam retry: 30912751Ssam ncoll = nselcoll; 31012751Ssam u.u_procp->p_flag |= SSEL; 31117593Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 31212751Ssam if (u.u_error || u.u_r.r_val1) 31312751Ssam goto done; 31417934Skarels s = splhigh(); 31512971Ssam /* this should be timercmp(&time, &atv, >=) */ 31612971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 31712971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 31812751Ssam splx(s); 31912751Ssam goto done; 32012751Ssam } 32112751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 32212751Ssam u.u_procp->p_flag &= ~SSEL; 32312751Ssam splx(s); 32412751Ssam goto retry; 32512751Ssam } 32612751Ssam u.u_procp->p_flag &= ~SSEL; 32712751Ssam if (uap->tv) { 32812751Ssam lqsave = u.u_qsave; 32912751Ssam if (setjmp(&u.u_qsave)) { 33012751Ssam untimeout(unselect, (caddr_t)u.u_procp); 33112751Ssam u.u_error = EINTR; 33212751Ssam splx(s); 33312751Ssam goto done; 33412751Ssam } 33512751Ssam timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 33612751Ssam } 33712751Ssam sleep((caddr_t)&selwait, PZERO+1); 33812751Ssam if (uap->tv) { 33912751Ssam u.u_qsave = lqsave; 34012751Ssam untimeout(unselect, (caddr_t)u.u_procp); 34112751Ssam } 34212751Ssam splx(s); 34312751Ssam goto retry; 34412751Ssam done: 34512751Ssam #define putbits(name, x) \ 34612751Ssam if (uap->name) { \ 34717593Skarels int error = copyout((caddr_t)obits[x], (caddr_t)uap->name, \ 34817593Skarels ni * sizeof(int)); \ 34912751Ssam if (error) \ 35012751Ssam u.u_error = error; \ 35112751Ssam } 35221106Skarels if (u.u_error != EINTR) { 35321106Skarels putbits(in, 0); 35421106Skarels putbits(ou, 1); 35521106Skarels putbits(ex, 2); 35612751Ssam #undef putbits 35721106Skarels } 35812751Ssam } 35912751Ssam 36012751Ssam unselect(p) 36112751Ssam register struct proc *p; 36212751Ssam { 36317934Skarels register int s = splhigh(); 36412751Ssam 36512751Ssam switch (p->p_stat) { 36612751Ssam 36712751Ssam case SSLEEP: 36812751Ssam setrun(p); 36912751Ssam break; 37012751Ssam 37112751Ssam case SSTOP: 37212751Ssam unsleep(p); 37312751Ssam break; 37412751Ssam } 37512751Ssam splx(s); 37612751Ssam } 37712751Ssam 37817593Skarels selscan(ibits, obits, nfd) 37917593Skarels int (*ibits)[NI], (*obits)[NI]; 38012751Ssam { 38117593Skarels register int which, bits, i, j; 38212751Ssam int flag; 38312751Ssam struct file *fp; 38412751Ssam int n = 0; 38512751Ssam 38612751Ssam for (which = 0; which < 3; which++) { 38712751Ssam switch (which) { 38812751Ssam 38912751Ssam case 0: 39012751Ssam flag = FREAD; break; 39112751Ssam 39212751Ssam case 1: 39312751Ssam flag = FWRITE; break; 39412751Ssam 39512751Ssam case 2: 39612751Ssam flag = 0; break; 39712751Ssam } 39817593Skarels for (i = 0; i < nfd; i += NBI) { 39917593Skarels bits = ibits[which][i/NBI]; 40017593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 40117593Skarels bits &= ~(1 << j); 40217593Skarels fp = u.u_ofile[i + j]; 40317593Skarels if (fp == NULL) { 40417593Skarels u.u_error = EBADF; 40517593Skarels break; 40617593Skarels } 40717593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 40817593Skarels sbit(obits[which], i + j); 40917593Skarels n++; 41017593Skarels } 41112751Ssam } 41212751Ssam } 41312751Ssam } 41412751Ssam return (n); 41512751Ssam } 41612751Ssam 4177423Sroot /*ARGSUSED*/ 41812751Ssam seltrue(dev, flag) 41912751Ssam dev_t dev; 42012751Ssam int flag; 4217423Sroot { 4227423Sroot 42312751Ssam return (1); 4247423Sroot } 4258103Sroot 42612751Ssam selwakeup(p, coll) 42712751Ssam register struct proc *p; 42812751Ssam int coll; 4298103Sroot { 4308103Sroot 43112751Ssam if (coll) { 43212751Ssam nselcoll++; 43312751Ssam wakeup((caddr_t)&selwait); 43412751Ssam } 43512751Ssam if (p) { 43617934Skarels int s = splhigh(); 43717270Skarels if (p->p_wchan == (caddr_t)&selwait) { 43817270Skarels if (p->p_stat == SSLEEP) 43917270Skarels setrun(p); 44017270Skarels else 44117270Skarels unsleep(p); 44217270Skarels } else if (p->p_flag & SSEL) 44312751Ssam p->p_flag &= ~SSEL; 44412751Ssam splx(s); 44512751Ssam } 4468103Sroot } 447