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