1*13270Ssam /* sys_generic.c 5.42 83/06/24 */ 27423Sroot 37423Sroot #include "../h/param.h" 47423Sroot #include "../h/systm.h" 57423Sroot #include "../h/dir.h" 67423Sroot #include "../h/user.h" 79560Ssam #include "../h/ioctl.h" 87423Sroot #include "../h/file.h" 97423Sroot #include "../h/proc.h" 107714Sroot #include "../h/uio.h" 1112751Ssam #include "../h/kernel.h" 1212751Ssam #include "../h/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; 1177820Sroot uio->uio_segflg = 0; 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 } 129*13270Ssam iov++; 1307820Sroot } 1317820Sroot count = uio->uio_resid; 13212751Ssam uio->uio_offset = fp->f_offset; 13312883Ssam if ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) { 1347820Sroot if (uio->uio_resid == count) 1357423Sroot u.u_eosys = RESTARTSYS; 13612751Ssam } else 13712751Ssam u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 1387820Sroot u.u_r.r_val1 = count - uio->uio_resid; 13912751Ssam fp->f_offset += u.u_r.r_val1; 1407423Sroot } 1417423Sroot 1427423Sroot /* 1437423Sroot * Ioctl system call 1447423Sroot */ 1457423Sroot ioctl() 1467423Sroot { 1477423Sroot register struct file *fp; 1487624Ssam struct a { 1497423Sroot int fdes; 1507423Sroot int cmd; 1517423Sroot caddr_t cmarg; 1527423Sroot } *uap; 1537820Sroot register int com; 1547820Sroot register u_int size; 1557624Ssam char data[IOCPARM_MASK+1]; 1567423Sroot 1577423Sroot uap = (struct a *)u.u_ap; 1587423Sroot if ((fp = getf(uap->fdes)) == NULL) 1597423Sroot return; 1607423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 1617423Sroot u.u_error = EBADF; 1627423Sroot return; 1637423Sroot } 1647624Ssam com = uap->cmd; 1657624Ssam 16613228Ssam #if defined(vax) && defined(COMPAT) 1677624Ssam /* 1687624Ssam * Map old style ioctl's into new for the 1697624Ssam * sake of backwards compatibility (sigh). 1707624Ssam */ 1717624Ssam if ((com&~0xffff) == 0) { 1727624Ssam com = mapioctl(com); 1737624Ssam if (com == 0) { 1747624Ssam u.u_error = EINVAL; 1757624Ssam return; 1767624Ssam } 1777624Ssam } 1787624Ssam #endif 1797624Ssam if (com == FIOCLEX) { 1809592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 1817423Sroot return; 1827423Sroot } 1837624Ssam if (com == FIONCLEX) { 1849592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 1857423Sroot return; 1867423Sroot } 1877624Ssam 1887624Ssam /* 1897624Ssam * Interpret high order word to find 1907624Ssam * amount of data to be copied to/from the 1917624Ssam * user's address space. 1927624Ssam */ 1937624Ssam size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 1947624Ssam if (size > sizeof (data)) { 1957624Ssam u.u_error = EFAULT; 1967423Sroot return; 1977423Sroot } 19810601Ssam if (com&IOC_IN) { 19910601Ssam if (size) { 20010601Ssam u.u_error = 20110601Ssam copyin(uap->cmarg, (caddr_t)data, (u_int)size); 20210601Ssam if (u.u_error) 20310601Ssam return; 20410601Ssam } else 20510601Ssam *(caddr_t *)data = uap->cmarg; 20610601Ssam } else if ((com&IOC_OUT) && size) 20710601Ssam /* 20810601Ssam * Zero the buffer on the stack so the user 20910601Ssam * always gets back something deterministic. 21010601Ssam */ 2117624Ssam bzero((caddr_t)data, size); 21211284Ssam else if (com&IOC_VOID) 21311284Ssam *(caddr_t *)data = uap->cmarg; 2147423Sroot 21512751Ssam switch (com) { 2167624Ssam 21712751Ssam case FIONBIO: 21812751Ssam u.u_error = fset(fp, FNDELAY, *(int *)data); 21912751Ssam return; 22012751Ssam 22112751Ssam case FIOASYNC: 22212751Ssam u.u_error = fset(fp, FASYNC, *(int *)data); 22312751Ssam return; 22412751Ssam 22512751Ssam case FIOSETOWN: 22612751Ssam u.u_error = fsetown(fp, *(int *)data); 22712751Ssam return; 22812751Ssam 22912751Ssam case FIOGETOWN: 23012751Ssam u.u_error = fgetown(fp, (int *)data); 23112751Ssam return; 2327423Sroot } 23312751Ssam u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 2347624Ssam /* 2357624Ssam * Copy any data to user, size was 2367624Ssam * already set and checked above. 2377624Ssam */ 2389999Ssam if (u.u_error == 0 && (com&IOC_OUT) && size) 2399999Ssam u.u_error = copyout(data, uap->cmarg, (u_int)size); 2407423Sroot } 2417423Sroot 24212751Ssam int unselect(); 24312751Ssam int nselcoll; 2447423Sroot /* 24512751Ssam * Select system call. 2467423Sroot */ 24712751Ssam select() 24812751Ssam { 24912751Ssam register struct uap { 25012751Ssam int nd; 25112751Ssam long *in, *ou, *ex; 25212751Ssam struct timeval *tv; 25312751Ssam } *uap = (struct uap *)u.u_ap; 25412751Ssam int ibits[3], obits[3]; 25512751Ssam struct timeval atv; 25613041Ssam int s, ncoll, mask; 25712751Ssam label_t lqsave; 25812751Ssam 25912751Ssam obits[0] = obits[1] = obits[2] = 0; 26012751Ssam if (uap->nd > NOFILE) 26112751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 26213041Ssam mask = (1 << uap->nd) - 1; 26312751Ssam 26412751Ssam #define getbits(name, x) \ 26512751Ssam if (uap->name) { \ 26612751Ssam u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 26712751Ssam sizeof (ibits[x])); \ 26812751Ssam if (u.u_error) \ 26912751Ssam goto done; \ 27013041Ssam ibits[x] &= mask; \ 27112751Ssam } else \ 27212751Ssam ibits[x] = 0; 27312751Ssam getbits(in, 0); 27412751Ssam getbits(ou, 1); 27512751Ssam getbits(ex, 2); 27612751Ssam #undef getbits 27712751Ssam 27812751Ssam if (uap->tv) { 27912751Ssam u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 28012751Ssam sizeof (atv)); 28112751Ssam if (u.u_error) 28212751Ssam goto done; 28312751Ssam if (itimerfix(&atv)) { 28412751Ssam u.u_error = EINVAL; 28512751Ssam goto done; 28612751Ssam } 28712751Ssam s = spl7(); timevaladd(&atv, &time); splx(s); 28812751Ssam } 28912751Ssam retry: 29012751Ssam ncoll = nselcoll; 29112751Ssam u.u_procp->p_flag |= SSEL; 29212751Ssam u.u_r.r_val1 = selscan(ibits, obits); 29312751Ssam if (u.u_error || u.u_r.r_val1) 29412751Ssam goto done; 29512751Ssam s = spl6(); 29612971Ssam /* this should be timercmp(&time, &atv, >=) */ 29712971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 29812971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 29912751Ssam splx(s); 30012751Ssam goto done; 30112751Ssam } 30212751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 30312751Ssam u.u_procp->p_flag &= ~SSEL; 30412751Ssam splx(s); 30512751Ssam goto retry; 30612751Ssam } 30712751Ssam u.u_procp->p_flag &= ~SSEL; 30812751Ssam if (uap->tv) { 30912751Ssam lqsave = u.u_qsave; 31012751Ssam if (setjmp(&u.u_qsave)) { 31112751Ssam untimeout(unselect, (caddr_t)u.u_procp); 31212751Ssam u.u_error = EINTR; 31312751Ssam splx(s); 31412751Ssam goto done; 31512751Ssam } 31612751Ssam timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 31712751Ssam } 31812751Ssam sleep((caddr_t)&selwait, PZERO+1); 31912751Ssam if (uap->tv) { 32012751Ssam u.u_qsave = lqsave; 32112751Ssam untimeout(unselect, (caddr_t)u.u_procp); 32212751Ssam } 32312751Ssam splx(s); 32412751Ssam goto retry; 32512751Ssam done: 32612751Ssam #define putbits(name, x) \ 32712751Ssam if (uap->name) { \ 32812751Ssam int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 32912751Ssam sizeof (obits[x])); \ 33012751Ssam if (error) \ 33112751Ssam u.u_error = error; \ 33212751Ssam } 33312751Ssam putbits(in, 0); 33412751Ssam putbits(ou, 1); 33512751Ssam putbits(ex, 2); 33612751Ssam #undef putbits 33712751Ssam } 33812751Ssam 33912751Ssam unselect(p) 34012751Ssam register struct proc *p; 34112751Ssam { 34212751Ssam register int s = spl6(); 34312751Ssam 34412751Ssam switch (p->p_stat) { 34512751Ssam 34612751Ssam case SSLEEP: 34712751Ssam setrun(p); 34812751Ssam break; 34912751Ssam 35012751Ssam case SSTOP: 35112751Ssam unsleep(p); 35212751Ssam break; 35312751Ssam } 35412751Ssam splx(s); 35512751Ssam } 35612751Ssam 35712751Ssam selscan(ibits, obits) 35812751Ssam int *ibits, *obits; 35912751Ssam { 36012751Ssam register int which, bits, i; 36112751Ssam int flag; 36212751Ssam struct file *fp; 36312751Ssam int n = 0; 36412751Ssam 36512751Ssam for (which = 0; which < 3; which++) { 36612751Ssam bits = ibits[which]; 36712751Ssam obits[which] = 0; 36812751Ssam switch (which) { 36912751Ssam 37012751Ssam case 0: 37112751Ssam flag = FREAD; break; 37212751Ssam 37312751Ssam case 1: 37412751Ssam flag = FWRITE; break; 37512751Ssam 37612751Ssam case 2: 37712751Ssam flag = 0; break; 37812751Ssam } 37912751Ssam while (i = ffs(bits)) { 38012751Ssam bits &= ~(1<<(i-1)); 38112751Ssam fp = u.u_ofile[i-1]; 38212751Ssam if (fp == NULL) { 38312751Ssam u.u_error = EBADF; 38412751Ssam break; 38512751Ssam } 38612751Ssam if ((*fp->f_ops->fo_select)(fp, flag)) { 38712751Ssam obits[which] |= (1<<(i-1)); 38812751Ssam n++; 38912751Ssam } 39012751Ssam } 39112751Ssam } 39212751Ssam return (n); 39312751Ssam } 39412751Ssam 3957423Sroot /*ARGSUSED*/ 39612751Ssam seltrue(dev, flag) 39712751Ssam dev_t dev; 39812751Ssam int flag; 3997423Sroot { 4007423Sroot 40112751Ssam return (1); 4027423Sroot } 4038103Sroot 40412751Ssam selwakeup(p, coll) 40512751Ssam register struct proc *p; 40612751Ssam int coll; 4078103Sroot { 4088103Sroot 40912751Ssam if (coll) { 41012751Ssam nselcoll++; 41112751Ssam wakeup((caddr_t)&selwait); 41212751Ssam } 41312751Ssam if (p) { 41412751Ssam int s = spl6(); 41512751Ssam if (p->p_wchan == (caddr_t)&selwait) 41612751Ssam setrun(p); 41712751Ssam else if (p->p_flag & SSEL) 41812751Ssam p->p_flag &= ~SSEL; 41912751Ssam splx(s); 42012751Ssam } 4218103Sroot } 422