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*33712Skarels * @(#)sys_generic.c 7.6 (Berkeley) 03/10/88 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" 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; 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; 1497423Sroot } 1507423Sroot 1517423Sroot /* 1527423Sroot * Ioctl system call 1537423Sroot */ 1547423Sroot ioctl() 1557423Sroot { 1567423Sroot register struct file *fp; 1577624Ssam struct a { 1587423Sroot int fdes; 1597423Sroot int cmd; 1607423Sroot caddr_t cmarg; 1617423Sroot } *uap; 1627820Sroot register int com; 1637820Sroot register u_int size; 16431653Smckusick caddr_t memp = 0; 16530530Skarels #define STK_PARAMS 128 16633480Skarels char stkbuf[STK_PARAMS]; 16733480Skarels caddr_t data = stkbuf; 1687423Sroot 1697423Sroot uap = (struct a *)u.u_ap; 17017004Smckusick GETF(fp, uap->fdes); 1717423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 1727423Sroot u.u_error = EBADF; 1737423Sroot return; 1747423Sroot } 1757624Ssam com = uap->cmd; 1767624Ssam 17713228Ssam #if defined(vax) && defined(COMPAT) 1787624Ssam /* 1797624Ssam * Map old style ioctl's into new for the 1807624Ssam * sake of backwards compatibility (sigh). 1817624Ssam */ 1827624Ssam if ((com&~0xffff) == 0) { 1837624Ssam com = mapioctl(com); 1847624Ssam if (com == 0) { 1857624Ssam u.u_error = EINVAL; 1867624Ssam return; 1877624Ssam } 1887624Ssam } 1897624Ssam #endif 1907624Ssam if (com == FIOCLEX) { 1919592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 1927423Sroot return; 1937423Sroot } 1947624Ssam if (com == FIONCLEX) { 1959592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 1967423Sroot return; 1977423Sroot } 1987624Ssam 1997624Ssam /* 2007624Ssam * Interpret high order word to find 2017624Ssam * amount of data to be copied to/from the 2027624Ssam * user's address space. 2037624Ssam */ 20430530Skarels size = IOCPARM_LEN(com); 20530530Skarels if (size > IOCPARM_MAX) { 2067624Ssam u.u_error = EFAULT; 2077423Sroot return; 2087423Sroot } 20933480Skarels if (size > sizeof (stkbuf)) { 21031653Smckusick memp = (caddr_t)malloc(IOCPARM_MAX, M_IOCTLOPS, M_WAITOK); 21131653Smckusick data = memp; 21230530Skarels } 21310601Ssam if (com&IOC_IN) { 21410601Ssam if (size) { 21510601Ssam u.u_error = 21630530Skarels copyin(uap->cmarg, data, (u_int)size); 21731653Smckusick if (u.u_error) { 21831653Smckusick if (memp) 21931653Smckusick free(memp, M_IOCTLOPS); 22010601Ssam return; 22131653Smckusick } 22210601Ssam } else 22310601Ssam *(caddr_t *)data = uap->cmarg; 22410601Ssam } else if ((com&IOC_OUT) && size) 22510601Ssam /* 22610601Ssam * Zero the buffer on the stack so the user 22710601Ssam * always gets back something deterministic. 22810601Ssam */ 22930530Skarels bzero(data, size); 23011284Ssam else if (com&IOC_VOID) 23111284Ssam *(caddr_t *)data = uap->cmarg; 2327423Sroot 23312751Ssam switch (com) { 2347624Ssam 23512751Ssam case FIONBIO: 23612751Ssam u.u_error = fset(fp, FNDELAY, *(int *)data); 23730530Skarels break; 23812751Ssam 23912751Ssam case FIOASYNC: 24012751Ssam u.u_error = fset(fp, FASYNC, *(int *)data); 24130530Skarels break; 24212751Ssam 24312751Ssam case FIOSETOWN: 24412751Ssam u.u_error = fsetown(fp, *(int *)data); 24530530Skarels break; 24612751Ssam 24712751Ssam case FIOGETOWN: 24812751Ssam u.u_error = fgetown(fp, (int *)data); 24930530Skarels break; 25030530Skarels default: 25130530Skarels if (setjmp(&u.u_qsave)) 25230530Skarels u.u_error = EINTR; 25330530Skarels else 25430530Skarels u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 25530530Skarels /* 25630530Skarels * Copy any data to user, size was 25730530Skarels * already set and checked above. 25830530Skarels */ 25930530Skarels if (u.u_error == 0 && (com&IOC_OUT) && size) 26030530Skarels u.u_error = copyout(data, uap->cmarg, (u_int)size); 26130530Skarels break; 2627423Sroot } 26331653Smckusick if (memp) 26431653Smckusick free(memp, M_IOCTLOPS); 2657423Sroot } 2667423Sroot 26712751Ssam int unselect(); 26812751Ssam int nselcoll; 26917593Skarels 2707423Sroot /* 27112751Ssam * Select system call. 2727423Sroot */ 27312751Ssam select() 27412751Ssam { 27512751Ssam register struct uap { 27612751Ssam int nd; 27723523Skarels fd_set *in, *ou, *ex; 27812751Ssam struct timeval *tv; 27912751Ssam } *uap = (struct uap *)u.u_ap; 28023523Skarels fd_set ibits[3], obits[3]; 28112751Ssam struct timeval atv; 28217593Skarels int s, ncoll, ni; 28312751Ssam label_t lqsave; 28412751Ssam 28526277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 28626277Skarels bzero((caddr_t)obits, sizeof(obits)); 28712751Ssam if (uap->nd > NOFILE) 28812751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 28923523Skarels ni = howmany(uap->nd, NFDBITS); 29012751Ssam 29112751Ssam #define getbits(name, x) \ 29212751Ssam if (uap->name) { \ 29323523Skarels u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 29426277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 29512751Ssam if (u.u_error) \ 29612751Ssam goto done; \ 29717593Skarels } 29812751Ssam getbits(in, 0); 29912751Ssam getbits(ou, 1); 30012751Ssam getbits(ex, 2); 30112751Ssam #undef getbits 30212751Ssam 30312751Ssam if (uap->tv) { 30412751Ssam u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 30512751Ssam sizeof (atv)); 30612751Ssam if (u.u_error) 30712751Ssam goto done; 30812751Ssam if (itimerfix(&atv)) { 30912751Ssam u.u_error = EINVAL; 31012751Ssam goto done; 31112751Ssam } 31217934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 31312751Ssam } 31412751Ssam retry: 31512751Ssam ncoll = nselcoll; 31612751Ssam u.u_procp->p_flag |= SSEL; 31717593Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 31812751Ssam if (u.u_error || u.u_r.r_val1) 31912751Ssam goto done; 32017934Skarels s = splhigh(); 32112971Ssam /* this should be timercmp(&time, &atv, >=) */ 32212971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 32312971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 32412751Ssam splx(s); 32512751Ssam goto done; 32612751Ssam } 32712751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 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: 350*33712Skarels u.u_procp->p_flag &= ~SSEL; 35112751Ssam #define putbits(name, x) \ 35212751Ssam if (uap->name) { \ 35323523Skarels int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 35426277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 35512751Ssam if (error) \ 35612751Ssam u.u_error = error; \ 35712751Ssam } 35826070Skarels if (u.u_error == 0) { 35921106Skarels putbits(in, 0); 36021106Skarels putbits(ou, 1); 36121106Skarels putbits(ex, 2); 36212751Ssam #undef putbits 36321106Skarels } 36412751Ssam } 36512751Ssam 36612751Ssam unselect(p) 36712751Ssam register struct proc *p; 36812751Ssam { 36917934Skarels register int s = splhigh(); 37012751Ssam 37112751Ssam switch (p->p_stat) { 37212751Ssam 37312751Ssam case SSLEEP: 37412751Ssam setrun(p); 37512751Ssam break; 37612751Ssam 37712751Ssam case SSTOP: 37812751Ssam unsleep(p); 37912751Ssam break; 38012751Ssam } 38112751Ssam splx(s); 38212751Ssam } 38312751Ssam 38417593Skarels selscan(ibits, obits, nfd) 38523523Skarels fd_set *ibits, *obits; 38612751Ssam { 38723523Skarels register int which, i, j; 38823523Skarels register fd_mask bits; 38912751Ssam int flag; 39012751Ssam struct file *fp; 39112751Ssam int n = 0; 39212751Ssam 39312751Ssam for (which = 0; which < 3; which++) { 39412751Ssam switch (which) { 39512751Ssam 39612751Ssam case 0: 39712751Ssam flag = FREAD; break; 39812751Ssam 39912751Ssam case 1: 40012751Ssam flag = FWRITE; break; 40112751Ssam 40212751Ssam case 2: 40312751Ssam flag = 0; break; 40412751Ssam } 40523523Skarels for (i = 0; i < nfd; i += NFDBITS) { 40623523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 40717593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 40817593Skarels bits &= ~(1 << j); 40917593Skarels fp = u.u_ofile[i + j]; 41017593Skarels if (fp == NULL) { 41117593Skarels u.u_error = EBADF; 41217593Skarels break; 41317593Skarels } 41417593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 41523523Skarels FD_SET(i + j, &obits[which]); 41617593Skarels n++; 41717593Skarels } 41812751Ssam } 41912751Ssam } 42012751Ssam } 42112751Ssam return (n); 42212751Ssam } 42312751Ssam 4247423Sroot /*ARGSUSED*/ 42512751Ssam seltrue(dev, flag) 42612751Ssam dev_t dev; 42712751Ssam int flag; 4287423Sroot { 4297423Sroot 43012751Ssam return (1); 4317423Sroot } 4328103Sroot 43312751Ssam selwakeup(p, coll) 43412751Ssam register struct proc *p; 43512751Ssam int coll; 4368103Sroot { 4378103Sroot 43812751Ssam if (coll) { 43912751Ssam nselcoll++; 44012751Ssam wakeup((caddr_t)&selwait); 44112751Ssam } 44212751Ssam if (p) { 44317934Skarels int s = splhigh(); 44417270Skarels if (p->p_wchan == (caddr_t)&selwait) { 44517270Skarels if (p->p_stat == SSLEEP) 44617270Skarels setrun(p); 44717270Skarels else 44817270Skarels unsleep(p); 44917270Skarels } else if (p->p_flag & SSEL) 45012751Ssam p->p_flag &= ~SSEL; 45112751Ssam splx(s); 45212751Ssam } 4538103Sroot } 454