xref: /csrg-svn/sys/kern/sys_generic.c (revision 42922)
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*42922Smckusick  *	@(#)sys_generic.c	7.17 (Berkeley) 06/05/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  */
37*42922Smckusick read(p, uap, retval)
38*42922Smckusick 	struct proc *p;
39*42922Smckusick 	register struct args {
407423Sroot 		int	fdes;
417423Sroot 		char	*cbuf;
427423Sroot 		unsigned count;
43*42922Smckusick 	} *uap;
44*42922Smckusick 	int *retval;
45*42922Smckusick {
4637728Smckusick 	register struct file *fp;
477746Sroot 	struct uio auio;
487746Sroot 	struct iovec aiov;
4937728Smckusick 	long cnt, error = 0;
5037728Smckusick #ifdef KTRACE
5137728Smckusick 	struct iovec ktriov;
5237728Smckusick #endif
537423Sroot 
5437728Smckusick 	if (((unsigned)uap->fdes) >= NOFILE ||
5537728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
5637728Smckusick 	    (fp->f_flag & FREAD) == 0)
5737728Smckusick 		RETURN (EBADF);
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 	 */
69*42922Smckusick 	if (KTRPOINT(p, KTR_GENIO))
7037728Smckusick 		ktriov = aiov;
7137728Smckusick #endif
7237728Smckusick 	cnt = uap->count;
7340703Skarels 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
7440703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
7540703Skarels 		    error == EINTR || error == EWOULDBLOCK))
7640703Skarels 			error = 0;
7737728Smckusick 	cnt -= auio.uio_resid;
7837728Smckusick #ifdef KTRACE
79*42922Smckusick 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
80*42922Smckusick 		ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt);
8137728Smckusick #endif
82*42922Smckusick 	*retval = cnt;
8337728Smckusick 	RETURN (error);
847820Sroot }
857820Sroot 
86*42922Smckusick /*
87*42922Smckusick  * Scatter read system call.
88*42922Smckusick  */
89*42922Smckusick readv(p, uap, retval)
90*42922Smckusick 	struct proc *p;
91*42922Smckusick 	register struct args {
927820Sroot 		int	fdes;
937820Sroot 		struct	iovec *iovp;
9426474Skarels 		unsigned iovcnt;
95*42922Smckusick 	} *uap;
96*42922Smckusick 	int *retval;
97*42922Smckusick {
9837728Smckusick 	register struct file *fp;
997820Sroot 	struct uio auio;
10037728Smckusick 	register struct iovec *iov;
10137728Smckusick 	struct iovec aiov[UIO_SMALLIOV];
10237728Smckusick 	long i, cnt, error = 0;
10337728Smckusick #ifdef KTRACE
10437728Smckusick 	struct iovec *ktriov = NULL;
10537728Smckusick #endif
1067820Sroot 
10737728Smckusick 	if (((unsigned)uap->fdes) >= NOFILE ||
10837728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
10937728Smckusick 	    (fp->f_flag & FREAD) == 0)
11037728Smckusick 		RETURN (EBADF);
11137127Skarels 	if (uap->iovcnt > UIO_SMALLIOV) {
11237728Smckusick 		if (uap->iovcnt > UIO_MAXIOV)
11337728Smckusick 			RETURN (EINVAL);
11437127Skarels 		MALLOC(iov, struct iovec *,
11537127Skarels 		      sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
11637127Skarels 	} else
11737127Skarels 		iov = aiov;
11837127Skarels 	auio.uio_iov = iov;
1197820Sroot 	auio.uio_iovcnt = uap->iovcnt;
12037728Smckusick 	auio.uio_rw = UIO_READ;
12137728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
12237728Smckusick 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
12337728Smckusick 	    uap->iovcnt * sizeof (struct iovec)))
12437127Skarels 		goto done;
12537728Smckusick 	auio.uio_resid = 0;
12637728Smckusick 	for (i = 0; i < uap->iovcnt; i++) {
12737728Smckusick 		if (iov->iov_len < 0) {
12837728Smckusick 			error = EINVAL;
12937728Smckusick 			goto done;
13037728Smckusick 		}
13137728Smckusick 		auio.uio_resid += iov->iov_len;
13237728Smckusick 		if (auio.uio_resid < 0) {
13337728Smckusick 			error = EINVAL;
13437728Smckusick 			goto done;
13537728Smckusick 		}
13637728Smckusick 		iov++;
13737728Smckusick 	}
13837728Smckusick #ifdef KTRACE
13937728Smckusick 	/*
14037728Smckusick 	 * if tracing, save a copy of iovec
14137728Smckusick 	 */
142*42922Smckusick 	if (KTRPOINT(p, KTR_GENIO))  {
14341990Smckusick 		unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec);
14437728Smckusick 
14537728Smckusick 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
14637728Smckusick 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
14737728Smckusick 	}
14837728Smckusick #endif
14937728Smckusick 	cnt = auio.uio_resid;
15040703Skarels 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
15140703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
15240703Skarels 		    error == EINTR || error == EWOULDBLOCK))
15340703Skarels 			error = 0;
15437728Smckusick 	cnt -= auio.uio_resid;
15537728Smckusick #ifdef KTRACE
15637728Smckusick 	if (ktriov != NULL) {
15741178Smarc 		if (error == 0)
158*42922Smckusick 			ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, cnt);
15937728Smckusick 		FREE(ktriov, M_TEMP);
16037728Smckusick 	}
16137728Smckusick #endif
162*42922Smckusick 	*retval = cnt;
16337127Skarels done:
16437728Smckusick 	if (uap->iovcnt > UIO_SMALLIOV)
16537127Skarels 		FREE(iov, M_IOV);
16637728Smckusick 	RETURN (error);
1677423Sroot }
1687423Sroot 
1697423Sroot /*
1707423Sroot  * Write system call
1717423Sroot  */
172*42922Smckusick write(p, uap, retval)
173*42922Smckusick 	struct proc *p;
174*42922Smckusick 	register struct args {
1757423Sroot 		int	fdes;
1767423Sroot 		char	*cbuf;
17726474Skarels 		unsigned count;
178*42922Smckusick 	} *uap;
179*42922Smckusick 	int *retval;
180*42922Smckusick {
18137728Smckusick 	register struct file *fp;
1827820Sroot 	struct uio auio;
1837820Sroot 	struct iovec aiov;
18437728Smckusick 	long cnt, error = 0;
18537728Smckusick #ifdef KTRACE
18637728Smckusick 	struct iovec ktriov;
18737728Smckusick #endif
1887423Sroot 
18937728Smckusick 	if (((unsigned)uap->fdes) >= NOFILE ||
19037728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
19137728Smckusick 	    (fp->f_flag & FWRITE) == 0)
19237728Smckusick 		RETURN (EBADF);
19337728Smckusick 	aiov.iov_base = (caddr_t)uap->cbuf;
19437728Smckusick 	aiov.iov_len = uap->count;
1957820Sroot 	auio.uio_iov = &aiov;
1967820Sroot 	auio.uio_iovcnt = 1;
19737728Smckusick 	auio.uio_resid = uap->count;
19837728Smckusick 	auio.uio_rw = UIO_WRITE;
19937728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
20037728Smckusick #ifdef KTRACE
20137728Smckusick 	/*
20237728Smckusick 	 * if tracing, save a copy of iovec
20337728Smckusick 	 */
204*42922Smckusick 	if (KTRPOINT(p, KTR_GENIO))
20537728Smckusick 		ktriov = aiov;
20637728Smckusick #endif
20737728Smckusick 	cnt = uap->count;
20840703Skarels 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
20940703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
21040703Skarels 		    error == EINTR || error == EWOULDBLOCK))
21140703Skarels 			error = 0;
21240703Skarels 		if (error == EPIPE)
213*42922Smckusick 			psignal(p, SIGPIPE);
21440703Skarels 	}
21537728Smckusick 	cnt -= auio.uio_resid;
21637728Smckusick #ifdef KTRACE
217*42922Smckusick 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
218*42922Smckusick 		ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
21938591Smarc 		    &ktriov, cnt);
22037728Smckusick #endif
221*42922Smckusick 	*retval = cnt;
22237728Smckusick 	RETURN (error);
2237820Sroot }
2247820Sroot 
225*42922Smckusick /*
226*42922Smckusick  * Gather write system call
227*42922Smckusick  */
228*42922Smckusick writev(p, uap, retval)
229*42922Smckusick 	struct proc *p;
230*42922Smckusick 	register struct args {
2317820Sroot 		int	fdes;
2327820Sroot 		struct	iovec *iovp;
23326474Skarels 		unsigned iovcnt;
234*42922Smckusick 	} *uap;
235*42922Smckusick 	int *retval;
236*42922Smckusick {
23737728Smckusick 	register struct file *fp;
2387820Sroot 	struct uio auio;
23937728Smckusick 	register struct iovec *iov;
24037728Smckusick 	struct iovec aiov[UIO_SMALLIOV];
24137728Smckusick 	long i, cnt, error = 0;
24237728Smckusick #ifdef KTRACE
24337728Smckusick 	struct iovec *ktriov = NULL;
24437728Smckusick #endif
2457820Sroot 
24637728Smckusick 	if (((unsigned)uap->fdes) >= NOFILE ||
24737728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL ||
24837728Smckusick 	    (fp->f_flag & FWRITE) == 0)
24937728Smckusick 		RETURN (EBADF);
25037127Skarels 	if (uap->iovcnt > UIO_SMALLIOV) {
25137728Smckusick 		if (uap->iovcnt > UIO_MAXIOV)
25237728Smckusick 			RETURN (EINVAL);
25337127Skarels 		MALLOC(iov, struct iovec *,
25437127Skarels 		      sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
25537127Skarels 	} else
25637127Skarels 		iov = aiov;
25737127Skarels 	auio.uio_iov = iov;
2587820Sroot 	auio.uio_iovcnt = uap->iovcnt;
25937728Smckusick 	auio.uio_rw = UIO_WRITE;
26037728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
26137728Smckusick 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
26237728Smckusick 	    uap->iovcnt * sizeof (struct iovec)))
26337127Skarels 		goto done;
26437728Smckusick 	auio.uio_resid = 0;
26537728Smckusick 	for (i = 0; i < uap->iovcnt; i++) {
2667820Sroot 		if (iov->iov_len < 0) {
26737728Smckusick 			error = EINVAL;
26837728Smckusick 			goto done;
2697820Sroot 		}
27037728Smckusick 		auio.uio_resid += iov->iov_len;
27137728Smckusick 		if (auio.uio_resid < 0) {
27237728Smckusick 			error = EINVAL;
27337728Smckusick 			goto done;
2747820Sroot 		}
27513270Ssam 		iov++;
2767820Sroot 	}
27737127Skarels #ifdef KTRACE
27837728Smckusick 	/*
27937728Smckusick 	 * if tracing, save a copy of iovec
28037728Smckusick 	 */
281*42922Smckusick 	if (KTRPOINT(p, KTR_GENIO))  {
28241990Smckusick 		unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec);
28337127Skarels 
28437127Skarels 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
28537728Smckusick 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
28637127Skarels 	}
28737127Skarels #endif
28837728Smckusick 	cnt = auio.uio_resid;
28940703Skarels 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
29040703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
29140703Skarels 		    error == EINTR || error == EWOULDBLOCK))
29240703Skarels 			error = 0;
29340703Skarels 		if (error == EPIPE)
294*42922Smckusick 			psignal(p, SIGPIPE);
29540703Skarels 	}
29637728Smckusick 	cnt -= auio.uio_resid;
29737127Skarels #ifdef KTRACE
29837127Skarels 	if (ktriov != NULL) {
29941178Smarc 		if (error == 0)
300*42922Smckusick 			ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
30141178Smarc 				ktriov, cnt);
30237127Skarels 		FREE(ktriov, M_TEMP);
30337127Skarels 	}
30437127Skarels #endif
305*42922Smckusick 	*retval = cnt;
30637728Smckusick done:
30737728Smckusick 	if (uap->iovcnt > UIO_SMALLIOV)
30837728Smckusick 		FREE(iov, M_IOV);
30937728Smckusick 	RETURN (error);
3107423Sroot }
3117423Sroot 
3127423Sroot /*
3137423Sroot  * Ioctl system call
3147423Sroot  */
315*42922Smckusick /* ARGSUSED */
316*42922Smckusick ioctl(p, uap, retval)
317*42922Smckusick 	struct proc *p;
318*42922Smckusick 	register struct args {
3197423Sroot 		int	fdes;
3207423Sroot 		int	cmd;
3217423Sroot 		caddr_t	cmarg;
322*42922Smckusick 	} *uap;
323*42922Smckusick 	int *retval;
324*42922Smckusick {
325*42922Smckusick 	register struct file *fp;
32640703Skarels 	register int com, error;
3277820Sroot 	register u_int size;
32831653Smckusick 	caddr_t memp = 0;
32930530Skarels #define STK_PARAMS	128
33033480Skarels 	char stkbuf[STK_PARAMS];
33133480Skarels 	caddr_t data = stkbuf;
3327423Sroot 
33337728Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
33437728Smckusick 	    (fp = u.u_ofile[uap->fdes]) == NULL)
33537728Smckusick 		RETURN (EBADF);
33640703Skarels 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
33740703Skarels 		RETURN (EBADF);
3387624Ssam 	com = uap->cmd;
3397624Ssam 
3407624Ssam 	if (com == FIOCLEX) {
3419592Ssam 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
3427423Sroot 		return;
3437423Sroot 	}
3447624Ssam 	if (com == FIONCLEX) {
3459592Ssam 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
34640703Skarels 		RETURN (0);
3477423Sroot 	}
3487624Ssam 
3497624Ssam 	/*
3507624Ssam 	 * Interpret high order word to find
3517624Ssam 	 * amount of data to be copied to/from the
3527624Ssam 	 * user's address space.
3537624Ssam 	 */
35430530Skarels 	size = IOCPARM_LEN(com);
35540703Skarels 	if (size > IOCPARM_MAX)
35640703Skarels 		RETURN (ENOTTY);
35733480Skarels 	if (size > sizeof (stkbuf)) {
35837127Skarels 		memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS,
35934473Smckusick 		    M_WAITOK);
36031653Smckusick 		data = memp;
36130530Skarels 	}
36210601Ssam 	if (com&IOC_IN) {
36310601Ssam 		if (size) {
36440703Skarels 			error = copyin(uap->cmarg, data, (u_int)size);
36540703Skarels 			if (error) {
36631653Smckusick 				if (memp)
36731653Smckusick 					free(memp, M_IOCTLOPS);
36840703Skarels 				RETURN (error);
36931653Smckusick 			}
37010601Ssam 		} else
37110601Ssam 			*(caddr_t *)data = uap->cmarg;
37210601Ssam 	} else if ((com&IOC_OUT) && size)
37310601Ssam 		/*
37437127Skarels 		 * Zero the buffer so the user always
37537127Skarels 		 * gets back something deterministic.
37610601Ssam 		 */
37730530Skarels 		bzero(data, size);
37811284Ssam 	else if (com&IOC_VOID)
37911284Ssam 		*(caddr_t *)data = uap->cmarg;
3807423Sroot 
38112751Ssam 	switch (com) {
3827624Ssam 
38312751Ssam 	case FIONBIO:
38440703Skarels 		error = fset(fp, FNDELAY, *(int *)data);
38530530Skarels 		break;
38612751Ssam 
38712751Ssam 	case FIOASYNC:
38840703Skarels 		error = fset(fp, FASYNC, *(int *)data);
38930530Skarels 		break;
39012751Ssam 
39112751Ssam 	case FIOSETOWN:
39240703Skarels 		error = fsetown(fp, *(int *)data);
39330530Skarels 		break;
39412751Ssam 
39512751Ssam 	case FIOGETOWN:
39640703Skarels 		error = fgetown(fp, (int *)data);
39730530Skarels 		break;
39830530Skarels 	default:
39940703Skarels 		error = (*fp->f_ops->fo_ioctl)(fp, com, data);
40030530Skarels 		/*
40130530Skarels 		 * Copy any data to user, size was
40230530Skarels 		 * already set and checked above.
40330530Skarels 		 */
40440703Skarels 		if (error == 0 && (com&IOC_OUT) && size)
40540703Skarels 			error = copyout(data, uap->cmarg, (u_int)size);
40630530Skarels 		break;
4077423Sroot 	}
40831653Smckusick 	if (memp)
40931653Smckusick 		free(memp, M_IOCTLOPS);
41040703Skarels 	RETURN (error);
4117423Sroot }
4127423Sroot 
41312751Ssam int	nselcoll;
41417593Skarels 
4157423Sroot /*
41612751Ssam  * Select system call.
4177423Sroot  */
418*42922Smckusick select(p, uap, retval)
419*42922Smckusick 	register struct proc *p;
420*42922Smckusick 	register struct args {
42112751Ssam 		int	nd;
42223523Skarels 		fd_set	*in, *ou, *ex;
42312751Ssam 		struct	timeval *tv;
424*42922Smckusick 	} *uap;
425*42922Smckusick 	int *retval;
426*42922Smckusick {
42723523Skarels 	fd_set ibits[3], obits[3];
42812751Ssam 	struct timeval atv;
42940703Skarels 	int s, ncoll, ni, error = 0, timo;
43012751Ssam 
43126277Skarels 	bzero((caddr_t)ibits, sizeof(ibits));
43226277Skarels 	bzero((caddr_t)obits, sizeof(obits));
43312751Ssam 	if (uap->nd > NOFILE)
43412751Ssam 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
43523523Skarels 	ni = howmany(uap->nd, NFDBITS);
43612751Ssam 
43712751Ssam #define	getbits(name, x) \
43812751Ssam 	if (uap->name) { \
43940703Skarels 		error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
44026277Skarels 		    (unsigned)(ni * sizeof(fd_mask))); \
44140703Skarels 		if (error) \
44212751Ssam 			goto done; \
44317593Skarels 	}
44412751Ssam 	getbits(in, 0);
44512751Ssam 	getbits(ou, 1);
44612751Ssam 	getbits(ex, 2);
44712751Ssam #undef	getbits
44812751Ssam 
44912751Ssam 	if (uap->tv) {
45040703Skarels 		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
45112751Ssam 			sizeof (atv));
45240703Skarels 		if (error)
45312751Ssam 			goto done;
45412751Ssam 		if (itimerfix(&atv)) {
45540703Skarels 			error = EINVAL;
45612751Ssam 			goto done;
45712751Ssam 		}
45817934Skarels 		s = splhigh(); timevaladd(&atv, &time); splx(s);
45940703Skarels 		timo = hzto(&atv);
46040703Skarels 	} else
46140703Skarels 		timo = 0;
46212751Ssam retry:
46312751Ssam 	ncoll = nselcoll;
464*42922Smckusick 	p->p_flag |= SSEL;
465*42922Smckusick 	error = selscan(ibits, obits, uap->nd, retval);
46640703Skarels 	if (error == 0)
46740703Skarels 		error = u.u_error;		/* XXX */
468*42922Smckusick 	if (error || *retval)
46912751Ssam 		goto done;
47017934Skarels 	s = splhigh();
47112971Ssam 	/* this should be timercmp(&time, &atv, >=) */
47212971Ssam 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
47312971Ssam 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
47412751Ssam 		splx(s);
47512751Ssam 		goto done;
47612751Ssam 	}
477*42922Smckusick 	if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
47812751Ssam 		splx(s);
47912751Ssam 		goto retry;
48012751Ssam 	}
481*42922Smckusick 	p->p_flag &= ~SSEL;
48240703Skarels 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
48312751Ssam 	splx(s);
48440703Skarels 	if (error == 0)
48540703Skarels 		goto retry;
48612751Ssam done:
487*42922Smckusick 	p->p_flag &= ~SSEL;
48840703Skarels 	/* select is not restarted after signals... */
48940703Skarels 	if (error == ERESTART)
49040703Skarels 		error = EINTR;
49140703Skarels 	if (error == EWOULDBLOCK)
49240703Skarels 		error = 0;
49312751Ssam #define	putbits(name, x) \
49412751Ssam 	if (uap->name) { \
49540703Skarels 		int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
49626277Skarels 		    (unsigned)(ni * sizeof(fd_mask))); \
49740703Skarels 		if (error2) \
49840703Skarels 			error = error2; \
49912751Ssam 	}
50040703Skarels 	if (error == 0) {
50121106Skarels 		putbits(in, 0);
50221106Skarels 		putbits(ou, 1);
50321106Skarels 		putbits(ex, 2);
50412751Ssam #undef putbits
50521106Skarels 	}
50640703Skarels 	RETURN (error);
50712751Ssam }
50812751Ssam 
509*42922Smckusick selscan(ibits, obits, nfd, retval)
51023523Skarels 	fd_set *ibits, *obits;
511*42922Smckusick 	int nfd, *retval;
51212751Ssam {
51323523Skarels 	register int which, i, j;
51423523Skarels 	register fd_mask bits;
51512751Ssam 	int flag;
51612751Ssam 	struct file *fp;
517*42922Smckusick 	int error = 0, n = 0;
51812751Ssam 
51912751Ssam 	for (which = 0; which < 3; which++) {
52012751Ssam 		switch (which) {
52112751Ssam 
52212751Ssam 		case 0:
52312751Ssam 			flag = FREAD; break;
52412751Ssam 
52512751Ssam 		case 1:
52612751Ssam 			flag = FWRITE; break;
52712751Ssam 
52812751Ssam 		case 2:
52912751Ssam 			flag = 0; break;
53012751Ssam 		}
53123523Skarels 		for (i = 0; i < nfd; i += NFDBITS) {
53223523Skarels 			bits = ibits[which].fds_bits[i/NFDBITS];
53317593Skarels 			while ((j = ffs(bits)) && i + --j < nfd) {
53417593Skarels 				bits &= ~(1 << j);
53517593Skarels 				fp = u.u_ofile[i + j];
53617593Skarels 				if (fp == NULL) {
537*42922Smckusick 					error = EBADF;
53817593Skarels 					break;
53917593Skarels 				}
54017593Skarels 				if ((*fp->f_ops->fo_select)(fp, flag)) {
54123523Skarels 					FD_SET(i + j, &obits[which]);
54217593Skarels 					n++;
54317593Skarels 				}
54412751Ssam 			}
54512751Ssam 		}
54612751Ssam 	}
547*42922Smckusick 	*retval = n;
548*42922Smckusick 	return (error);
54912751Ssam }
55012751Ssam 
5517423Sroot /*ARGSUSED*/
55212751Ssam seltrue(dev, flag)
55312751Ssam 	dev_t dev;
55412751Ssam 	int flag;
5557423Sroot {
5567423Sroot 
55712751Ssam 	return (1);
5587423Sroot }
5598103Sroot 
56012751Ssam selwakeup(p, coll)
56112751Ssam 	register struct proc *p;
56212751Ssam 	int coll;
5638103Sroot {
5648103Sroot 
56512751Ssam 	if (coll) {
56612751Ssam 		nselcoll++;
56712751Ssam 		wakeup((caddr_t)&selwait);
56812751Ssam 	}
56912751Ssam 	if (p) {
57017934Skarels 		int s = splhigh();
57117270Skarels 		if (p->p_wchan == (caddr_t)&selwait) {
57217270Skarels 			if (p->p_stat == SSLEEP)
57317270Skarels 				setrun(p);
57417270Skarels 			else
57517270Skarels 				unsleep(p);
57617270Skarels 		} else if (p->p_flag & SSEL)
57712751Ssam 			p->p_flag &= ~SSEL;
57812751Ssam 		splx(s);
57912751Ssam 	}
5808103Sroot }
581