xref: /netbsd-src/sys/kern/sys_generic.c (revision 1f2744e6e4915c9da2a3f980279398c4cf7d5e6d)
1 /*	$NetBSD: sys_generic.c,v 1.19 1995/03/21 13:33:34 mycroft 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.5 (Berkeley) 1/21/94
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/uio.h>
51 #include <sys/kernel.h>
52 #include <sys/stat.h>
53 #include <sys/malloc.h>
54 #ifdef KTRACE
55 #include <sys/ktrace.h>
56 #endif
57 
58 #include <sys/mount.h>
59 #include <sys/syscallargs.h>
60 
61 /*
62  * Read system call.
63  */
64 /* ARGSUSED */
65 read(p, uap, retval)
66 	struct proc *p;
67 	register struct read_args /* {
68 		syscallarg(int) fd;
69 		syscallarg(char *) buf;
70 		syscallarg(u_int) nbyte;
71 	} */ *uap;
72 	register_t *retval;
73 {
74 	register struct file *fp;
75 	register struct filedesc *fdp = p->p_fd;
76 	struct uio auio;
77 	struct iovec aiov;
78 	long cnt, error = 0;
79 #ifdef KTRACE
80 	struct iovec ktriov;
81 #endif
82 
83 	if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
84 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
85 	    (fp->f_flag & FREAD) == 0)
86 		return (EBADF);
87 	aiov.iov_base = (caddr_t)SCARG(uap, buf);
88 	aiov.iov_len = SCARG(uap, nbyte);
89 	auio.uio_iov = &aiov;
90 	auio.uio_iovcnt = 1;
91 	auio.uio_resid = SCARG(uap, nbyte);
92 	auio.uio_rw = UIO_READ;
93 	auio.uio_segflg = UIO_USERSPACE;
94 	auio.uio_procp = p;
95 	if (auio.uio_resid < 0)
96 		return EINVAL;
97 #ifdef KTRACE
98 	/*
99 	 * if tracing, save a copy of iovec
100 	 */
101 	if (KTRPOINT(p, KTR_GENIO))
102 		ktriov = aiov;
103 #endif
104 	cnt = SCARG(uap, nbyte);
105 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
106 		if (auio.uio_resid != cnt && (error == ERESTART ||
107 		    error == EINTR || error == EWOULDBLOCK))
108 			error = 0;
109 	cnt -= auio.uio_resid;
110 #ifdef KTRACE
111 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
112 		ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov,
113 		    cnt, error);
114 #endif
115 	*retval = cnt;
116 	return (error);
117 }
118 
119 /*
120  * Scatter read system call.
121  */
122 readv(p, uap, retval)
123 	struct proc *p;
124 	register struct readv_args /* {
125 		syscallarg(int) fd;
126 		syscallarg(struct iovec *) iovp;
127 		syscallarg(u_int) iovcnt;
128 	} */ *uap;
129 	register_t *retval;
130 {
131 	register struct file *fp;
132 	register struct filedesc *fdp = p->p_fd;
133 	struct uio auio;
134 	register struct iovec *iov;
135 	struct iovec *needfree;
136 	struct iovec aiov[UIO_SMALLIOV];
137 	long i, cnt, error = 0;
138 	u_int iovlen;
139 #ifdef KTRACE
140 	struct iovec *ktriov = NULL;
141 #endif
142 
143 	if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
144 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
145 	    (fp->f_flag & FREAD) == 0)
146 		return (EBADF);
147 	/* note: can't use iovlen until iovcnt is validated */
148 	iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
149 	if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
150 		if (SCARG(uap, iovcnt) > UIO_MAXIOV)
151 			return (EINVAL);
152 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
153 		needfree = iov;
154 	} else {
155 		iov = aiov;
156 		needfree = NULL;
157 	}
158 	auio.uio_iov = iov;
159 	auio.uio_iovcnt = SCARG(uap, iovcnt);
160 	auio.uio_rw = UIO_READ;
161 	auio.uio_segflg = UIO_USERSPACE;
162 	auio.uio_procp = p;
163 	if (error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen))
164 		goto done;
165 	auio.uio_resid = 0;
166 	for (i = 0; i < SCARG(uap, iovcnt); i++) {
167 		if (iov->iov_len < 0) {
168 			error = EINVAL;
169 			goto done;
170 		}
171 		auio.uio_resid += iov->iov_len;
172 		if (auio.uio_resid < 0) {
173 			error = EINVAL;
174 			goto done;
175 		}
176 		iov++;
177 	}
178 #ifdef KTRACE
179 	/*
180 	 * if tracing, save a copy of iovec
181 	 */
182 	if (KTRPOINT(p, KTR_GENIO))  {
183 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
184 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
185 	}
186 #endif
187 	cnt = auio.uio_resid;
188 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
189 		if (auio.uio_resid != cnt && (error == ERESTART ||
190 		    error == EINTR || error == EWOULDBLOCK))
191 			error = 0;
192 	cnt -= auio.uio_resid;
193 #ifdef KTRACE
194 	if (ktriov != NULL) {
195 		if (error == 0)
196 			ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov,
197 			    cnt, error);
198 		FREE(ktriov, M_TEMP);
199 	}
200 #endif
201 	*retval = cnt;
202 done:
203 	if (needfree)
204 		FREE(needfree, M_IOV);
205 	return (error);
206 }
207 
208 /*
209  * Write system call
210  */
211 write(p, uap, retval)
212 	struct proc *p;
213 	register struct write_args /* {
214 		syscallarg(int) fd;
215 		syscallarg(char *) buf;
216 		syscallarg(u_int) nbyte;
217 	} */ *uap;
218 	register_t *retval;
219 {
220 	register struct file *fp;
221 	register struct filedesc *fdp = p->p_fd;
222 	struct uio auio;
223 	struct iovec aiov;
224 	long cnt, error = 0;
225 #ifdef KTRACE
226 	struct iovec ktriov;
227 #endif
228 
229 	if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
230 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
231 	    (fp->f_flag & FWRITE) == 0)
232 		return (EBADF);
233 	aiov.iov_base = (caddr_t)SCARG(uap, buf);
234 	aiov.iov_len = SCARG(uap, nbyte);
235 	auio.uio_iov = &aiov;
236 	auio.uio_iovcnt = 1;
237 	auio.uio_resid = SCARG(uap, nbyte);
238 	auio.uio_rw = UIO_WRITE;
239 	auio.uio_segflg = UIO_USERSPACE;
240 	auio.uio_procp = p;
241 	if (auio.uio_resid < 0)
242 		return EINVAL;
243 #ifdef KTRACE
244 	/*
245 	 * if tracing, save a copy of iovec
246 	 */
247 	if (KTRPOINT(p, KTR_GENIO))
248 		ktriov = aiov;
249 #endif
250 	cnt = SCARG(uap, nbyte);
251 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
252 		if (auio.uio_resid != cnt && (error == ERESTART ||
253 		    error == EINTR || error == EWOULDBLOCK))
254 			error = 0;
255 		if (error == EPIPE)
256 			psignal(p, SIGPIPE);
257 	}
258 	cnt -= auio.uio_resid;
259 #ifdef KTRACE
260 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
261 		ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
262 		    &ktriov, cnt, error);
263 #endif
264 	*retval = cnt;
265 	return (error);
266 }
267 
268 /*
269  * Gather write system call
270  */
271 writev(p, uap, retval)
272 	struct proc *p;
273 	register struct writev_args /* {
274 		syscallarg(int) fd;
275 		syscallarg(struct iovec *) iovp;
276 		syscallarg(u_int) iovcnt;
277 	} */ *uap;
278 	register_t *retval;
279 {
280 	register struct file *fp;
281 	register struct filedesc *fdp = p->p_fd;
282 	struct uio auio;
283 	register struct iovec *iov;
284 	struct iovec *needfree;
285 	struct iovec aiov[UIO_SMALLIOV];
286 	long i, cnt, error = 0;
287 	u_int iovlen;
288 #ifdef KTRACE
289 	struct iovec *ktriov = NULL;
290 #endif
291 
292 	if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
293 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
294 	    (fp->f_flag & FWRITE) == 0)
295 		return (EBADF);
296 	/* note: can't use iovlen until iovcnt is validated */
297 	iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
298 	if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
299 		if (SCARG(uap, iovcnt) > UIO_MAXIOV)
300 			return (EINVAL);
301 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
302 		needfree = iov;
303 	} else {
304 		iov = aiov;
305 		needfree = NULL;
306 	}
307 	auio.uio_iov = iov;
308 	auio.uio_iovcnt = SCARG(uap, iovcnt);
309 	auio.uio_rw = UIO_WRITE;
310 	auio.uio_segflg = UIO_USERSPACE;
311 	auio.uio_procp = p;
312 	if (error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen))
313 		goto done;
314 	auio.uio_resid = 0;
315 	for (i = 0; i < SCARG(uap, iovcnt); i++) {
316 		if (iov->iov_len < 0) {
317 			error = EINVAL;
318 			goto done;
319 		}
320 		auio.uio_resid += iov->iov_len;
321 		if (auio.uio_resid < 0) {
322 			error = EINVAL;
323 			goto done;
324 		}
325 		iov++;
326 	}
327 #ifdef KTRACE
328 	/*
329 	 * if tracing, save a copy of iovec
330 	 */
331 	if (KTRPOINT(p, KTR_GENIO))  {
332 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
333 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
334 	}
335 #endif
336 	cnt = auio.uio_resid;
337 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
338 		if (auio.uio_resid != cnt && (error == ERESTART ||
339 		    error == EINTR || error == EWOULDBLOCK))
340 			error = 0;
341 		if (error == EPIPE)
342 			psignal(p, SIGPIPE);
343 	}
344 	cnt -= auio.uio_resid;
345 #ifdef KTRACE
346 	if (ktriov != NULL) {
347 		if (error == 0)
348 			ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
349 				ktriov, cnt, error);
350 		FREE(ktriov, M_TEMP);
351 	}
352 #endif
353 	*retval = cnt;
354 done:
355 	if (needfree)
356 		FREE(needfree, M_IOV);
357 	return (error);
358 }
359 
360 /*
361  * Ioctl system call
362  */
363 /* ARGSUSED */
364 ioctl(p, uap, retval)
365 	struct proc *p;
366 	register struct ioctl_args /* {
367 		syscallarg(int) fd;
368 		syscallarg(u_long) com;
369 		syscallarg(caddr_t) data;
370 	} */ *uap;
371 	register_t *retval;
372 {
373 	register struct file *fp;
374 	register struct filedesc *fdp;
375 	register u_long com;
376 	register int error;
377 	register u_int size;
378 	caddr_t data, memp;
379 	int tmp;
380 #define STK_PARAMS	128
381 	char stkbuf[STK_PARAMS];
382 
383 	fdp = p->p_fd;
384 	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
385 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
386 		return (EBADF);
387 
388 	if ((fp->f_flag & (FREAD | FWRITE)) == 0)
389 		return (EBADF);
390 
391 	switch (com = SCARG(uap, com)) {
392 	case FIONCLEX:
393 		fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
394 		return (0);
395 	case FIOCLEX:
396 		fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
397 		return (0);
398 	}
399 
400 	/*
401 	 * Interpret high order word to find amount of data to be
402 	 * copied to/from the user's address space.
403 	 */
404 	size = IOCPARM_LEN(com);
405 	if (size > IOCPARM_MAX)
406 		return (ENOTTY);
407 	memp = NULL;
408 	if (size > sizeof (stkbuf)) {
409 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
410 		data = memp;
411 	} else
412 		data = stkbuf;
413 	if (com&IOC_IN) {
414 		if (size) {
415 			error = copyin(SCARG(uap, data), data, (u_int)size);
416 			if (error) {
417 				if (memp)
418 					free(memp, M_IOCTLOPS);
419 				return (error);
420 			}
421 		} else
422 			*(caddr_t *)data = SCARG(uap, data);
423 	} else if ((com&IOC_OUT) && size)
424 		/*
425 		 * Zero the buffer so the user always
426 		 * gets back something deterministic.
427 		 */
428 		bzero(data, size);
429 	else if (com&IOC_VOID)
430 		*(caddr_t *)data = SCARG(uap, data);
431 
432 	switch (com) {
433 
434 	case FIONBIO:
435 		if (tmp = *(int *)data)
436 			fp->f_flag |= FNONBLOCK;
437 		else
438 			fp->f_flag &= ~FNONBLOCK;
439 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
440 		break;
441 
442 	case FIOASYNC:
443 		if (tmp = *(int *)data)
444 			fp->f_flag |= FASYNC;
445 		else
446 			fp->f_flag &= ~FASYNC;
447 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
448 		break;
449 
450 	case FIOSETOWN:
451 		tmp = *(int *)data;
452 		if (fp->f_type == DTYPE_SOCKET) {
453 			((struct socket *)fp->f_data)->so_pgid = tmp;
454 			error = 0;
455 			break;
456 		}
457 		if (tmp <= 0) {
458 			tmp = -tmp;
459 		} else {
460 			struct proc *p1 = pfind(tmp);
461 			if (p1 == 0) {
462 				error = ESRCH;
463 				break;
464 			}
465 			tmp = p1->p_pgrp->pg_id;
466 		}
467 		error = (*fp->f_ops->fo_ioctl)
468 			(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
469 		break;
470 
471 	case FIOGETOWN:
472 		if (fp->f_type == DTYPE_SOCKET) {
473 			error = 0;
474 			*(int *)data = ((struct socket *)fp->f_data)->so_pgid;
475 			break;
476 		}
477 		error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
478 		*(int *)data = -*(int *)data;
479 		break;
480 
481 	default:
482 		error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
483 		/*
484 		 * Copy any data to user, size was
485 		 * already set and checked above.
486 		 */
487 		if (error == 0 && (com&IOC_OUT) && size)
488 			error = copyout(data, SCARG(uap, data), (u_int)size);
489 		break;
490 	}
491 	if (memp)
492 		free(memp, M_IOCTLOPS);
493 	return (error);
494 }
495 
496 int	selwait, nselcoll;
497 
498 /*
499  * Select system call.
500  */
501 select(p, uap, retval)
502 	register struct proc *p;
503 	register struct select_args /* {
504 		syscallarg(u_int) nd;
505 		syscallarg(fd_set *) in;
506 		syscallarg(fd_set *) ou;
507 		syscallarg(fd_set *) ex;
508 		syscallarg(struct timeval *) tv;
509 	} */ *uap;
510 	register_t *retval;
511 {
512 	fd_set ibits[3], obits[3];
513 	struct timeval atv;
514 	int s, ncoll, error = 0, timo;
515 	u_int ni;
516 
517 	bzero((caddr_t)ibits, sizeof(ibits));
518 	bzero((caddr_t)obits, sizeof(obits));
519 	if (SCARG(uap, nd) > FD_SETSIZE)
520 		return (EINVAL);
521 	if (SCARG(uap, nd) > p->p_fd->fd_nfiles) {
522 		/* forgiving; slightly wrong */
523 		SCARG(uap, nd) = p->p_fd->fd_nfiles;
524 	}
525 	ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask);
526 
527 #define	getbits(name, x) \
528 	if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \
529 	    (caddr_t)&ibits[x], ni))) \
530 		goto done;
531 	getbits(in, 0);
532 	getbits(ou, 1);
533 	getbits(ex, 2);
534 #undef	getbits
535 
536 	if (SCARG(uap, tv)) {
537 		error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv,
538 			sizeof (atv));
539 		if (error)
540 			goto done;
541 		if (itimerfix(&atv)) {
542 			error = EINVAL;
543 			goto done;
544 		}
545 		s = splclock();
546 		timeradd(&atv, &time, &atv);
547 		timo = hzto(&atv);
548 		/*
549 		 * Avoid inadvertently sleeping forever.
550 		 */
551 		if (timo == 0)
552 			timo = 1;
553 		splx(s);
554 	} else
555 		timo = 0;
556 retry:
557 	ncoll = nselcoll;
558 	p->p_flag |= P_SELECT;
559 	error = selscan(p, ibits, obits, SCARG(uap, nd), retval);
560 	if (error || *retval)
561 		goto done;
562 	s = splhigh();
563 	/* this should be timercmp(&time, &atv, >=) */
564 	if (SCARG(uap, tv) && (time.tv_sec > atv.tv_sec ||
565 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
566 		splx(s);
567 		goto done;
568 	}
569 	if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
570 		splx(s);
571 		goto retry;
572 	}
573 	p->p_flag &= ~P_SELECT;
574 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
575 	splx(s);
576 	if (error == 0)
577 		goto retry;
578 done:
579 	p->p_flag &= ~P_SELECT;
580 	/* select is not restarted after signals... */
581 	if (error == ERESTART)
582 		error = EINTR;
583 	if (error == EWOULDBLOCK)
584 		error = 0;
585 #define	putbits(name, x) \
586 	if (SCARG(uap, name) && (error2 = copyout((caddr_t)&obits[x], \
587 	    (caddr_t)SCARG(uap, name), ni))) \
588 		error = error2;
589 	if (error == 0) {
590 		int error2;
591 
592 		putbits(in, 0);
593 		putbits(ou, 1);
594 		putbits(ex, 2);
595 #undef putbits
596 	}
597 	return (error);
598 }
599 
600 selscan(p, ibits, obits, nfd, retval)
601 	struct proc *p;
602 	fd_set *ibits, *obits;
603 	int nfd;
604 	register_t *retval;
605 {
606 	register struct filedesc *fdp = p->p_fd;
607 	register int msk, i, j, fd;
608 	register fd_mask bits;
609 	struct file *fp;
610 	int n = 0;
611 	static int flag[3] = { FREAD, FWRITE, 0 };
612 
613 	for (msk = 0; msk < 3; msk++) {
614 		for (i = 0; i < nfd; i += NFDBITS) {
615 			bits = ibits[msk].fds_bits[i/NFDBITS];
616 			while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
617 				bits &= ~(1 << j);
618 				fp = fdp->fd_ofiles[fd];
619 				if (fp == NULL)
620 					return (EBADF);
621 				if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
622 					FD_SET(fd, &obits[msk]);
623 					n++;
624 				}
625 			}
626 		}
627 	}
628 	*retval = n;
629 	return (0);
630 }
631 
632 /*ARGSUSED*/
633 seltrue(dev, flag, p)
634 	dev_t dev;
635 	int flag;
636 	struct proc *p;
637 {
638 
639 	return (1);
640 }
641 
642 /*
643  * Record a select request.
644  */
645 void
646 selrecord(selector, sip)
647 	struct proc *selector;
648 	struct selinfo *sip;
649 {
650 	struct proc *p;
651 	pid_t mypid;
652 
653 	mypid = selector->p_pid;
654 	if (sip->si_pid == mypid)
655 		return;
656 	if (sip->si_pid && (p = pfind(sip->si_pid)) &&
657 	    p->p_wchan == (caddr_t)&selwait)
658 		sip->si_flags |= SI_COLL;
659 	else
660 		sip->si_pid = mypid;
661 }
662 
663 /*
664  * Do a wakeup when a selectable event occurs.
665  */
666 void
667 selwakeup(sip)
668 	register struct selinfo *sip;
669 {
670 	register struct proc *p;
671 	int s;
672 
673 	if (sip->si_pid == 0)
674 		return;
675 	if (sip->si_flags & SI_COLL) {
676 		nselcoll++;
677 		sip->si_flags &= ~SI_COLL;
678 		wakeup((caddr_t)&selwait);
679 	}
680 	p = pfind(sip->si_pid);
681 	sip->si_pid = 0;
682 	if (p != NULL) {
683 		s = splhigh();
684 		if (p->p_wchan == (caddr_t)&selwait) {
685 			if (p->p_stat == SSLEEP)
686 				setrunnable(p);
687 			else
688 				unsleep(p);
689 		} else if (p->p_flag & P_SELECT)
690 			p->p_flag &= ~P_SELECT;
691 		splx(s);
692 	}
693 }
694