1 /* $NetBSD: sys_generic.c,v 1.36 1998/03/01 02:22:32 fvdl 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.9 (Berkeley) 2/14/95 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 auio.uio_resid += iov->iov_len; 181 if (auio.uio_resid < 0) { 182 error = EINVAL; 183 goto done; 184 } 185 iov++; 186 } 187 #ifdef KTRACE 188 /* 189 * if tracing, save a copy of iovec 190 */ 191 if (KTRPOINT(p, KTR_GENIO)) { 192 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 193 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 194 } 195 #endif 196 cnt = auio.uio_resid; 197 error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred); 198 if (error) 199 if (auio.uio_resid != cnt && (error == ERESTART || 200 error == EINTR || error == EWOULDBLOCK)) 201 error = 0; 202 cnt -= auio.uio_resid; 203 #ifdef KTRACE 204 if (KTRPOINT(p, KTR_GENIO)) 205 if (error == 0) { 206 ktrgenio(p->p_tracep, fd, UIO_READ, ktriov, cnt, 207 error); 208 FREE(ktriov, M_TEMP); 209 } 210 #endif 211 *retval = cnt; 212 done: 213 if (needfree) 214 FREE(needfree, M_IOV); 215 return (error); 216 } 217 218 /* 219 * Write system call 220 */ 221 int 222 sys_write(p, v, retval) 223 struct proc *p; 224 void *v; 225 register_t *retval; 226 { 227 register struct sys_write_args /* { 228 syscallarg(int) fd; 229 syscallarg(const void *) buf; 230 syscallarg(size_t) nbyte; 231 } */ *uap = v; 232 int fd = SCARG(uap, fd); 233 register struct file *fp; 234 register struct filedesc *fdp = p->p_fd; 235 struct uio auio; 236 struct iovec aiov; 237 long cnt, error = 0; 238 #ifdef KTRACE 239 struct iovec ktriov; 240 #endif 241 242 if ((u_int)fd >= fdp->fd_nfiles || 243 (fp = fdp->fd_ofiles[fd]) == NULL || 244 (fp->f_flag & FWRITE) == 0) 245 return (EBADF); 246 aiov.iov_base = (char *)SCARG(uap, buf); /* XXX kills const */ 247 aiov.iov_len = SCARG(uap, nbyte); 248 auio.uio_iov = &aiov; 249 auio.uio_iovcnt = 1; 250 auio.uio_resid = SCARG(uap, nbyte); 251 auio.uio_rw = UIO_WRITE; 252 auio.uio_segflg = UIO_USERSPACE; 253 auio.uio_procp = p; 254 if (auio.uio_resid < 0) 255 return EINVAL; 256 #ifdef KTRACE 257 /* 258 * if tracing, save a copy of iovec 259 */ 260 if (KTRPOINT(p, KTR_GENIO)) 261 ktriov = aiov; 262 #endif 263 cnt = SCARG(uap, nbyte); 264 error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred); 265 if (error) { 266 if (auio.uio_resid != cnt && (error == ERESTART || 267 error == EINTR || error == EWOULDBLOCK)) 268 error = 0; 269 if (error == EPIPE) 270 psignal(p, SIGPIPE); 271 } 272 cnt -= auio.uio_resid; 273 #ifdef KTRACE 274 if (KTRPOINT(p, KTR_GENIO) && error == 0) 275 ktrgenio(p->p_tracep, fd, UIO_WRITE, &ktriov, cnt, error); 276 #endif 277 *retval = cnt; 278 return (error); 279 } 280 281 /* 282 * Gather write system call 283 */ 284 int 285 sys_writev(p, v, retval) 286 struct proc *p; 287 void *v; 288 register_t *retval; 289 { 290 register struct sys_writev_args /* { 291 syscallarg(int) fd; 292 syscallarg(const struct iovec *) iovp; 293 syscallarg(u_int) iovcnt; 294 } */ *uap = v; 295 int fd = SCARG(uap, fd); 296 int iovcnt = SCARG(uap, iovcnt); 297 register struct file *fp; 298 register struct filedesc *fdp = p->p_fd; 299 struct uio auio; 300 register struct iovec *iov; 301 struct iovec *needfree; 302 struct iovec aiov[UIO_SMALLIOV]; 303 long i, cnt, error = 0; 304 u_int iovlen; 305 #ifdef KTRACE 306 struct iovec *ktriov = NULL; 307 #endif 308 309 if ((u_int)fd >= fdp->fd_nfiles || 310 (fp = fdp->fd_ofiles[fd]) == NULL || 311 (fp->f_flag & FWRITE) == 0) 312 return (EBADF); 313 /* note: can't use iovlen until iovcnt is validated */ 314 iovlen = iovcnt * sizeof (struct iovec); 315 if ((u_int)iovcnt > UIO_SMALLIOV) { 316 if ((u_int)iovcnt > UIO_MAXIOV) 317 return (EINVAL); 318 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 319 needfree = iov; 320 } else { 321 iov = aiov; 322 needfree = NULL; 323 } 324 auio.uio_iov = iov; 325 auio.uio_iovcnt = iovcnt; 326 auio.uio_rw = UIO_WRITE; 327 auio.uio_segflg = UIO_USERSPACE; 328 auio.uio_procp = p; 329 error = copyin(SCARG(uap, iovp), iov, iovlen); 330 if (error) 331 goto done; 332 auio.uio_resid = 0; 333 for (i = 0; i < iovcnt; i++) { 334 auio.uio_resid += iov->iov_len; 335 if (auio.uio_resid < 0) { 336 error = EINVAL; 337 goto done; 338 } 339 iov++; 340 } 341 #ifdef KTRACE 342 /* 343 * if tracing, save a copy of iovec 344 */ 345 if (KTRPOINT(p, KTR_GENIO)) { 346 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 347 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 348 } 349 #endif 350 cnt = auio.uio_resid; 351 error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred); 352 if (error) { 353 if (auio.uio_resid != cnt && (error == ERESTART || 354 error == EINTR || error == EWOULDBLOCK)) 355 error = 0; 356 if (error == EPIPE) 357 psignal(p, SIGPIPE); 358 } 359 cnt -= auio.uio_resid; 360 #ifdef KTRACE 361 if (KTRPOINT(p, KTR_GENIO)) 362 if (error == 0) { 363 ktrgenio(p->p_tracep, fd, UIO_WRITE, ktriov, cnt, 364 error); 365 FREE(ktriov, M_TEMP); 366 } 367 #endif 368 *retval = cnt; 369 done: 370 if (needfree) 371 FREE(needfree, M_IOV); 372 return (error); 373 } 374 375 /* 376 * Ioctl system call 377 */ 378 /* ARGSUSED */ 379 int 380 sys_ioctl(p, v, retval) 381 struct proc *p; 382 void *v; 383 register_t *retval; 384 { 385 register struct sys_ioctl_args /* { 386 syscallarg(int) fd; 387 syscallarg(u_long) com; 388 syscallarg(caddr_t) data; 389 } */ *uap = v; 390 register struct file *fp; 391 register struct filedesc *fdp; 392 register u_long com; 393 register int error; 394 register u_int size; 395 caddr_t data, memp; 396 int tmp; 397 #define STK_PARAMS 128 398 char stkbuf[STK_PARAMS]; 399 400 fdp = p->p_fd; 401 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 402 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 403 return (EBADF); 404 405 if ((fp->f_flag & (FREAD | FWRITE)) == 0) 406 return (EBADF); 407 408 switch (com = SCARG(uap, com)) { 409 case FIONCLEX: 410 fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE; 411 return (0); 412 case FIOCLEX: 413 fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE; 414 return (0); 415 } 416 417 /* 418 * Interpret high order word to find amount of data to be 419 * copied to/from the user's address space. 420 */ 421 size = IOCPARM_LEN(com); 422 if (size > IOCPARM_MAX) 423 return (ENOTTY); 424 memp = NULL; 425 if (size > sizeof (stkbuf)) { 426 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 427 data = memp; 428 } else 429 data = stkbuf; 430 if (com&IOC_IN) { 431 if (size) { 432 error = copyin(SCARG(uap, data), data, size); 433 if (error) { 434 if (memp) 435 free(memp, M_IOCTLOPS); 436 return (error); 437 } 438 } else 439 *(caddr_t *)data = SCARG(uap, data); 440 } else if ((com&IOC_OUT) && size) 441 /* 442 * Zero the buffer so the user always 443 * gets back something deterministic. 444 */ 445 bzero(data, size); 446 else if (com&IOC_VOID) 447 *(caddr_t *)data = SCARG(uap, data); 448 449 switch (com) { 450 451 case FIONBIO: 452 if ((tmp = *(int *)data) != 0) 453 fp->f_flag |= FNONBLOCK; 454 else 455 fp->f_flag &= ~FNONBLOCK; 456 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 457 break; 458 459 case FIOASYNC: 460 if ((tmp = *(int *)data) != 0) 461 fp->f_flag |= FASYNC; 462 else 463 fp->f_flag &= ~FASYNC; 464 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 465 break; 466 467 case FIOSETOWN: 468 tmp = *(int *)data; 469 if (fp->f_type == DTYPE_SOCKET) { 470 ((struct socket *)fp->f_data)->so_pgid = tmp; 471 error = 0; 472 break; 473 } 474 if (tmp <= 0) { 475 tmp = -tmp; 476 } else { 477 struct proc *p1 = pfind(tmp); 478 if (p1 == 0) { 479 error = ESRCH; 480 break; 481 } 482 tmp = p1->p_pgrp->pg_id; 483 } 484 error = (*fp->f_ops->fo_ioctl) 485 (fp, TIOCSPGRP, (caddr_t)&tmp, p); 486 break; 487 488 case FIOGETOWN: 489 if (fp->f_type == DTYPE_SOCKET) { 490 error = 0; 491 *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 492 break; 493 } 494 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p); 495 *(int *)data = -*(int *)data; 496 break; 497 498 default: 499 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 500 /* 501 * Copy any data to user, size was 502 * already set and checked above. 503 */ 504 if (error == 0 && (com&IOC_OUT) && size) 505 error = copyout(data, SCARG(uap, data), size); 506 break; 507 } 508 if (memp) 509 free(memp, M_IOCTLOPS); 510 return (error); 511 } 512 513 int selwait, nselcoll; 514 515 /* 516 * Select system call. 517 */ 518 int 519 sys_select(p, v, retval) 520 register struct proc *p; 521 void *v; 522 register_t *retval; 523 { 524 register struct sys_select_args /* { 525 syscallarg(int) nd; 526 syscallarg(fd_set *) in; 527 syscallarg(fd_set *) ou; 528 syscallarg(fd_set *) ex; 529 syscallarg(struct timeval *) tv; 530 } */ *uap = v; 531 caddr_t bits; 532 char smallbits[howmany(FD_SETSIZE, NFDBITS) * sizeof(fd_mask) * 6]; 533 struct timeval atv; 534 int s, ncoll, error = 0, timo; 535 size_t ni; 536 537 if (SCARG(uap, nd) < 0) 538 return (EINVAL); 539 if (SCARG(uap, nd) > p->p_fd->fd_nfiles) { 540 /* forgiving; slightly wrong */ 541 SCARG(uap, nd) = p->p_fd->fd_nfiles; 542 } 543 ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask); 544 if (ni * 6 > sizeof(smallbits)) 545 bits = malloc(ni * 6, M_TEMP, M_WAITOK); 546 else 547 bits = smallbits; 548 549 #define getbits(name, x) \ 550 if (SCARG(uap, name)) { \ 551 error = copyin(SCARG(uap, name), bits + ni * x, ni); \ 552 if (error) \ 553 goto done; \ 554 } else \ 555 bzero(bits + ni * x, ni); 556 getbits(in, 0); 557 getbits(ou, 1); 558 getbits(ex, 2); 559 #undef getbits 560 561 if (SCARG(uap, tv)) { 562 error = copyin(SCARG(uap, tv), (caddr_t)&atv, 563 sizeof (atv)); 564 if (error) 565 goto done; 566 if (itimerfix(&atv)) { 567 error = EINVAL; 568 goto done; 569 } 570 s = splclock(); 571 timeradd(&atv, &time, &atv); 572 timo = hzto(&atv); 573 /* 574 * Avoid inadvertently sleeping forever. 575 */ 576 if (timo == 0) 577 timo = 1; 578 splx(s); 579 } else 580 timo = 0; 581 retry: 582 ncoll = nselcoll; 583 p->p_flag |= P_SELECT; 584 error = selscan(p, (fd_mask *)(bits + ni * 0), 585 (fd_mask *)(bits + ni * 3), SCARG(uap, nd), retval); 586 if (error || *retval) 587 goto done; 588 s = splhigh(); 589 if (timo && timercmp(&time, &atv, >=)) { 590 splx(s); 591 goto done; 592 } 593 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { 594 splx(s); 595 goto retry; 596 } 597 p->p_flag &= ~P_SELECT; 598 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 599 splx(s); 600 if (error == 0) 601 goto retry; 602 done: 603 p->p_flag &= ~P_SELECT; 604 /* select is not restarted after signals... */ 605 if (error == ERESTART) 606 error = EINTR; 607 if (error == EWOULDBLOCK) 608 error = 0; 609 if (error == 0) { 610 #define putbits(name, x) \ 611 if (SCARG(uap, name)) { \ 612 error = copyout(bits + ni * x, SCARG(uap, name), ni); \ 613 if (error) \ 614 goto out; \ 615 } 616 putbits(in, 3); 617 putbits(ou, 4); 618 putbits(ex, 5); 619 #undef putbits 620 } 621 out: 622 if (ni * 6 > sizeof(smallbits)) 623 free(bits, M_TEMP); 624 return (error); 625 } 626 627 int 628 selscan(p, ibitp, obitp, nfd, retval) 629 struct proc *p; 630 fd_mask *ibitp, *obitp; 631 int nfd; 632 register_t *retval; 633 { 634 register struct filedesc *fdp = p->p_fd; 635 register int msk, i, j, fd; 636 register fd_mask ibits, obits; 637 struct file *fp; 638 int n = 0; 639 static int flag[3] = { POLLRDNORM | POLLHUP | POLLERR, 640 POLLWRNORM | POLLHUP | POLLERR, 641 POLLRDBAND }; 642 643 for (msk = 0; msk < 3; msk++) { 644 for (i = 0; i < nfd; i += NFDBITS) { 645 ibits = *ibitp++; 646 obits = 0; 647 while ((j = ffs(ibits)) && (fd = i + --j) < nfd) { 648 ibits &= ~(1 << j); 649 fp = fdp->fd_ofiles[fd]; 650 if (fp == NULL) 651 return (EBADF); 652 if ((*fp->f_ops->fo_poll)(fp, flag[msk], p)) { 653 obits |= (1 << j); 654 n++; 655 } 656 } 657 *obitp++ = obits; 658 } 659 } 660 *retval = n; 661 return (0); 662 } 663 664 /* 665 * Poll system call. 666 */ 667 int 668 sys_poll(p, v, retval) 669 register struct proc *p; 670 void *v; 671 register_t *retval; 672 { 673 register struct sys_poll_args /* { 674 syscallarg(struct pollfd *) fds; 675 syscallarg(u_int) nfds; 676 syscallarg(int) timeout; 677 } */ *uap = v; 678 caddr_t bits; 679 char smallbits[32 * sizeof(struct pollfd)]; 680 struct timeval atv; 681 int s, ncoll, error = 0, timo; 682 size_t ni; 683 684 if (SCARG(uap, nfds) > p->p_fd->fd_nfiles) { 685 /* forgiving; slightly wrong */ 686 SCARG(uap, nfds) = p->p_fd->fd_nfiles; 687 } 688 ni = SCARG(uap, nfds) * sizeof(struct pollfd); 689 if (ni > sizeof(smallbits)) 690 bits = malloc(ni, M_TEMP, M_WAITOK); 691 else 692 bits = smallbits; 693 694 error = copyin(SCARG(uap, fds), bits, ni); 695 if (error) 696 goto done; 697 698 if (SCARG(uap, timeout) != INFTIM) { 699 atv.tv_sec = SCARG(uap, timeout) / 1000; 700 atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000; 701 if (itimerfix(&atv)) { 702 error = EINVAL; 703 goto done; 704 } 705 s = splclock(); 706 timeradd(&atv, &time, &atv); 707 timo = hzto(&atv); 708 /* 709 * Avoid inadvertently sleeping forever. 710 */ 711 if (timo == 0) 712 timo = 1; 713 splx(s); 714 } else 715 timo = 0; 716 retry: 717 ncoll = nselcoll; 718 p->p_flag |= P_SELECT; 719 error = pollscan(p, (struct pollfd *)bits, SCARG(uap, nfds), retval); 720 if (error || *retval) 721 goto done; 722 s = splhigh(); 723 if (timo && timercmp(&time, &atv, >=)) { 724 splx(s); 725 goto done; 726 } 727 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { 728 splx(s); 729 goto retry; 730 } 731 p->p_flag &= ~P_SELECT; 732 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 733 splx(s); 734 if (error == 0) 735 goto retry; 736 done: 737 p->p_flag &= ~P_SELECT; 738 /* poll is not restarted after signals... */ 739 if (error == ERESTART) 740 error = EINTR; 741 if (error == EWOULDBLOCK) 742 error = 0; 743 if (error == 0) { 744 error = copyout(bits, SCARG(uap, fds), ni); 745 if (error) 746 goto out; 747 } 748 out: 749 if (ni > sizeof(smallbits)) 750 free(bits, M_TEMP); 751 return (error); 752 } 753 754 int 755 pollscan(p, fds, nfd, retval) 756 struct proc *p; 757 struct pollfd *fds; 758 int nfd; 759 register_t *retval; 760 { 761 register struct filedesc *fdp = p->p_fd; 762 int i; 763 struct file *fp; 764 int n = 0; 765 766 for (i = 0; i < nfd; i++, fds++) { 767 if ((u_int)fds->fd >= fdp->fd_nfiles) { 768 fds->revents = POLLNVAL; 769 n++; 770 } else { 771 fp = fdp->fd_ofiles[fds->fd]; 772 if (fp == 0) { 773 fds->revents = POLLNVAL; 774 n++; 775 } else { 776 fds->revents = (*fp->f_ops->fo_poll)(fp, 777 fds->events | POLLERR | POLLHUP, p); 778 if (fds->revents != 0) 779 n++; 780 } 781 } 782 } 783 *retval = n; 784 return (0); 785 } 786 787 /*ARGSUSED*/ 788 int 789 seltrue(dev, events, p) 790 dev_t dev; 791 int events; 792 struct proc *p; 793 { 794 795 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 796 } 797 798 /* 799 * Record a select request. 800 */ 801 void 802 selrecord(selector, sip) 803 struct proc *selector; 804 struct selinfo *sip; 805 { 806 struct proc *p; 807 pid_t mypid; 808 809 mypid = selector->p_pid; 810 if (sip->si_pid == mypid) 811 return; 812 if (sip->si_pid && (p = pfind(sip->si_pid)) && 813 p->p_wchan == (caddr_t)&selwait) 814 sip->si_flags |= SI_COLL; 815 else 816 sip->si_pid = mypid; 817 } 818 819 /* 820 * Do a wakeup when a selectable event occurs. 821 */ 822 void 823 selwakeup(sip) 824 register struct selinfo *sip; 825 { 826 register struct proc *p; 827 int s; 828 829 if (sip->si_pid == 0) 830 return; 831 if (sip->si_flags & SI_COLL) { 832 nselcoll++; 833 sip->si_flags &= ~SI_COLL; 834 wakeup((caddr_t)&selwait); 835 } 836 p = pfind(sip->si_pid); 837 sip->si_pid = 0; 838 if (p != NULL) { 839 s = splhigh(); 840 if (p->p_wchan == (caddr_t)&selwait) { 841 if (p->p_stat == SSLEEP) 842 setrunnable(p); 843 else 844 unsleep(p); 845 } else if (p->p_flag & P_SELECT) 846 p->p_flag &= ~P_SELECT; 847 splx(s); 848 } 849 } 850