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