1 /* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94 39 * $Id: sys_generic.c,v 1.13 1995/05/30 08:05:56 rgrimes Exp $ 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/filedesc.h> 45 #include <sys/ioctl.h> 46 #include <sys/file.h> 47 #include <sys/proc.h> 48 #include <sys/stat.h> 49 #include <sys/signalvar.h> 50 #include <sys/socket.h> 51 #include <sys/socketvar.h> 52 #include <sys/uio.h> 53 #include <sys/kernel.h> 54 #include <sys/stat.h> 55 #include <sys/malloc.h> 56 #ifdef KTRACE 57 #include <sys/ktrace.h> 58 #endif 59 #include <vm/vm.h> 60 61 int selscan __P((struct proc *, fd_set *, fd_set *, int, int *)); 62 63 /* 64 * Read system call. 65 */ 66 struct read_args { 67 int fd; 68 char *buf; 69 u_int nbyte; 70 }; 71 /* ARGSUSED */ 72 int 73 read(p, uap, retval) 74 struct proc *p; 75 register struct read_args *uap; 76 int *retval; 77 { 78 register struct file *fp; 79 register struct filedesc *fdp = p->p_fd; 80 struct uio auio; 81 struct iovec aiov; 82 long cnt, error = 0; 83 #ifdef KTRACE 84 struct iovec ktriov; 85 #endif 86 87 if (((u_int)uap->fd) >= fdp->fd_nfiles || 88 (fp = fdp->fd_ofiles[uap->fd]) == NULL || 89 (fp->f_flag & FREAD) == 0) 90 return (EBADF); 91 aiov.iov_base = (caddr_t)uap->buf; 92 aiov.iov_len = uap->nbyte; 93 auio.uio_iov = &aiov; 94 auio.uio_iovcnt = 1; 95 96 auio.uio_resid = uap->nbyte; 97 if (auio.uio_resid < 0) 98 return (EINVAL); 99 100 auio.uio_rw = UIO_READ; 101 auio.uio_segflg = UIO_USERSPACE; 102 auio.uio_procp = p; 103 #ifdef KTRACE 104 /* 105 * if tracing, save a copy of iovec 106 */ 107 if (KTRPOINT(p, KTR_GENIO)) 108 ktriov = aiov; 109 #endif 110 cnt = uap->nbyte; 111 if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))) 112 if (auio.uio_resid != cnt && (error == ERESTART || 113 error == EINTR || error == EWOULDBLOCK)) 114 error = 0; 115 cnt -= auio.uio_resid; 116 #ifdef KTRACE 117 if (KTRPOINT(p, KTR_GENIO) && error == 0) 118 ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error); 119 #endif 120 *retval = cnt; 121 return (error); 122 } 123 124 /* 125 * Scatter read system call. 126 */ 127 struct readv_args { 128 int fdes; 129 struct iovec *iovp; 130 u_int iovcnt; 131 }; 132 int 133 readv(p, uap, retval) 134 struct proc *p; 135 register struct readv_args *uap; 136 int *retval; 137 { 138 register struct file *fp; 139 register struct filedesc *fdp = p->p_fd; 140 struct uio auio; 141 register struct iovec *iov; 142 struct iovec *needfree; 143 struct iovec aiov[UIO_SMALLIOV]; 144 long i, cnt, error = 0; 145 u_int iovlen; 146 #ifdef KTRACE 147 struct iovec *ktriov = NULL; 148 #endif 149 150 if (((u_int)uap->fdes) >= fdp->fd_nfiles || 151 (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 152 (fp->f_flag & FREAD) == 0) 153 return (EBADF); 154 /* note: can't use iovlen until iovcnt is validated */ 155 iovlen = uap->iovcnt * sizeof (struct iovec); 156 if (uap->iovcnt > UIO_SMALLIOV) { 157 if (uap->iovcnt > UIO_MAXIOV) 158 return (EINVAL); 159 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 160 needfree = iov; 161 } else { 162 iov = aiov; 163 needfree = NULL; 164 } 165 auio.uio_iov = iov; 166 auio.uio_iovcnt = uap->iovcnt; 167 auio.uio_rw = UIO_READ; 168 auio.uio_segflg = UIO_USERSPACE; 169 auio.uio_procp = p; 170 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))) 171 goto done; 172 auio.uio_resid = 0; 173 for (i = 0; i < uap->iovcnt; i++) { 174 auio.uio_resid += iov->iov_len; 175 if (auio.uio_resid < 0) { 176 error = EINVAL; 177 goto done; 178 } 179 iov++; 180 } 181 #ifdef KTRACE 182 /* 183 * if tracing, save a copy of iovec 184 */ 185 if (KTRPOINT(p, KTR_GENIO)) { 186 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 187 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 188 } 189 #endif 190 cnt = auio.uio_resid; 191 if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))) 192 if (auio.uio_resid != cnt && (error == ERESTART || 193 error == EINTR || error == EWOULDBLOCK)) 194 error = 0; 195 cnt -= auio.uio_resid; 196 #ifdef KTRACE 197 if (ktriov != NULL) { 198 if (error == 0) 199 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 200 cnt, error); 201 FREE(ktriov, M_TEMP); 202 } 203 #endif 204 *retval = cnt; 205 done: 206 if (needfree) 207 FREE(needfree, M_IOV); 208 return (error); 209 } 210 211 /* 212 * Write system call 213 */ 214 struct write_args { 215 int fd; 216 char *buf; 217 u_int nbyte; 218 }; 219 int 220 write(p, uap, retval) 221 struct proc *p; 222 register struct write_args *uap; 223 int *retval; 224 { 225 register struct file *fp; 226 register struct filedesc *fdp = p->p_fd; 227 struct uio auio; 228 struct iovec aiov; 229 long cnt, error = 0; 230 #ifdef KTRACE 231 struct iovec ktriov; 232 #endif 233 234 if (((u_int)uap->fd) >= fdp->fd_nfiles || 235 (fp = fdp->fd_ofiles[uap->fd]) == NULL || 236 (fp->f_flag & FWRITE) == 0) 237 return (EBADF); 238 aiov.iov_base = (caddr_t)uap->buf; 239 aiov.iov_len = uap->nbyte; 240 auio.uio_iov = &aiov; 241 auio.uio_iovcnt = 1; 242 auio.uio_resid = uap->nbyte; 243 auio.uio_rw = UIO_WRITE; 244 auio.uio_segflg = UIO_USERSPACE; 245 auio.uio_procp = p; 246 #ifdef KTRACE 247 /* 248 * if tracing, save a copy of iovec 249 */ 250 if (KTRPOINT(p, KTR_GENIO)) 251 ktriov = aiov; 252 #endif 253 cnt = uap->nbyte; 254 if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred))) { 255 if (auio.uio_resid != cnt && (error == ERESTART || 256 error == EINTR || error == EWOULDBLOCK)) 257 error = 0; 258 if (error == EPIPE) 259 psignal(p, SIGPIPE); 260 } 261 cnt -= auio.uio_resid; 262 #ifdef KTRACE 263 if (KTRPOINT(p, KTR_GENIO) && error == 0) 264 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 265 &ktriov, cnt, error); 266 #endif 267 *retval = cnt; 268 return (error); 269 } 270 271 /* 272 * Gather write system call 273 */ 274 struct writev_args { 275 int fd; 276 struct iovec *iovp; 277 u_int iovcnt; 278 }; 279 int 280 writev(p, uap, retval) 281 struct proc *p; 282 register struct writev_args *uap; 283 int *retval; 284 { 285 register struct file *fp; 286 register struct filedesc *fdp = p->p_fd; 287 struct uio auio; 288 register struct iovec *iov; 289 struct iovec *needfree; 290 struct iovec aiov[UIO_SMALLIOV]; 291 long i, cnt, error = 0; 292 u_int iovlen; 293 #ifdef KTRACE 294 struct iovec *ktriov = NULL; 295 #endif 296 297 if (((u_int)uap->fd) >= fdp->fd_nfiles || 298 (fp = fdp->fd_ofiles[uap->fd]) == NULL || 299 (fp->f_flag & FWRITE) == 0) 300 return (EBADF); 301 /* note: can't use iovlen until iovcnt is validated */ 302 iovlen = uap->iovcnt * sizeof (struct iovec); 303 if (uap->iovcnt > UIO_SMALLIOV) { 304 if (uap->iovcnt > UIO_MAXIOV) 305 return (EINVAL); 306 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 307 needfree = iov; 308 } else { 309 iov = aiov; 310 needfree = NULL; 311 } 312 auio.uio_iov = iov; 313 auio.uio_iovcnt = uap->iovcnt; 314 auio.uio_rw = UIO_WRITE; 315 auio.uio_segflg = UIO_USERSPACE; 316 auio.uio_procp = p; 317 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))) 318 goto done; 319 auio.uio_resid = 0; 320 for (i = 0; i < uap->iovcnt; i++) { 321 auio.uio_resid += iov->iov_len; 322 if (auio.uio_resid < 0) { 323 error = EINVAL; 324 goto done; 325 } 326 iov++; 327 } 328 #ifdef KTRACE 329 /* 330 * if tracing, save a copy of iovec 331 */ 332 if (KTRPOINT(p, KTR_GENIO)) { 333 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 334 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 335 } 336 #endif 337 cnt = auio.uio_resid; 338 if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred))) { 339 if (auio.uio_resid != cnt && (error == ERESTART || 340 error == EINTR || error == EWOULDBLOCK)) 341 error = 0; 342 if (error == EPIPE) 343 psignal(p, SIGPIPE); 344 } 345 cnt -= auio.uio_resid; 346 #ifdef KTRACE 347 if (ktriov != NULL) { 348 if (error == 0) 349 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 350 ktriov, cnt, error); 351 FREE(ktriov, M_TEMP); 352 } 353 #endif 354 *retval = cnt; 355 done: 356 if (needfree) 357 FREE(needfree, M_IOV); 358 return (error); 359 } 360 361 /* 362 * Ioctl system call 363 */ 364 struct ioctl_args { 365 int fd; 366 int com; 367 caddr_t data; 368 }; 369 /* ARGSUSED */ 370 int 371 ioctl(p, uap, retval) 372 struct proc *p; 373 register struct ioctl_args *uap; 374 int *retval; 375 { 376 register struct file *fp; 377 register struct filedesc *fdp; 378 register int com, error; 379 register u_int size; 380 caddr_t data, memp; 381 int tmp; 382 #define STK_PARAMS 128 383 char stkbuf[STK_PARAMS]; 384 385 fdp = p->p_fd; 386 if ((u_int)uap->fd >= fdp->fd_nfiles || 387 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 388 return (EBADF); 389 390 if ((fp->f_flag & (FREAD | FWRITE)) == 0) 391 return (EBADF); 392 393 switch (com = uap->com) { 394 case FIONCLEX: 395 fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE; 396 return (0); 397 case FIOCLEX: 398 fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE; 399 return (0); 400 } 401 402 /* 403 * Interpret high order word to find amount of data to be 404 * copied to/from the user's address space. 405 */ 406 size = IOCPARM_LEN(com); 407 if (size > IOCPARM_MAX) 408 return (ENOTTY); 409 memp = NULL; 410 if (size > sizeof (stkbuf)) { 411 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 412 data = memp; 413 } else 414 data = stkbuf; 415 if (com&IOC_IN) { 416 if (size) { 417 error = copyin(uap->data, data, (u_int)size); 418 if (error) { 419 if (memp) 420 free(memp, M_IOCTLOPS); 421 return (error); 422 } 423 } else 424 *(caddr_t *)data = uap->data; 425 } else if ((com&IOC_OUT) && size) 426 /* 427 * Zero the buffer so the user always 428 * gets back something deterministic. 429 */ 430 bzero(data, size); 431 else if (com&IOC_VOID) 432 *(caddr_t *)data = uap->data; 433 434 switch (com) { 435 436 case FIONBIO: 437 if ((tmp = *(int *)data)) 438 fp->f_flag |= FNONBLOCK; 439 else 440 fp->f_flag &= ~FNONBLOCK; 441 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 442 break; 443 444 case FIOASYNC: 445 if ((tmp = *(int *)data)) 446 fp->f_flag |= FASYNC; 447 else 448 fp->f_flag &= ~FASYNC; 449 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 450 break; 451 452 case FIOSETOWN: 453 tmp = *(int *)data; 454 if (fp->f_type == DTYPE_SOCKET) { 455 ((struct socket *)fp->f_data)->so_pgid = tmp; 456 error = 0; 457 break; 458 } 459 if (tmp <= 0) { 460 tmp = -tmp; 461 } else { 462 struct proc *p1 = pfind(tmp); 463 if (p1 == 0) { 464 error = ESRCH; 465 break; 466 } 467 tmp = p1->p_pgrp->pg_id; 468 } 469 error = (*fp->f_ops->fo_ioctl) 470 (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); 471 break; 472 473 case FIOGETOWN: 474 if (fp->f_type == DTYPE_SOCKET) { 475 error = 0; 476 *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 477 break; 478 } 479 error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); 480 *(int *)data = -*(int *)data; 481 break; 482 483 default: 484 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 485 /* 486 * Copy any data to user, size was 487 * already set and checked above. 488 */ 489 if (error == 0 && (com&IOC_OUT) && size) 490 error = copyout(data, uap->data, (u_int)size); 491 break; 492 } 493 if (memp) 494 free(memp, M_IOCTLOPS); 495 return (error); 496 } 497 498 int selwait, nselcoll; 499 500 /* 501 * Select system call. 502 */ 503 struct select_args { 504 u_int nd; 505 fd_set *in, *ou, *ex; 506 struct timeval *tv; 507 }; 508 int 509 select(p, uap, retval) 510 register struct proc *p; 511 register struct select_args *uap; 512 int *retval; 513 { 514 fd_set ibits[3], obits[3]; 515 struct timeval atv; 516 int s, ncoll, error = 0, timo; 517 u_int ni; 518 519 bzero((caddr_t)ibits, sizeof(ibits)); 520 bzero((caddr_t)obits, sizeof(obits)); 521 if (uap->nd > FD_SETSIZE) 522 return (EINVAL); 523 if (uap->nd > p->p_fd->fd_nfiles) 524 uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 525 ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask); 526 527 #define getbits(name, x) \ 528 if (uap->name && \ 529 (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \ 530 goto done; 531 getbits(in, 0); 532 getbits(ou, 1); 533 getbits(ex, 2); 534 #undef getbits 535 536 if (uap->tv) { 537 error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 538 sizeof (atv)); 539 if (error) 540 goto done; 541 if (itimerfix(&atv)) { 542 error = EINVAL; 543 goto done; 544 } 545 s = splclock(); 546 timevaladd(&atv, (struct timeval *)&time); 547 timo = hzto(&atv); 548 /* 549 * Avoid inadvertently sleeping forever. 550 */ 551 if (timo == 0) 552 timo = 1; 553 splx(s); 554 } else 555 timo = 0; 556 retry: 557 ncoll = nselcoll; 558 p->p_flag |= P_SELECT; 559 error = selscan(p, ibits, obits, uap->nd, retval); 560 if (error || *retval) 561 goto done; 562 s = splhigh(); 563 /* this should be timercmp(&time, &atv, >=) */ 564 if (uap->tv && (time.tv_sec > atv.tv_sec || 565 (time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec))) { 566 splx(s); 567 goto done; 568 } 569 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { 570 splx(s); 571 goto retry; 572 } 573 p->p_flag &= ~P_SELECT; 574 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 575 splx(s); 576 if (error == 0) 577 goto retry; 578 done: 579 p->p_flag &= ~P_SELECT; 580 /* select is not restarted after signals... */ 581 if (error == ERESTART) 582 error = EINTR; 583 if (error == EWOULDBLOCK) 584 error = 0; 585 #define putbits(name, x) \ 586 if (uap->name && \ 587 (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \ 588 error = error2; 589 if (error == 0) { 590 int error2; 591 592 putbits(in, 0); 593 putbits(ou, 1); 594 putbits(ex, 2); 595 #undef putbits 596 } 597 return (error); 598 } 599 600 int 601 selscan(p, ibits, obits, nfd, retval) 602 struct proc *p; 603 fd_set *ibits, *obits; 604 int nfd, *retval; 605 { 606 register struct filedesc *fdp = p->p_fd; 607 register int msk, i, j, fd; 608 register fd_mask bits; 609 struct file *fp; 610 int n = 0; 611 static int flag[3] = { FREAD, FWRITE, 0 }; 612 613 for (msk = 0; msk < 3; msk++) { 614 for (i = 0; i < nfd; i += NFDBITS) { 615 bits = ibits[msk].fds_bits[i/NFDBITS]; 616 while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 617 bits &= ~(1 << j); 618 fp = fdp->fd_ofiles[fd]; 619 if (fp == NULL) 620 return (EBADF); 621 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 622 FD_SET(fd, &obits[msk]); 623 n++; 624 } 625 } 626 } 627 } 628 *retval = n; 629 return (0); 630 } 631 632 /*ARGSUSED*/ 633 int 634 seltrue(dev, flag, p) 635 dev_t dev; 636 int flag; 637 struct proc *p; 638 { 639 640 return (1); 641 } 642 643 /* 644 * Record a select request. 645 */ 646 void 647 selrecord(selector, sip) 648 struct proc *selector; 649 struct selinfo *sip; 650 { 651 struct proc *p; 652 pid_t mypid; 653 654 mypid = selector->p_pid; 655 if (sip->si_pid == mypid) 656 return; 657 if (sip->si_pid && (p = pfind(sip->si_pid)) && 658 p->p_wchan == (caddr_t)&selwait) 659 sip->si_flags |= SI_COLL; 660 else 661 sip->si_pid = mypid; 662 } 663 664 /* 665 * Do a wakeup when a selectable event occurs. 666 */ 667 void 668 selwakeup(sip) 669 register struct selinfo *sip; 670 { 671 register struct proc *p; 672 int s; 673 674 if (sip->si_pid == 0) 675 return; 676 if (sip->si_flags & SI_COLL) { 677 nselcoll++; 678 sip->si_flags &= ~SI_COLL; 679 wakeup((caddr_t)&selwait); 680 } 681 p = pfind(sip->si_pid); 682 sip->si_pid = 0; 683 if (p != NULL) { 684 s = splhigh(); 685 if (p->p_wchan == (caddr_t)&selwait) { 686 if (p->p_stat == SSLEEP) 687 setrunnable(p); 688 else 689 unsleep(p); 690 } else if (p->p_flag & P_SELECT) 691 p->p_flag &= ~P_SELECT; 692 splx(s); 693 } 694 } 695