1*12751Ssam /* sys_generic.c 5.36 83/05/27 */ 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" 11*12751Ssam #include "../h/kernel.h" 12*12751Ssam #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 } 1297820Sroot } 1307820Sroot count = uio->uio_resid; 131*12751Ssam uio->uio_offset = fp->f_offset; 1328118Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { 1337820Sroot if (uio->uio_resid == count) 1347423Sroot u.u_eosys = RESTARTSYS; 135*12751Ssam } else 136*12751Ssam u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 1377820Sroot u.u_r.r_val1 = count - uio->uio_resid; 138*12751Ssam fp->f_offset += u.u_r.r_val1; 1397423Sroot } 1407423Sroot 1417423Sroot /* 1427423Sroot * Ioctl system call 1437423Sroot */ 1447423Sroot ioctl() 1457423Sroot { 1467423Sroot register struct file *fp; 1477624Ssam struct a { 1487423Sroot int fdes; 1497423Sroot int cmd; 1507423Sroot caddr_t cmarg; 1517423Sroot } *uap; 1527820Sroot register int com; 1537820Sroot register u_int size; 1547624Ssam char data[IOCPARM_MASK+1]; 1557423Sroot 1567423Sroot uap = (struct a *)u.u_ap; 1577423Sroot if ((fp = getf(uap->fdes)) == NULL) 1587423Sroot return; 1597423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 1607423Sroot u.u_error = EBADF; 1617423Sroot return; 1627423Sroot } 1637624Ssam com = uap->cmd; 1647624Ssam 165*12751Ssam #if defined(vax) && !defined(NOCOMPAT) 1667624Ssam /* 1677624Ssam * Map old style ioctl's into new for the 1687624Ssam * sake of backwards compatibility (sigh). 1697624Ssam */ 1707624Ssam if ((com&~0xffff) == 0) { 1717624Ssam com = mapioctl(com); 1727624Ssam if (com == 0) { 1737624Ssam u.u_error = EINVAL; 1747624Ssam return; 1757624Ssam } 1767624Ssam } 1777624Ssam #endif 1787624Ssam if (com == FIOCLEX) { 1799592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 1807423Sroot return; 1817423Sroot } 1827624Ssam if (com == FIONCLEX) { 1839592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 1847423Sroot return; 1857423Sroot } 1867624Ssam 1877624Ssam /* 1887624Ssam * Interpret high order word to find 1897624Ssam * amount of data to be copied to/from the 1907624Ssam * user's address space. 1917624Ssam */ 1927624Ssam size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 1937624Ssam if (size > sizeof (data)) { 1947624Ssam u.u_error = EFAULT; 1957423Sroot return; 1967423Sroot } 19710601Ssam if (com&IOC_IN) { 19810601Ssam if (size) { 19910601Ssam u.u_error = 20010601Ssam copyin(uap->cmarg, (caddr_t)data, (u_int)size); 20110601Ssam if (u.u_error) 20210601Ssam return; 20310601Ssam } else 20410601Ssam *(caddr_t *)data = uap->cmarg; 20510601Ssam } else if ((com&IOC_OUT) && size) 20610601Ssam /* 20710601Ssam * Zero the buffer on the stack so the user 20810601Ssam * always gets back something deterministic. 20910601Ssam */ 2107624Ssam bzero((caddr_t)data, size); 21111284Ssam else if (com&IOC_VOID) 21211284Ssam *(caddr_t *)data = uap->cmarg; 2137423Sroot 214*12751Ssam switch (com) { 2157624Ssam 216*12751Ssam case FIONBIO: 217*12751Ssam u.u_error = fset(fp, FNDELAY, *(int *)data); 218*12751Ssam return; 219*12751Ssam 220*12751Ssam case FIOASYNC: 221*12751Ssam u.u_error = fset(fp, FASYNC, *(int *)data); 222*12751Ssam return; 223*12751Ssam 224*12751Ssam case FIOSETOWN: 225*12751Ssam u.u_error = fsetown(fp, *(int *)data); 226*12751Ssam return; 227*12751Ssam 228*12751Ssam case FIOGETOWN: 229*12751Ssam u.u_error = fgetown(fp, (int *)data); 230*12751Ssam return; 2317423Sroot } 232*12751Ssam u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 2337624Ssam /* 2347624Ssam * Copy any data to user, size was 2357624Ssam * already set and checked above. 2367624Ssam */ 2379999Ssam if (u.u_error == 0 && (com&IOC_OUT) && size) 2389999Ssam u.u_error = copyout(data, uap->cmarg, (u_int)size); 2397423Sroot } 2407423Sroot 241*12751Ssam int unselect(); 242*12751Ssam int nselcoll; 2437423Sroot /* 244*12751Ssam * Select system call. 2457423Sroot */ 246*12751Ssam select() 247*12751Ssam { 248*12751Ssam register struct uap { 249*12751Ssam int nd; 250*12751Ssam long *in, *ou, *ex; 251*12751Ssam struct timeval *tv; 252*12751Ssam } *uap = (struct uap *)u.u_ap; 253*12751Ssam int ibits[3], obits[3]; 254*12751Ssam struct timeval atv; 255*12751Ssam int s, ncoll; 256*12751Ssam label_t lqsave; 257*12751Ssam 258*12751Ssam obits[0] = obits[1] = obits[2] = 0; 259*12751Ssam if (uap->nd > NOFILE) 260*12751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 261*12751Ssam 262*12751Ssam #define getbits(name, x) \ 263*12751Ssam if (uap->name) { \ 264*12751Ssam u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 265*12751Ssam sizeof (ibits[x])); \ 266*12751Ssam if (u.u_error) \ 267*12751Ssam goto done; \ 268*12751Ssam } else \ 269*12751Ssam ibits[x] = 0; 270*12751Ssam getbits(in, 0); 271*12751Ssam getbits(ou, 1); 272*12751Ssam getbits(ex, 2); 273*12751Ssam #undef getbits 274*12751Ssam 275*12751Ssam if (uap->tv) { 276*12751Ssam u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 277*12751Ssam sizeof (atv)); 278*12751Ssam if (u.u_error) 279*12751Ssam goto done; 280*12751Ssam if (itimerfix(&atv)) { 281*12751Ssam u.u_error = EINVAL; 282*12751Ssam goto done; 283*12751Ssam } 284*12751Ssam s = spl7(); timevaladd(&atv, &time); splx(s); 285*12751Ssam } 286*12751Ssam retry: 287*12751Ssam ncoll = nselcoll; 288*12751Ssam u.u_procp->p_flag |= SSEL; 289*12751Ssam u.u_r.r_val1 = selscan(ibits, obits); 290*12751Ssam if (u.u_error || u.u_r.r_val1) 291*12751Ssam goto done; 292*12751Ssam s = spl6(); 293*12751Ssam if (uap->tv && timercmp(&time, &atv, >=)) { 294*12751Ssam splx(s); 295*12751Ssam goto done; 296*12751Ssam } 297*12751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 298*12751Ssam u.u_procp->p_flag &= ~SSEL; 299*12751Ssam splx(s); 300*12751Ssam goto retry; 301*12751Ssam } 302*12751Ssam u.u_procp->p_flag &= ~SSEL; 303*12751Ssam if (uap->tv) { 304*12751Ssam lqsave = u.u_qsave; 305*12751Ssam if (setjmp(&u.u_qsave)) { 306*12751Ssam untimeout(unselect, (caddr_t)u.u_procp); 307*12751Ssam u.u_error = EINTR; 308*12751Ssam splx(s); 309*12751Ssam goto done; 310*12751Ssam } 311*12751Ssam timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 312*12751Ssam } 313*12751Ssam sleep((caddr_t)&selwait, PZERO+1); 314*12751Ssam if (uap->tv) { 315*12751Ssam u.u_qsave = lqsave; 316*12751Ssam untimeout(unselect, (caddr_t)u.u_procp); 317*12751Ssam } 318*12751Ssam splx(s); 319*12751Ssam goto retry; 320*12751Ssam done: 321*12751Ssam #define putbits(name, x) \ 322*12751Ssam if (uap->name) { \ 323*12751Ssam int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 324*12751Ssam sizeof (obits[x])); \ 325*12751Ssam if (error) \ 326*12751Ssam u.u_error = error; \ 327*12751Ssam } 328*12751Ssam putbits(in, 0); 329*12751Ssam putbits(ou, 1); 330*12751Ssam putbits(ex, 2); 331*12751Ssam #undef putbits 332*12751Ssam } 333*12751Ssam 334*12751Ssam unselect(p) 335*12751Ssam register struct proc *p; 336*12751Ssam { 337*12751Ssam register int s = spl6(); 338*12751Ssam 339*12751Ssam switch (p->p_stat) { 340*12751Ssam 341*12751Ssam case SSLEEP: 342*12751Ssam setrun(p); 343*12751Ssam break; 344*12751Ssam 345*12751Ssam case SSTOP: 346*12751Ssam unsleep(p); 347*12751Ssam break; 348*12751Ssam } 349*12751Ssam splx(s); 350*12751Ssam } 351*12751Ssam 352*12751Ssam selscan(ibits, obits) 353*12751Ssam int *ibits, *obits; 354*12751Ssam { 355*12751Ssam register int which, bits, i; 356*12751Ssam int flag; 357*12751Ssam struct file *fp; 358*12751Ssam int n = 0; 359*12751Ssam 360*12751Ssam for (which = 0; which < 3; which++) { 361*12751Ssam bits = ibits[which]; 362*12751Ssam obits[which] = 0; 363*12751Ssam switch (which) { 364*12751Ssam 365*12751Ssam case 0: 366*12751Ssam flag = FREAD; break; 367*12751Ssam 368*12751Ssam case 1: 369*12751Ssam flag = FWRITE; break; 370*12751Ssam 371*12751Ssam case 2: 372*12751Ssam flag = 0; break; 373*12751Ssam } 374*12751Ssam while (i = ffs(bits)) { 375*12751Ssam bits &= ~(1<<(i-1)); 376*12751Ssam fp = u.u_ofile[i-1]; 377*12751Ssam if (fp == NULL) { 378*12751Ssam u.u_error = EBADF; 379*12751Ssam break; 380*12751Ssam } 381*12751Ssam if ((*fp->f_ops->fo_select)(fp, flag)) { 382*12751Ssam obits[which] |= (1<<(i-1)); 383*12751Ssam n++; 384*12751Ssam } 385*12751Ssam } 386*12751Ssam } 387*12751Ssam return (n); 388*12751Ssam } 389*12751Ssam 3907423Sroot /*ARGSUSED*/ 391*12751Ssam seltrue(dev, flag) 392*12751Ssam dev_t dev; 393*12751Ssam int flag; 3947423Sroot { 3957423Sroot 396*12751Ssam return (1); 3977423Sroot } 3988103Sroot 399*12751Ssam selwakeup(p, coll) 400*12751Ssam register struct proc *p; 401*12751Ssam int coll; 4028103Sroot { 4038103Sroot 404*12751Ssam if (coll) { 405*12751Ssam nselcoll++; 406*12751Ssam wakeup((caddr_t)&selwait); 407*12751Ssam } 408*12751Ssam if (p) { 409*12751Ssam int s = spl6(); 410*12751Ssam if (p->p_wchan == (caddr_t)&selwait) 411*12751Ssam setrun(p); 412*12751Ssam else if (p->p_flag & SSEL) 413*12751Ssam p->p_flag &= ~SSEL; 414*12751Ssam splx(s); 415*12751Ssam } 4168103Sroot } 4178103Sroot 418*12751Ssam fstat() 4198103Sroot { 420*12751Ssam register struct file *fp; 421*12751Ssam register struct a { 422*12751Ssam int fdes; 423*12751Ssam struct stat *sb; 424*12751Ssam } *uap; 425*12751Ssam struct stat ub; 4268103Sroot 427*12751Ssam uap = (struct a *)u.u_ap; 428*12751Ssam fp = getf(uap->fdes); 429*12751Ssam if (fp == 0) 430*12751Ssam return; 431*12751Ssam u.u_error = (*fp->f_ops->fo_stat)(fp, &ub); 432*12751Ssam if (u.u_error == 0) 433*12751Ssam u.u_error = copyout(&ub, uap->sb, sizeof (ub)); 4348103Sroot } 435