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