xref: /csrg-svn/sys/kern/sys_generic.c (revision 40703)
123384Smckusick /*
237728Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
337728Smckusick  * All rights reserved.
423384Smckusick  *
537728Smckusick  * Redistribution and use in source and binary forms are permitted
637728Smckusick  * provided that the above copyright notice and this paragraph are
737728Smckusick  * duplicated in all such forms and that any documentation,
837728Smckusick  * advertising materials, and other materials related to such
937728Smckusick  * distribution and use acknowledge that the software was developed
1037728Smckusick  * by the University of California, Berkeley.  The name of the
1137728Smckusick  * University may not be used to endorse or promote products derived
1237728Smckusick  * from this software without specific prior written permission.
1337728Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437728Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537728Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637728Smckusick  *
17*40703Skarels  *	@(#)sys_generic.c	7.14 (Berkeley) 04/03/90
1823384Smckusick  */
197423Sroot 
2017094Sbloom #include "param.h"
2117094Sbloom #include "systm.h"
2237728Smckusick #include "syscontext.h"
2317094Sbloom #include "ioctl.h"
2417094Sbloom #include "file.h"
2517094Sbloom #include "proc.h"
2617094Sbloom #include "uio.h"
2717094Sbloom #include "kernel.h"
2817094Sbloom #include "stat.h"
2931653Smckusick #include "malloc.h"
3037127Skarels #ifdef KTRACE
3137127Skarels #include "ktrace.h"
3237127Skarels #endif
337423Sroot 
347423Sroot /*
357423Sroot  * Read system call.
367423Sroot  */
377423Sroot read()
387423Sroot {
397423Sroot 	register struct a {
407423Sroot 		int	fdes;
417423Sroot 		char	*cbuf;
427423Sroot 		unsigned count;
437820Sroot 	} *uap = (struct a *)u.u_ap;
4437728Smckusick 	register struct file *fp;
457746Sroot 	struct uio auio;
467746Sroot 	struct iovec aiov;
4737728Smckusick 	long cnt, error = 0;
4837728Smckusick #ifdef KTRACE
4937728Smckusick 	struct iovec ktriov;
5037728Smckusick #endif
517423Sroot 
5237728Smckusick 	if (((unsigned)uap->fdes) >= NOFILE ||
5337728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
5437728Smckusick 	    (fp->f_flag & FREAD) == 0)
5537728Smckusick 		RETURN (EBADF);
5637728Smckusick 	if (uap->count < 0)
5737728Smckusick 		RETURN (EINVAL);
587820Sroot 	aiov.iov_base = (caddr_t)uap->cbuf;
597820Sroot 	aiov.iov_len = uap->count;
607820Sroot 	auio.uio_iov = &aiov;
617820Sroot 	auio.uio_iovcnt = 1;
6237728Smckusick 	auio.uio_resid = uap->count;
6337728Smckusick 	auio.uio_rw = UIO_READ;
6437728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
6537728Smckusick #ifdef KTRACE
6637728Smckusick 	/*
6737728Smckusick 	 * if tracing, save a copy of iovec
6837728Smckusick 	 */
6937728Smckusick 	if (KTRPOINT(u.u_procp, KTR_GENIO))
7037728Smckusick 		ktriov = aiov;
7137728Smckusick #endif
7237728Smckusick 	cnt = uap->count;
73*40703Skarels 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
74*40703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
75*40703Skarels 		    error == EINTR || error == EWOULDBLOCK))
76*40703Skarels 			error = 0;
7737728Smckusick 	cnt -= auio.uio_resid;
7837728Smckusick #ifdef KTRACE
7937728Smckusick 	if (KTRPOINT(u.u_procp, KTR_GENIO))
8038591Smarc 		ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt);
8137728Smckusick #endif
8237728Smckusick 	u.u_r.r_val1 = cnt;
8337728Smckusick 	RETURN (error);
847820Sroot }
857820Sroot 
867820Sroot readv()
877820Sroot {
887820Sroot 	register struct a {
897820Sroot 		int	fdes;
907820Sroot 		struct	iovec *iovp;
9126474Skarels 		unsigned iovcnt;
927820Sroot 	} *uap = (struct a *)u.u_ap;
9337728Smckusick 	register struct file *fp;
947820Sroot 	struct uio auio;
9537728Smckusick 	register struct iovec *iov;
9637728Smckusick 	struct iovec aiov[UIO_SMALLIOV];
9737728Smckusick 	long i, cnt, error = 0;
9837728Smckusick #ifdef KTRACE
9937728Smckusick 	struct iovec *ktriov = NULL;
10037728Smckusick #endif
1017820Sroot 
10237728Smckusick 	if (((unsigned)uap->fdes) >= NOFILE ||
10337728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
10437728Smckusick 	    (fp->f_flag & FREAD) == 0)
10537728Smckusick 		RETURN (EBADF);
10637127Skarels 	if (uap->iovcnt > UIO_SMALLIOV) {
10737728Smckusick 		if (uap->iovcnt > UIO_MAXIOV)
10837728Smckusick 			RETURN (EINVAL);
10937127Skarels 		MALLOC(iov, struct iovec *,
11037127Skarels 		      sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
11137127Skarels 	} else
11237127Skarels 		iov = aiov;
11337127Skarels 	auio.uio_iov = iov;
1147820Sroot 	auio.uio_iovcnt = uap->iovcnt;
11537728Smckusick 	auio.uio_rw = UIO_READ;
11637728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
11737728Smckusick 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
11837728Smckusick 	    uap->iovcnt * sizeof (struct iovec)))
11937127Skarels 		goto done;
12037728Smckusick 	auio.uio_resid = 0;
12137728Smckusick 	for (i = 0; i < uap->iovcnt; i++) {
12237728Smckusick 		if (iov->iov_len < 0) {
12337728Smckusick 			error = EINVAL;
12437728Smckusick 			goto done;
12537728Smckusick 		}
12637728Smckusick 		auio.uio_resid += iov->iov_len;
12737728Smckusick 		if (auio.uio_resid < 0) {
12837728Smckusick 			error = EINVAL;
12937728Smckusick 			goto done;
13037728Smckusick 		}
13137728Smckusick 		iov++;
13237728Smckusick 	}
13337728Smckusick #ifdef KTRACE
13437728Smckusick 	/*
13537728Smckusick 	 * if tracing, save a copy of iovec
13637728Smckusick 	 */
13737728Smckusick 	if (KTRPOINT(u.u_procp, KTR_GENIO))  {
13837728Smckusick 		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
13937728Smckusick 
14037728Smckusick 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
14137728Smckusick 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
14237728Smckusick 	}
14337728Smckusick #endif
14437728Smckusick 	cnt = auio.uio_resid;
145*40703Skarels 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
146*40703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
147*40703Skarels 		    error == EINTR || error == EWOULDBLOCK))
148*40703Skarels 			error = 0;
14937728Smckusick 	cnt -= auio.uio_resid;
15037728Smckusick #ifdef KTRACE
15137728Smckusick 	if (ktriov != NULL) {
15237728Smckusick 		ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, ktriov, cnt);
15337728Smckusick 		FREE(ktriov, M_TEMP);
15437728Smckusick 	}
15537728Smckusick #endif
15637728Smckusick 	u.u_r.r_val1 = cnt;
15737127Skarels done:
15837728Smckusick 	if (uap->iovcnt > UIO_SMALLIOV)
15937127Skarels 		FREE(iov, M_IOV);
16037728Smckusick 	RETURN (error);
1617423Sroot }
1627423Sroot 
1637423Sroot /*
1647423Sroot  * Write system call
1657423Sroot  */
1667423Sroot write()
1677423Sroot {
1687423Sroot 	register struct a {
1697423Sroot 		int	fdes;
1707423Sroot 		char	*cbuf;
17126474Skarels 		unsigned count;
1727820Sroot 	} *uap = (struct a *)u.u_ap;
17337728Smckusick 	register struct file *fp;
1747820Sroot 	struct uio auio;
1757820Sroot 	struct iovec aiov;
17637728Smckusick 	long cnt, error = 0;
17737728Smckusick #ifdef KTRACE
17837728Smckusick 	struct iovec ktriov;
17937728Smckusick #endif
1807423Sroot 
18137728Smckusick 	if (((unsigned)uap->fdes) >= NOFILE ||
18237728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
18337728Smckusick 	    (fp->f_flag & FWRITE) == 0)
18437728Smckusick 		RETURN (EBADF);
18537728Smckusick 	if (uap->count < 0)
18637728Smckusick 		RETURN (EINVAL);
18737728Smckusick 	aiov.iov_base = (caddr_t)uap->cbuf;
18837728Smckusick 	aiov.iov_len = uap->count;
1897820Sroot 	auio.uio_iov = &aiov;
1907820Sroot 	auio.uio_iovcnt = 1;
19137728Smckusick 	auio.uio_resid = uap->count;
19237728Smckusick 	auio.uio_rw = UIO_WRITE;
19337728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
19437728Smckusick #ifdef KTRACE
19537728Smckusick 	/*
19637728Smckusick 	 * if tracing, save a copy of iovec
19737728Smckusick 	 */
19837728Smckusick 	if (KTRPOINT(u.u_procp, KTR_GENIO))
19937728Smckusick 		ktriov = aiov;
20037728Smckusick #endif
20137728Smckusick 	cnt = uap->count;
202*40703Skarels 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
203*40703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
204*40703Skarels 		    error == EINTR || error == EWOULDBLOCK))
205*40703Skarels 			error = 0;
206*40703Skarels 		if (error == EPIPE)
207*40703Skarels 			psignal(u.u_procp, SIGPIPE);
208*40703Skarels 	}
20937728Smckusick 	cnt -= auio.uio_resid;
21037728Smckusick #ifdef KTRACE
21137728Smckusick 	if (KTRPOINT(u.u_procp, KTR_GENIO))
21237728Smckusick 		ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE,
21338591Smarc 		    &ktriov, cnt);
21437728Smckusick #endif
21537728Smckusick 	u.u_r.r_val1 = cnt;
21637728Smckusick 	RETURN (error);
2177820Sroot }
2187820Sroot 
2197820Sroot writev()
2207820Sroot {
2217820Sroot 	register struct a {
2227820Sroot 		int	fdes;
2237820Sroot 		struct	iovec *iovp;
22426474Skarels 		unsigned iovcnt;
2257820Sroot 	} *uap = (struct a *)u.u_ap;
22637728Smckusick 	register struct file *fp;
2277820Sroot 	struct uio auio;
22837728Smckusick 	register struct iovec *iov;
22937728Smckusick 	struct iovec aiov[UIO_SMALLIOV];
23037728Smckusick 	long i, cnt, error = 0;
23137728Smckusick #ifdef KTRACE
23237728Smckusick 	struct iovec *ktriov = NULL;
23337728Smckusick #endif
2347820Sroot 
23537728Smckusick 	if (((unsigned)uap->fdes) >= NOFILE ||
23637728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
23737728Smckusick 	    (fp->f_flag & FWRITE) == 0)
23837728Smckusick 		RETURN (EBADF);
23937127Skarels 	if (uap->iovcnt > UIO_SMALLIOV) {
24037728Smckusick 		if (uap->iovcnt > UIO_MAXIOV)
24137728Smckusick 			RETURN (EINVAL);
24237127Skarels 		MALLOC(iov, struct iovec *,
24337127Skarels 		      sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
24437127Skarels 	} else
24537127Skarels 		iov = aiov;
24637127Skarels 	auio.uio_iov = iov;
2477820Sroot 	auio.uio_iovcnt = uap->iovcnt;
24837728Smckusick 	auio.uio_rw = UIO_WRITE;
24937728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
25037728Smckusick 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
25137728Smckusick 	    uap->iovcnt * sizeof (struct iovec)))
25237127Skarels 		goto done;
25337728Smckusick 	auio.uio_resid = 0;
25437728Smckusick 	for (i = 0; i < uap->iovcnt; i++) {
2557820Sroot 		if (iov->iov_len < 0) {
25637728Smckusick 			error = EINVAL;
25737728Smckusick 			goto done;
2587820Sroot 		}
25937728Smckusick 		auio.uio_resid += iov->iov_len;
26037728Smckusick 		if (auio.uio_resid < 0) {
26137728Smckusick 			error = EINVAL;
26237728Smckusick 			goto done;
2637820Sroot 		}
26413270Ssam 		iov++;
2657820Sroot 	}
26637127Skarels #ifdef KTRACE
26737728Smckusick 	/*
26837728Smckusick 	 * if tracing, save a copy of iovec
26937728Smckusick 	 */
27037127Skarels 	if (KTRPOINT(u.u_procp, KTR_GENIO))  {
27137728Smckusick 		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
27237127Skarels 
27337127Skarels 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
27437728Smckusick 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
27537127Skarels 	}
27637127Skarels #endif
27737728Smckusick 	cnt = auio.uio_resid;
278*40703Skarels 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
279*40703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
280*40703Skarels 		    error == EINTR || error == EWOULDBLOCK))
281*40703Skarels 			error = 0;
282*40703Skarels 		if (error == EPIPE)
283*40703Skarels 			psignal(u.u_procp, SIGPIPE);
284*40703Skarels 	}
28537728Smckusick 	cnt -= auio.uio_resid;
28637127Skarels #ifdef KTRACE
28737127Skarels 	if (ktriov != NULL) {
28837728Smckusick 		ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE,
28937728Smckusick 		    ktriov, cnt);
29037127Skarels 		FREE(ktriov, M_TEMP);
29137127Skarels 	}
29237127Skarels #endif
29337728Smckusick 	u.u_r.r_val1 = cnt;
29437728Smckusick done:
29537728Smckusick 	if (uap->iovcnt > UIO_SMALLIOV)
29637728Smckusick 		FREE(iov, M_IOV);
29737728Smckusick 	RETURN (error);
2987423Sroot }
2997423Sroot 
3007423Sroot /*
3017423Sroot  * Ioctl system call
3027423Sroot  */
3037423Sroot ioctl()
3047423Sroot {
3057423Sroot 	register struct file *fp;
3067624Ssam 	struct a {
3077423Sroot 		int	fdes;
3087423Sroot 		int	cmd;
3097423Sroot 		caddr_t	cmarg;
31037728Smckusick 	} *uap = (struct a *)u.u_ap;
311*40703Skarels 	register int com, error;
3127820Sroot 	register u_int size;
31331653Smckusick 	caddr_t memp = 0;
31430530Skarels #define STK_PARAMS	128
31533480Skarels 	char stkbuf[STK_PARAMS];
31633480Skarels 	caddr_t data = stkbuf;
3177423Sroot 
31837728Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
31937728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL)
32037728Smckusick 		RETURN (EBADF);
321*40703Skarels 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
322*40703Skarels 		RETURN (EBADF);
3237624Ssam 	com = uap->cmd;
3247624Ssam 
3257624Ssam 	if (com == FIOCLEX) {
3269592Ssam 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
3277423Sroot 		return;
3287423Sroot 	}
3297624Ssam 	if (com == FIONCLEX) {
3309592Ssam 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
331*40703Skarels 		RETURN (0);
3327423Sroot 	}
3337624Ssam 
3347624Ssam 	/*
3357624Ssam 	 * Interpret high order word to find
3367624Ssam 	 * amount of data to be copied to/from the
3377624Ssam 	 * user's address space.
3387624Ssam 	 */
33930530Skarels 	size = IOCPARM_LEN(com);
340*40703Skarels 	if (size > IOCPARM_MAX)
341*40703Skarels 		RETURN (ENOTTY);
34233480Skarels 	if (size > sizeof (stkbuf)) {
34337127Skarels 		memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS,
34434473Smckusick 		    M_WAITOK);
34531653Smckusick 		data = memp;
34630530Skarels 	}
34710601Ssam 	if (com&IOC_IN) {
34810601Ssam 		if (size) {
349*40703Skarels 			error = copyin(uap->cmarg, data, (u_int)size);
350*40703Skarels 			if (error) {
35131653Smckusick 				if (memp)
35231653Smckusick 					free(memp, M_IOCTLOPS);
353*40703Skarels 				RETURN (error);
35431653Smckusick 			}
35510601Ssam 		} else
35610601Ssam 			*(caddr_t *)data = uap->cmarg;
35710601Ssam 	} else if ((com&IOC_OUT) && size)
35810601Ssam 		/*
35937127Skarels 		 * Zero the buffer so the user always
36037127Skarels 		 * gets back something deterministic.
36110601Ssam 		 */
36230530Skarels 		bzero(data, size);
36311284Ssam 	else if (com&IOC_VOID)
36411284Ssam 		*(caddr_t *)data = uap->cmarg;
3657423Sroot 
36612751Ssam 	switch (com) {
3677624Ssam 
36812751Ssam 	case FIONBIO:
369*40703Skarels 		error = fset(fp, FNDELAY, *(int *)data);
37030530Skarels 		break;
37112751Ssam 
37212751Ssam 	case FIOASYNC:
373*40703Skarels 		error = fset(fp, FASYNC, *(int *)data);
37430530Skarels 		break;
37512751Ssam 
37612751Ssam 	case FIOSETOWN:
377*40703Skarels 		error = fsetown(fp, *(int *)data);
37830530Skarels 		break;
37912751Ssam 
38012751Ssam 	case FIOGETOWN:
381*40703Skarels 		error = fgetown(fp, (int *)data);
38230530Skarels 		break;
38330530Skarels 	default:
384*40703Skarels 		error = (*fp->f_ops->fo_ioctl)(fp, com, data);
38530530Skarels 		/*
38630530Skarels 		 * Copy any data to user, size was
38730530Skarels 		 * already set and checked above.
38830530Skarels 		 */
389*40703Skarels 		if (error == 0 && (com&IOC_OUT) && size)
390*40703Skarels 			error = copyout(data, uap->cmarg, (u_int)size);
39130530Skarels 		break;
3927423Sroot 	}
39331653Smckusick 	if (memp)
39431653Smckusick 		free(memp, M_IOCTLOPS);
395*40703Skarels 	RETURN (error);
3967423Sroot }
3977423Sroot 
39812751Ssam int	nselcoll;
39917593Skarels 
4007423Sroot /*
40112751Ssam  * Select system call.
4027423Sroot  */
40312751Ssam select()
40412751Ssam {
40512751Ssam 	register struct uap  {
40612751Ssam 		int	nd;
40723523Skarels 		fd_set	*in, *ou, *ex;
40812751Ssam 		struct	timeval *tv;
40912751Ssam 	} *uap = (struct uap *)u.u_ap;
41023523Skarels 	fd_set ibits[3], obits[3];
41112751Ssam 	struct timeval atv;
412*40703Skarels 	int s, ncoll, ni, error = 0, timo;
41312751Ssam 
41426277Skarels 	bzero((caddr_t)ibits, sizeof(ibits));
41526277Skarels 	bzero((caddr_t)obits, sizeof(obits));
41612751Ssam 	if (uap->nd > NOFILE)
41712751Ssam 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
41823523Skarels 	ni = howmany(uap->nd, NFDBITS);
41912751Ssam 
42012751Ssam #define	getbits(name, x) \
42112751Ssam 	if (uap->name) { \
422*40703Skarels 		error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
42326277Skarels 		    (unsigned)(ni * sizeof(fd_mask))); \
424*40703Skarels 		if (error) \
42512751Ssam 			goto done; \
42617593Skarels 	}
42712751Ssam 	getbits(in, 0);
42812751Ssam 	getbits(ou, 1);
42912751Ssam 	getbits(ex, 2);
43012751Ssam #undef	getbits
43112751Ssam 
43212751Ssam 	if (uap->tv) {
433*40703Skarels 		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
43412751Ssam 			sizeof (atv));
435*40703Skarels 		if (error)
43612751Ssam 			goto done;
43712751Ssam 		if (itimerfix(&atv)) {
438*40703Skarels 			error = EINVAL;
43912751Ssam 			goto done;
44012751Ssam 		}
44117934Skarels 		s = splhigh(); timevaladd(&atv, &time); splx(s);
442*40703Skarels 		timo = hzto(&atv);
443*40703Skarels 	} else
444*40703Skarels 		timo = 0;
44512751Ssam retry:
44612751Ssam 	ncoll = nselcoll;
44712751Ssam 	u.u_procp->p_flag |= SSEL;
448*40703Skarels 	u.u_r.r_val1 = selscan(ibits, obits, uap->nd, &error);
449*40703Skarels 	if (error == 0)
450*40703Skarels 		error = u.u_error;		/* XXX */
451*40703Skarels 	if (error || u.u_r.r_val1)
45212751Ssam 		goto done;
45317934Skarels 	s = splhigh();
45412971Ssam 	/* this should be timercmp(&time, &atv, >=) */
45512971Ssam 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
45612971Ssam 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
45712751Ssam 		splx(s);
45812751Ssam 		goto done;
45912751Ssam 	}
46012751Ssam 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
46112751Ssam 		splx(s);
46212751Ssam 		goto retry;
46312751Ssam 	}
46412751Ssam 	u.u_procp->p_flag &= ~SSEL;
465*40703Skarels 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
46612751Ssam 	splx(s);
467*40703Skarels 	if (error == 0)
468*40703Skarels 		goto retry;
46912751Ssam done:
47033712Skarels 	u.u_procp->p_flag &= ~SSEL;
471*40703Skarels 	/* select is not restarted after signals... */
472*40703Skarels 	if (error == ERESTART)
473*40703Skarels 		error = EINTR;
474*40703Skarels 	if (error == EWOULDBLOCK)
475*40703Skarels 		error = 0;
47612751Ssam #define	putbits(name, x) \
47712751Ssam 	if (uap->name) { \
478*40703Skarels 		int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
47926277Skarels 		    (unsigned)(ni * sizeof(fd_mask))); \
480*40703Skarels 		if (error2) \
481*40703Skarels 			error = error2; \
48212751Ssam 	}
483*40703Skarels 	if (error == 0) {
48421106Skarels 		putbits(in, 0);
48521106Skarels 		putbits(ou, 1);
48621106Skarels 		putbits(ex, 2);
48712751Ssam #undef putbits
48821106Skarels 	}
489*40703Skarels 	RETURN (error);
49012751Ssam }
49112751Ssam 
492*40703Skarels selscan(ibits, obits, nfd, errp)
49323523Skarels 	fd_set *ibits, *obits;
494*40703Skarels 	int nfd, *errp;
49512751Ssam {
49623523Skarels 	register int which, i, j;
49723523Skarels 	register fd_mask bits;
49812751Ssam 	int flag;
49912751Ssam 	struct file *fp;
50012751Ssam 	int n = 0;
50112751Ssam 
50212751Ssam 	for (which = 0; which < 3; which++) {
50312751Ssam 		switch (which) {
50412751Ssam 
50512751Ssam 		case 0:
50612751Ssam 			flag = FREAD; break;
50712751Ssam 
50812751Ssam 		case 1:
50912751Ssam 			flag = FWRITE; break;
51012751Ssam 
51112751Ssam 		case 2:
51212751Ssam 			flag = 0; break;
51312751Ssam 		}
51423523Skarels 		for (i = 0; i < nfd; i += NFDBITS) {
51523523Skarels 			bits = ibits[which].fds_bits[i/NFDBITS];
51617593Skarels 			while ((j = ffs(bits)) && i + --j < nfd) {
51717593Skarels 				bits &= ~(1 << j);
51817593Skarels 				fp = u.u_ofile[i + j];
51917593Skarels 				if (fp == NULL) {
520*40703Skarels 					*errp = EBADF;
52117593Skarels 					break;
52217593Skarels 				}
52317593Skarels 				if ((*fp->f_ops->fo_select)(fp, flag)) {
52423523Skarels 					FD_SET(i + j, &obits[which]);
52517593Skarels 					n++;
52617593Skarels 				}
52712751Ssam 			}
52812751Ssam 		}
52912751Ssam 	}
53012751Ssam 	return (n);
53112751Ssam }
53212751Ssam 
5337423Sroot /*ARGSUSED*/
53412751Ssam seltrue(dev, flag)
53512751Ssam 	dev_t dev;
53612751Ssam 	int flag;
5377423Sroot {
5387423Sroot 
53912751Ssam 	return (1);
5407423Sroot }
5418103Sroot 
54212751Ssam selwakeup(p, coll)
54312751Ssam 	register struct proc *p;
54412751Ssam 	int coll;
5458103Sroot {
5468103Sroot 
54712751Ssam 	if (coll) {
54812751Ssam 		nselcoll++;
54912751Ssam 		wakeup((caddr_t)&selwait);
55012751Ssam 	}
55112751Ssam 	if (p) {
55217934Skarels 		int s = splhigh();
55317270Skarels 		if (p->p_wchan == (caddr_t)&selwait) {
55417270Skarels 			if (p->p_stat == SSLEEP)
55517270Skarels 				setrun(p);
55617270Skarels 			else
55717270Skarels 				unsleep(p);
55817270Skarels 		} else if (p->p_flag & SSEL)
55912751Ssam 			p->p_flag &= ~SSEL;
56012751Ssam 		splx(s);
56112751Ssam 	}
5628103Sroot }
563