1: /* 2: * Copyright (c) 1982, 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)sys_generic.c 7.1 (Berkeley) 6/5/86 7: */ 8: 9: #include "param.h" 10: #include "systm.h" 11: #include "dir.h" 12: #include "user.h" 13: #include "ioctl.h" 14: #include "file.h" 15: #include "proc.h" 16: #include "uio.h" 17: #include "kernel.h" 18: #include "stat.h" 19: 20: /* 21: * Read system call. 22: */ 23: read() 24: { 25: register struct a { 26: int fdes; 27: char *cbuf; 28: unsigned count; 29: } *uap = (struct a *)u.u_ap; 30: struct uio auio; 31: struct iovec aiov; 32: 33: aiov.iov_base = (caddr_t)uap->cbuf; 34: aiov.iov_len = uap->count; 35: auio.uio_iov = &aiov; 36: auio.uio_iovcnt = 1; 37: rwuio(&auio, UIO_READ); 38: } 39: 40: readv() 41: { 42: register struct a { 43: int fdes; 44: struct iovec *iovp; 45: unsigned iovcnt; 46: } *uap = (struct a *)u.u_ap; 47: struct uio auio; 48: struct iovec aiov[16]; /* XXX */ 49: 50: if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 51: u.u_error = EINVAL; 52: return; 53: } 54: auio.uio_iov = aiov; 55: auio.uio_iovcnt = uap->iovcnt; 56: u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 57: uap->iovcnt * sizeof (struct iovec)); 58: if (u.u_error) 59: return; 60: rwuio(&auio, UIO_READ); 61: } 62: 63: /* 64: * Write system call 65: */ 66: write() 67: { 68: register struct a { 69: int fdes; 70: char *cbuf; 71: unsigned count; 72: } *uap = (struct a *)u.u_ap; 73: struct uio auio; 74: struct iovec aiov; 75: 76: auio.uio_iov = &aiov; 77: auio.uio_iovcnt = 1; 78: aiov.iov_base = uap->cbuf; 79: aiov.iov_len = uap->count; 80: rwuio(&auio, UIO_WRITE); 81: } 82: 83: writev() 84: { 85: register struct a { 86: int fdes; 87: struct iovec *iovp; 88: unsigned iovcnt; 89: } *uap = (struct a *)u.u_ap; 90: struct uio auio; 91: struct iovec aiov[16]; /* XXX */ 92: 93: if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 94: u.u_error = EINVAL; 95: return; 96: } 97: auio.uio_iov = aiov; 98: auio.uio_iovcnt = uap->iovcnt; 99: u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 100: uap->iovcnt * sizeof (struct iovec)); 101: if (u.u_error) 102: return; 103: rwuio(&auio, UIO_WRITE); 104: } 105: 106: rwuio(uio, rw) 107: register struct uio *uio; 108: enum uio_rw rw; 109: { 110: struct a { 111: int fdes; 112: }; 113: register struct file *fp; 114: register struct iovec *iov; 115: int i, count; 116: 117: GETF(fp, ((struct a *)u.u_ap)->fdes); 118: if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) { 119: u.u_error = EBADF; 120: return; 121: } 122: uio->uio_resid = 0; 123: uio->uio_segflg = UIO_USERSPACE; 124: iov = uio->uio_iov; 125: for (i = 0; i < uio->uio_iovcnt; i++) { 126: if (iov->iov_len < 0) { 127: u.u_error = EINVAL; 128: return; 129: } 130: uio->uio_resid += iov->iov_len; 131: if (uio->uio_resid < 0) { 132: u.u_error = EINVAL; 133: return; 134: } 135: iov++; 136: } 137: count = uio->uio_resid; 138: uio->uio_offset = fp->f_offset; 139: if (setjmp(&u.u_qsave)) { 140: if (uio->uio_resid == count) { 141: if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 142: u.u_error = EINTR; 143: else 144: u.u_eosys = RESTARTSYS; 145: } 146: } else 147: u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 148: u.u_r.r_val1 = count - uio->uio_resid; 149: fp->f_offset += u.u_r.r_val1; 150: } 151: 152: /* 153: * Ioctl system call 154: */ 155: ioctl() 156: { 157: register struct file *fp; 158: struct a { 159: int fdes; 160: int cmd; 161: caddr_t cmarg; 162: } *uap; 163: register int com; 164: register u_int size; 165: char data[IOCPARM_MASK+1]; 166: 167: uap = (struct a *)u.u_ap; 168: GETF(fp, uap->fdes); 169: if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 170: u.u_error = EBADF; 171: return; 172: } 173: com = uap->cmd; 174: 175: #if defined(vax) && defined(COMPAT) 176: /* 177: * Map old style ioctl's into new for the 178: * sake of backwards compatibility (sigh). 179: */ 180: if ((com&~0xffff) == 0) { 181: com = mapioctl(com); 182: if (com == 0) { 183: u.u_error = EINVAL; 184: return; 185: } 186: } 187: #endif 188: if (com == FIOCLEX) { 189: u.u_pofile[uap->fdes] |= UF_EXCLOSE; 190: return; 191: } 192: if (com == FIONCLEX) { 193: u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 194: return; 195: } 196: 197: /* 198: * Interpret high order word to find 199: * amount of data to be copied to/from the 200: * user's address space. 201: */ 202: size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 203: if (size > sizeof (data)) { 204: u.u_error = EFAULT; 205: return; 206: } 207: if (com&IOC_IN) { 208: if (size) { 209: u.u_error = 210: copyin(uap->cmarg, (caddr_t)data, (u_int)size); 211: if (u.u_error) 212: return; 213: } else 214: *(caddr_t *)data = uap->cmarg; 215: } else if ((com&IOC_OUT) && size) 216: /* 217: * Zero the buffer on the stack so the user 218: * always gets back something deterministic. 219: */ 220: bzero((caddr_t)data, size); 221: else if (com&IOC_VOID) 222: *(caddr_t *)data = uap->cmarg; 223: 224: switch (com) { 225: 226: case FIONBIO: 227: u.u_error = fset(fp, FNDELAY, *(int *)data); 228: return; 229: 230: case FIOASYNC: 231: u.u_error = fset(fp, FASYNC, *(int *)data); 232: return; 233: 234: case FIOSETOWN: 235: u.u_error = fsetown(fp, *(int *)data); 236: return; 237: 238: case FIOGETOWN: 239: u.u_error = fgetown(fp, (int *)data); 240: return; 241: } 242: u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 243: /* 244: * Copy any data to user, size was 245: * already set and checked above. 246: */ 247: if (u.u_error == 0 && (com&IOC_OUT) && size) 248: u.u_error = copyout(data, uap->cmarg, (u_int)size); 249: } 250: 251: int unselect(); 252: int nselcoll; 253: 254: /* 255: * Select system call. 256: */ 257: select() 258: { 259: register struct uap { 260: int nd; 261: fd_set *in, *ou, *ex; 262: struct timeval *tv; 263: } *uap = (struct uap *)u.u_ap; 264: fd_set ibits[3], obits[3]; 265: struct timeval atv; 266: int s, ncoll, ni; 267: label_t lqsave; 268: 269: bzero((caddr_t)ibits, sizeof(ibits)); 270: bzero((caddr_t)obits, sizeof(obits)); 271: if (uap->nd > NOFILE) 272: uap->nd = NOFILE; /* forgiving, if slightly wrong */ 273: ni = howmany(uap->nd, NFDBITS); 274: 275: #define getbits(name, x) \ 276: if (uap->name) { \ 277: u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 278: (unsigned)(ni * sizeof(fd_mask))); \ 279: if (u.u_error) \ 280: goto done; \ 281: } 282: getbits(in, 0); 283: getbits(ou, 1); 284: getbits(ex, 2); 285: #undef getbits 286: 287: if (uap->tv) { 288: u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 289: sizeof (atv)); 290: if (u.u_error) 291: goto done; 292: if (itimerfix(&atv)) { 293: u.u_error = EINVAL; 294: goto done; 295: } 296: s = splhigh(); timevaladd(&atv, &time); splx(s); 297: } 298: retry: 299: ncoll = nselcoll; 300: u.u_procp->p_flag |= SSEL; 301: u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 302: if (u.u_error || u.u_r.r_val1) 303: goto done; 304: s = splhigh(); 305: /* this should be timercmp(&time, &atv, >=) */ 306: if (uap->tv && (time.tv_sec > atv.tv_sec || 307: time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 308: splx(s); 309: goto done; 310: } 311: if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 312: u.u_procp->p_flag &= ~SSEL; 313: splx(s); 314: goto retry; 315: } 316: u.u_procp->p_flag &= ~SSEL; 317: if (uap->tv) { 318: lqsave = u.u_qsave; 319: if (setjmp(&u.u_qsave)) { 320: untimeout(unselect, (caddr_t)u.u_procp); 321: u.u_error = EINTR; 322: splx(s); 323: goto done; 324: } 325: timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 326: } 327: sleep((caddr_t)&selwait, PZERO+1); 328: if (uap->tv) { 329: u.u_qsave = lqsave; 330: untimeout(unselect, (caddr_t)u.u_procp); 331: } 332: splx(s); 333: goto retry; 334: done: 335: #define putbits(name, x) \ 336: if (uap->name) { \ 337: int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 338: (unsigned)(ni * sizeof(fd_mask))); \ 339: if (error) \ 340: u.u_error = error; \ 341: } 342: if (u.u_error == 0) { 343: putbits(in, 0); 344: putbits(ou, 1); 345: putbits(ex, 2); 346: #undef putbits 347: } 348: } 349: 350: unselect(p) 351: register struct proc *p; 352: { 353: register int s = splhigh(); 354: 355: switch (p->p_stat) { 356: 357: case SSLEEP: 358: setrun(p); 359: break; 360: 361: case SSTOP: 362: unsleep(p); 363: break; 364: } 365: splx(s); 366: } 367: 368: selscan(ibits, obits, nfd) 369: fd_set *ibits, *obits; 370: { 371: register int which, i, j; 372: register fd_mask bits; 373: int flag; 374: struct file *fp; 375: int n = 0; 376: 377: for (which = 0; which < 3; which++) { 378: switch (which) { 379: 380: case 0: 381: flag = FREAD; break; 382: 383: case 1: 384: flag = FWRITE; break; 385: 386: case 2: 387: flag = 0; break; 388: } 389: for (i = 0; i < nfd; i += NFDBITS) { 390: bits = ibits[which].fds_bits[i/NFDBITS]; 391: while ((j = ffs(bits)) && i + --j < nfd) { 392: bits &= ~(1 << j); 393: fp = u.u_ofile[i + j]; 394: if (fp == NULL) { 395: u.u_error = EBADF; 396: break; 397: } 398: if ((*fp->f_ops->fo_select)(fp, flag)) { 399: FD_SET(i + j, &obits[which]); 400: n++; 401: } 402: } 403: } 404: } 405: return (n); 406: } 407: 408: /*ARGSUSED*/ 409: seltrue(dev, flag) 410: dev_t dev; 411: int flag; 412: { 413: 414: return (1); 415: } 416: 417: selwakeup(p, coll) 418: register struct proc *p; 419: int coll; 420: { 421: 422: if (coll) { 423: nselcoll++; 424: wakeup((caddr_t)&selwait); 425: } 426: if (p) { 427: int s = splhigh(); 428: if (p->p_wchan == (caddr_t)&selwait) { 429: if (p->p_stat == SSLEEP) 430: setrun(p); 431: else 432: unsleep(p); 433: } else if (p->p_flag & SSEL) 434: p->p_flag &= ~SSEL; 435: splx(s); 436: } 437: }