123384Smckusick /* 229104Smckusick * Copyright (c) 1982, 1986 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*30530Skarels * @(#)sys_generic.c 7.2 (Berkeley) 02/19/87 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" 19*30530Skarels #include "buf.h" /* XXX */ 207423Sroot 217423Sroot /* 227423Sroot * Read system call. 237423Sroot */ 247423Sroot read() 257423Sroot { 267423Sroot register struct a { 277423Sroot int fdes; 287423Sroot char *cbuf; 297423Sroot unsigned count; 307820Sroot } *uap = (struct a *)u.u_ap; 317746Sroot struct uio auio; 327746Sroot struct iovec aiov; 337423Sroot 347820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 357820Sroot aiov.iov_len = uap->count; 367820Sroot auio.uio_iov = &aiov; 377820Sroot auio.uio_iovcnt = 1; 387820Sroot rwuio(&auio, UIO_READ); 397820Sroot } 407820Sroot 417820Sroot readv() 427820Sroot { 437820Sroot register struct a { 447820Sroot int fdes; 457820Sroot struct iovec *iovp; 4626474Skarels unsigned iovcnt; 477820Sroot } *uap = (struct a *)u.u_ap; 487820Sroot struct uio auio; 497820Sroot struct iovec aiov[16]; /* XXX */ 507820Sroot 5126474Skarels if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 527423Sroot u.u_error = EINVAL; 537423Sroot return; 547423Sroot } 557820Sroot auio.uio_iov = aiov; 567820Sroot auio.uio_iovcnt = uap->iovcnt; 579999Ssam u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 5826474Skarels uap->iovcnt * sizeof (struct iovec)); 599999Ssam if (u.u_error) 607423Sroot return; 617820Sroot rwuio(&auio, UIO_READ); 627423Sroot } 637423Sroot 647423Sroot /* 657423Sroot * Write system call 667423Sroot */ 677423Sroot write() 687423Sroot { 697423Sroot register struct a { 707423Sroot int fdes; 717423Sroot char *cbuf; 7226474Skarels unsigned count; 737820Sroot } *uap = (struct a *)u.u_ap; 747820Sroot struct uio auio; 757820Sroot struct iovec aiov; 767423Sroot 777820Sroot auio.uio_iov = &aiov; 787820Sroot auio.uio_iovcnt = 1; 797820Sroot aiov.iov_base = uap->cbuf; 807820Sroot aiov.iov_len = uap->count; 817820Sroot rwuio(&auio, UIO_WRITE); 827820Sroot } 837820Sroot 847820Sroot writev() 857820Sroot { 867820Sroot register struct a { 877820Sroot int fdes; 887820Sroot struct iovec *iovp; 8926474Skarels unsigned iovcnt; 907820Sroot } *uap = (struct a *)u.u_ap; 917820Sroot struct uio auio; 927820Sroot struct iovec aiov[16]; /* XXX */ 937820Sroot 9426474Skarels if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 957423Sroot u.u_error = EINVAL; 967423Sroot return; 977423Sroot } 987820Sroot auio.uio_iov = aiov; 997820Sroot auio.uio_iovcnt = uap->iovcnt; 1009999Ssam u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 10126474Skarels uap->iovcnt * sizeof (struct iovec)); 1029999Ssam if (u.u_error) 1037820Sroot return; 1047820Sroot rwuio(&auio, UIO_WRITE); 1057820Sroot } 1067820Sroot 1077820Sroot rwuio(uio, rw) 1087820Sroot register struct uio *uio; 1097820Sroot enum uio_rw rw; 1107820Sroot { 1117820Sroot struct a { 1127820Sroot int fdes; 1137820Sroot }; 1147820Sroot register struct file *fp; 1157820Sroot register struct iovec *iov; 1167820Sroot int i, count; 1177820Sroot 1187820Sroot GETF(fp, ((struct a *)u.u_ap)->fdes); 1197820Sroot if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) { 1207423Sroot u.u_error = EBADF; 1217423Sroot return; 1227423Sroot } 1237820Sroot uio->uio_resid = 0; 12416702Smckusick uio->uio_segflg = UIO_USERSPACE; 1257820Sroot iov = uio->uio_iov; 1267820Sroot for (i = 0; i < uio->uio_iovcnt; i++) { 1277820Sroot if (iov->iov_len < 0) { 1287820Sroot u.u_error = EINVAL; 1297820Sroot return; 1307820Sroot } 1317820Sroot uio->uio_resid += iov->iov_len; 1327820Sroot if (uio->uio_resid < 0) { 1337820Sroot u.u_error = EINVAL; 1347820Sroot return; 1357820Sroot } 13613270Ssam iov++; 1377820Sroot } 1387820Sroot count = uio->uio_resid; 13912751Ssam uio->uio_offset = fp->f_offset; 14018309Smckusick if (setjmp(&u.u_qsave)) { 14118309Smckusick if (uio->uio_resid == count) { 14221009Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 14318309Smckusick u.u_error = EINTR; 14418309Smckusick else 14518309Smckusick u.u_eosys = RESTARTSYS; 14618309Smckusick } 14712751Ssam } else 14812751Ssam u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 1497820Sroot u.u_r.r_val1 = count - uio->uio_resid; 15012751Ssam fp->f_offset += u.u_r.r_val1; 1517423Sroot } 1527423Sroot 1537423Sroot /* 1547423Sroot * Ioctl system call 1557423Sroot */ 1567423Sroot ioctl() 1577423Sroot { 1587423Sroot register struct file *fp; 1597624Ssam struct a { 1607423Sroot int fdes; 1617423Sroot int cmd; 1627423Sroot caddr_t cmarg; 1637423Sroot } *uap; 1647820Sroot register int com; 1657820Sroot register u_int size; 166*30530Skarels struct buf *bp = 0; 167*30530Skarels #define STK_PARAMS 128 168*30530Skarels char buf[STK_PARAMS]; 169*30530Skarels caddr_t data = buf; 1707423Sroot 1717423Sroot uap = (struct a *)u.u_ap; 17217004Smckusick GETF(fp, uap->fdes); 1737423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 1747423Sroot u.u_error = EBADF; 1757423Sroot return; 1767423Sroot } 1777624Ssam com = uap->cmd; 1787624Ssam 17913228Ssam #if defined(vax) && defined(COMPAT) 1807624Ssam /* 1817624Ssam * Map old style ioctl's into new for the 1827624Ssam * sake of backwards compatibility (sigh). 1837624Ssam */ 1847624Ssam if ((com&~0xffff) == 0) { 1857624Ssam com = mapioctl(com); 1867624Ssam if (com == 0) { 1877624Ssam u.u_error = EINVAL; 1887624Ssam return; 1897624Ssam } 1907624Ssam } 1917624Ssam #endif 1927624Ssam if (com == FIOCLEX) { 1939592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 1947423Sroot return; 1957423Sroot } 1967624Ssam if (com == FIONCLEX) { 1979592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 1987423Sroot return; 1997423Sroot } 2007624Ssam 2017624Ssam /* 2027624Ssam * Interpret high order word to find 2037624Ssam * amount of data to be copied to/from the 2047624Ssam * user's address space. 2057624Ssam */ 206*30530Skarels size = IOCPARM_LEN(com); 207*30530Skarels if (size > IOCPARM_MAX) { 2087624Ssam u.u_error = EFAULT; 2097423Sroot return; 2107423Sroot } 211*30530Skarels if (size > sizeof (buf)) { 212*30530Skarels bp = geteblk(IOCPARM_MAX); /* XXX */ 213*30530Skarels data = bp->b_un.b_addr; 214*30530Skarels } 21510601Ssam if (com&IOC_IN) { 21610601Ssam if (size) { 21710601Ssam u.u_error = 218*30530Skarels copyin(uap->cmarg, data, (u_int)size); 21910601Ssam if (u.u_error) 22010601Ssam return; 22110601Ssam } else 22210601Ssam *(caddr_t *)data = uap->cmarg; 22310601Ssam } else if ((com&IOC_OUT) && size) 22410601Ssam /* 22510601Ssam * Zero the buffer on the stack so the user 22610601Ssam * always gets back something deterministic. 22710601Ssam */ 228*30530Skarels bzero(data, size); 22911284Ssam else if (com&IOC_VOID) 23011284Ssam *(caddr_t *)data = uap->cmarg; 2317423Sroot 23212751Ssam switch (com) { 2337624Ssam 23412751Ssam case FIONBIO: 23512751Ssam u.u_error = fset(fp, FNDELAY, *(int *)data); 236*30530Skarels break; 23712751Ssam 23812751Ssam case FIOASYNC: 23912751Ssam u.u_error = fset(fp, FASYNC, *(int *)data); 240*30530Skarels break; 24112751Ssam 24212751Ssam case FIOSETOWN: 24312751Ssam u.u_error = fsetown(fp, *(int *)data); 244*30530Skarels break; 24512751Ssam 24612751Ssam case FIOGETOWN: 24712751Ssam u.u_error = fgetown(fp, (int *)data); 248*30530Skarels break; 249*30530Skarels default: 250*30530Skarels if (setjmp(&u.u_qsave)) 251*30530Skarels u.u_error = EINTR; 252*30530Skarels else 253*30530Skarels u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 254*30530Skarels /* 255*30530Skarels * Copy any data to user, size was 256*30530Skarels * already set and checked above. 257*30530Skarels */ 258*30530Skarels if (u.u_error == 0 && (com&IOC_OUT) && size) 259*30530Skarels u.u_error = copyout(data, uap->cmarg, (u_int)size); 260*30530Skarels break; 2617423Sroot } 262*30530Skarels if (bp) 263*30530Skarels brelse(bp); 2647423Sroot } 2657423Sroot 26612751Ssam int unselect(); 26712751Ssam int nselcoll; 26817593Skarels 2697423Sroot /* 27012751Ssam * Select system call. 2717423Sroot */ 27212751Ssam select() 27312751Ssam { 27412751Ssam register struct uap { 27512751Ssam int nd; 27623523Skarels fd_set *in, *ou, *ex; 27712751Ssam struct timeval *tv; 27812751Ssam } *uap = (struct uap *)u.u_ap; 27923523Skarels fd_set ibits[3], obits[3]; 28012751Ssam struct timeval atv; 28117593Skarels int s, ncoll, ni; 28212751Ssam label_t lqsave; 28312751Ssam 28426277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 28526277Skarels bzero((caddr_t)obits, sizeof(obits)); 28612751Ssam if (uap->nd > NOFILE) 28712751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 28823523Skarels ni = howmany(uap->nd, NFDBITS); 28912751Ssam 29012751Ssam #define getbits(name, x) \ 29112751Ssam if (uap->name) { \ 29223523Skarels u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 29326277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 29412751Ssam if (u.u_error) \ 29512751Ssam goto done; \ 29617593Skarels } 29712751Ssam getbits(in, 0); 29812751Ssam getbits(ou, 1); 29912751Ssam getbits(ex, 2); 30012751Ssam #undef getbits 30112751Ssam 30212751Ssam if (uap->tv) { 30312751Ssam u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 30412751Ssam sizeof (atv)); 30512751Ssam if (u.u_error) 30612751Ssam goto done; 30712751Ssam if (itimerfix(&atv)) { 30812751Ssam u.u_error = EINVAL; 30912751Ssam goto done; 31012751Ssam } 31117934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 31212751Ssam } 31312751Ssam retry: 31412751Ssam ncoll = nselcoll; 31512751Ssam u.u_procp->p_flag |= SSEL; 31617593Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 31712751Ssam if (u.u_error || u.u_r.r_val1) 31812751Ssam goto done; 31917934Skarels s = splhigh(); 32012971Ssam /* this should be timercmp(&time, &atv, >=) */ 32112971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 32212971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 32312751Ssam splx(s); 32412751Ssam goto done; 32512751Ssam } 32612751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 32712751Ssam u.u_procp->p_flag &= ~SSEL; 32812751Ssam splx(s); 32912751Ssam goto retry; 33012751Ssam } 33112751Ssam u.u_procp->p_flag &= ~SSEL; 33212751Ssam if (uap->tv) { 33312751Ssam lqsave = u.u_qsave; 33412751Ssam if (setjmp(&u.u_qsave)) { 33512751Ssam untimeout(unselect, (caddr_t)u.u_procp); 33612751Ssam u.u_error = EINTR; 33712751Ssam splx(s); 33812751Ssam goto done; 33912751Ssam } 34012751Ssam timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 34112751Ssam } 34212751Ssam sleep((caddr_t)&selwait, PZERO+1); 34312751Ssam if (uap->tv) { 34412751Ssam u.u_qsave = lqsave; 34512751Ssam untimeout(unselect, (caddr_t)u.u_procp); 34612751Ssam } 34712751Ssam splx(s); 34812751Ssam goto retry; 34912751Ssam done: 35012751Ssam #define putbits(name, x) \ 35112751Ssam if (uap->name) { \ 35223523Skarels int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 35326277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 35412751Ssam if (error) \ 35512751Ssam u.u_error = error; \ 35612751Ssam } 35726070Skarels if (u.u_error == 0) { 35821106Skarels putbits(in, 0); 35921106Skarels putbits(ou, 1); 36021106Skarels putbits(ex, 2); 36112751Ssam #undef putbits 36221106Skarels } 36312751Ssam } 36412751Ssam 36512751Ssam unselect(p) 36612751Ssam register struct proc *p; 36712751Ssam { 36817934Skarels register int s = splhigh(); 36912751Ssam 37012751Ssam switch (p->p_stat) { 37112751Ssam 37212751Ssam case SSLEEP: 37312751Ssam setrun(p); 37412751Ssam break; 37512751Ssam 37612751Ssam case SSTOP: 37712751Ssam unsleep(p); 37812751Ssam break; 37912751Ssam } 38012751Ssam splx(s); 38112751Ssam } 38212751Ssam 38317593Skarels selscan(ibits, obits, nfd) 38423523Skarels fd_set *ibits, *obits; 38512751Ssam { 38623523Skarels register int which, i, j; 38723523Skarels register fd_mask bits; 38812751Ssam int flag; 38912751Ssam struct file *fp; 39012751Ssam int n = 0; 39112751Ssam 39212751Ssam for (which = 0; which < 3; which++) { 39312751Ssam switch (which) { 39412751Ssam 39512751Ssam case 0: 39612751Ssam flag = FREAD; break; 39712751Ssam 39812751Ssam case 1: 39912751Ssam flag = FWRITE; break; 40012751Ssam 40112751Ssam case 2: 40212751Ssam flag = 0; break; 40312751Ssam } 40423523Skarels for (i = 0; i < nfd; i += NFDBITS) { 40523523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 40617593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 40717593Skarels bits &= ~(1 << j); 40817593Skarels fp = u.u_ofile[i + j]; 40917593Skarels if (fp == NULL) { 41017593Skarels u.u_error = EBADF; 41117593Skarels break; 41217593Skarels } 41317593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 41423523Skarels FD_SET(i + j, &obits[which]); 41517593Skarels n++; 41617593Skarels } 41712751Ssam } 41812751Ssam } 41912751Ssam } 42012751Ssam return (n); 42112751Ssam } 42212751Ssam 4237423Sroot /*ARGSUSED*/ 42412751Ssam seltrue(dev, flag) 42512751Ssam dev_t dev; 42612751Ssam int flag; 4277423Sroot { 4287423Sroot 42912751Ssam return (1); 4307423Sroot } 4318103Sroot 43212751Ssam selwakeup(p, coll) 43312751Ssam register struct proc *p; 43412751Ssam int coll; 4358103Sroot { 4368103Sroot 43712751Ssam if (coll) { 43812751Ssam nselcoll++; 43912751Ssam wakeup((caddr_t)&selwait); 44012751Ssam } 44112751Ssam if (p) { 44217934Skarels int s = splhigh(); 44317270Skarels if (p->p_wchan == (caddr_t)&selwait) { 44417270Skarels if (p->p_stat == SSLEEP) 44517270Skarels setrun(p); 44617270Skarels else 44717270Skarels unsleep(p); 44817270Skarels } else if (p->p_flag & SSEL) 44912751Ssam p->p_flag &= ~SSEL; 45012751Ssam splx(s); 45112751Ssam } 4528103Sroot } 453