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