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