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*34473Smckusick * @(#)sys_generic.c 7.7 (Berkeley) 05/24/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)) { 210*34473Smckusick memp = (caddr_t)malloc((u_long)IOCPARM_MAX, M_IOCTLOPS, 211*34473Smckusick M_WAITOK); 21231653Smckusick data = memp; 21330530Skarels } 21410601Ssam if (com&IOC_IN) { 21510601Ssam if (size) { 21610601Ssam u.u_error = 21730530Skarels copyin(uap->cmarg, data, (u_int)size); 21831653Smckusick if (u.u_error) { 21931653Smckusick if (memp) 22031653Smckusick free(memp, M_IOCTLOPS); 22110601Ssam return; 22231653Smckusick } 22310601Ssam } else 22410601Ssam *(caddr_t *)data = uap->cmarg; 22510601Ssam } else if ((com&IOC_OUT) && size) 22610601Ssam /* 22710601Ssam * Zero the buffer on the stack so the user 22810601Ssam * always gets back something deterministic. 22910601Ssam */ 23030530Skarels bzero(data, size); 23111284Ssam else if (com&IOC_VOID) 23211284Ssam *(caddr_t *)data = uap->cmarg; 2337423Sroot 23412751Ssam switch (com) { 2357624Ssam 23612751Ssam case FIONBIO: 23712751Ssam u.u_error = fset(fp, FNDELAY, *(int *)data); 23830530Skarels break; 23912751Ssam 24012751Ssam case FIOASYNC: 24112751Ssam u.u_error = fset(fp, FASYNC, *(int *)data); 24230530Skarels break; 24312751Ssam 24412751Ssam case FIOSETOWN: 24512751Ssam u.u_error = fsetown(fp, *(int *)data); 24630530Skarels break; 24712751Ssam 24812751Ssam case FIOGETOWN: 24912751Ssam u.u_error = fgetown(fp, (int *)data); 25030530Skarels break; 25130530Skarels default: 25230530Skarels if (setjmp(&u.u_qsave)) 25330530Skarels u.u_error = EINTR; 25430530Skarels else 25530530Skarels u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 25630530Skarels /* 25730530Skarels * Copy any data to user, size was 25830530Skarels * already set and checked above. 25930530Skarels */ 26030530Skarels if (u.u_error == 0 && (com&IOC_OUT) && size) 26130530Skarels u.u_error = copyout(data, uap->cmarg, (u_int)size); 26230530Skarels break; 2637423Sroot } 26431653Smckusick if (memp) 26531653Smckusick free(memp, M_IOCTLOPS); 2667423Sroot } 2677423Sroot 26812751Ssam int unselect(); 26912751Ssam int nselcoll; 27017593Skarels 2717423Sroot /* 27212751Ssam * Select system call. 2737423Sroot */ 27412751Ssam select() 27512751Ssam { 27612751Ssam register struct uap { 27712751Ssam int nd; 27823523Skarels fd_set *in, *ou, *ex; 27912751Ssam struct timeval *tv; 28012751Ssam } *uap = (struct uap *)u.u_ap; 28123523Skarels fd_set ibits[3], obits[3]; 28212751Ssam struct timeval atv; 28317593Skarels int s, ncoll, ni; 28412751Ssam label_t lqsave; 28512751Ssam 28626277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 28726277Skarels bzero((caddr_t)obits, sizeof(obits)); 28812751Ssam if (uap->nd > NOFILE) 28912751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 29023523Skarels ni = howmany(uap->nd, NFDBITS); 29112751Ssam 29212751Ssam #define getbits(name, x) \ 29312751Ssam if (uap->name) { \ 29423523Skarels u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 29526277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 29612751Ssam if (u.u_error) \ 29712751Ssam goto done; \ 29817593Skarels } 29912751Ssam getbits(in, 0); 30012751Ssam getbits(ou, 1); 30112751Ssam getbits(ex, 2); 30212751Ssam #undef getbits 30312751Ssam 30412751Ssam if (uap->tv) { 30512751Ssam u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 30612751Ssam sizeof (atv)); 30712751Ssam if (u.u_error) 30812751Ssam goto done; 30912751Ssam if (itimerfix(&atv)) { 31012751Ssam u.u_error = EINVAL; 31112751Ssam goto done; 31212751Ssam } 31317934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 31412751Ssam } 31512751Ssam retry: 31612751Ssam ncoll = nselcoll; 31712751Ssam u.u_procp->p_flag |= SSEL; 31817593Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 31912751Ssam if (u.u_error || u.u_r.r_val1) 32012751Ssam goto done; 32117934Skarels s = splhigh(); 32212971Ssam /* this should be timercmp(&time, &atv, >=) */ 32312971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 32412971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 32512751Ssam splx(s); 32612751Ssam goto done; 32712751Ssam } 32812751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 32912751Ssam splx(s); 33012751Ssam goto retry; 33112751Ssam } 33212751Ssam u.u_procp->p_flag &= ~SSEL; 33312751Ssam if (uap->tv) { 33412751Ssam lqsave = u.u_qsave; 33512751Ssam if (setjmp(&u.u_qsave)) { 33612751Ssam untimeout(unselect, (caddr_t)u.u_procp); 33712751Ssam u.u_error = EINTR; 33812751Ssam splx(s); 33912751Ssam goto done; 34012751Ssam } 34112751Ssam timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 34212751Ssam } 34312751Ssam sleep((caddr_t)&selwait, PZERO+1); 34412751Ssam if (uap->tv) { 34512751Ssam u.u_qsave = lqsave; 34612751Ssam untimeout(unselect, (caddr_t)u.u_procp); 34712751Ssam } 34812751Ssam splx(s); 34912751Ssam goto retry; 35012751Ssam done: 35133712Skarels u.u_procp->p_flag &= ~SSEL; 35212751Ssam #define putbits(name, x) \ 35312751Ssam if (uap->name) { \ 35423523Skarels int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 35526277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 35612751Ssam if (error) \ 35712751Ssam u.u_error = error; \ 35812751Ssam } 35926070Skarels if (u.u_error == 0) { 36021106Skarels putbits(in, 0); 36121106Skarels putbits(ou, 1); 36221106Skarels putbits(ex, 2); 36312751Ssam #undef putbits 36421106Skarels } 36512751Ssam } 36612751Ssam 36712751Ssam unselect(p) 36812751Ssam register struct proc *p; 36912751Ssam { 37017934Skarels register int s = splhigh(); 37112751Ssam 37212751Ssam switch (p->p_stat) { 37312751Ssam 37412751Ssam case SSLEEP: 37512751Ssam setrun(p); 37612751Ssam break; 37712751Ssam 37812751Ssam case SSTOP: 37912751Ssam unsleep(p); 38012751Ssam break; 38112751Ssam } 38212751Ssam splx(s); 38312751Ssam } 38412751Ssam 38517593Skarels selscan(ibits, obits, nfd) 38623523Skarels fd_set *ibits, *obits; 38712751Ssam { 38823523Skarels register int which, i, j; 38923523Skarels register fd_mask bits; 39012751Ssam int flag; 39112751Ssam struct file *fp; 39212751Ssam int n = 0; 39312751Ssam 39412751Ssam for (which = 0; which < 3; which++) { 39512751Ssam switch (which) { 39612751Ssam 39712751Ssam case 0: 39812751Ssam flag = FREAD; break; 39912751Ssam 40012751Ssam case 1: 40112751Ssam flag = FWRITE; break; 40212751Ssam 40312751Ssam case 2: 40412751Ssam flag = 0; break; 40512751Ssam } 40623523Skarels for (i = 0; i < nfd; i += NFDBITS) { 40723523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 40817593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 40917593Skarels bits &= ~(1 << j); 41017593Skarels fp = u.u_ofile[i + j]; 41117593Skarels if (fp == NULL) { 41217593Skarels u.u_error = EBADF; 41317593Skarels break; 41417593Skarels } 41517593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 41623523Skarels FD_SET(i + j, &obits[which]); 41717593Skarels n++; 41817593Skarels } 41912751Ssam } 42012751Ssam } 42112751Ssam } 42212751Ssam return (n); 42312751Ssam } 42412751Ssam 4257423Sroot /*ARGSUSED*/ 42612751Ssam seltrue(dev, flag) 42712751Ssam dev_t dev; 42812751Ssam int flag; 4297423Sroot { 4307423Sroot 43112751Ssam return (1); 4327423Sroot } 4338103Sroot 43412751Ssam selwakeup(p, coll) 43512751Ssam register struct proc *p; 43612751Ssam int coll; 4378103Sroot { 4388103Sroot 43912751Ssam if (coll) { 44012751Ssam nselcoll++; 44112751Ssam wakeup((caddr_t)&selwait); 44212751Ssam } 44312751Ssam if (p) { 44417934Skarels int s = splhigh(); 44517270Skarels if (p->p_wchan == (caddr_t)&selwait) { 44617270Skarels if (p->p_stat == SSLEEP) 44717270Skarels setrun(p); 44817270Skarels else 44917270Skarels unsleep(p); 45017270Skarels } else if (p->p_flag & SSEL) 45112751Ssam p->p_flag &= ~SSEL; 45212751Ssam splx(s); 45312751Ssam } 4548103Sroot } 455