sys_generic.c revision 1.36 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