xref: /csrg-svn/sys/kern/sys_generic.c (revision 47974)
123384Smckusick /*
237728Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
337728Smckusick  * All rights reserved.
423384Smckusick  *
544444Sbostic  * %sccs.include.redist.c%
637728Smckusick  *
7*47974Skarels  *	@(#)sys_generic.c	7.27 (Berkeley) 04/12/91
823384Smckusick  */
97423Sroot 
1017094Sbloom #include "param.h"
1117094Sbloom #include "systm.h"
1245914Smckusick #include "filedesc.h"
1317094Sbloom #include "ioctl.h"
1417094Sbloom #include "file.h"
1517094Sbloom #include "proc.h"
1617094Sbloom #include "uio.h"
1717094Sbloom #include "kernel.h"
1817094Sbloom #include "stat.h"
1931653Smckusick #include "malloc.h"
2037127Skarels #ifdef KTRACE
2137127Skarels #include "ktrace.h"
2237127Skarels #endif
237423Sroot 
247423Sroot /*
257423Sroot  * Read system call.
267423Sroot  */
2745122Sbostic /* ARGSUSED */
2842922Smckusick read(p, uap, retval)
2942922Smckusick 	struct proc *p;
3042922Smckusick 	register struct args {
317423Sroot 		int	fdes;
327423Sroot 		char	*cbuf;
337423Sroot 		unsigned count;
3442922Smckusick 	} *uap;
3542922Smckusick 	int *retval;
3642922Smckusick {
3737728Smckusick 	register struct file *fp;
3845914Smckusick 	register struct filedesc *fdp = p->p_fd;
397746Sroot 	struct uio auio;
407746Sroot 	struct iovec aiov;
4137728Smckusick 	long cnt, error = 0;
4237728Smckusick #ifdef KTRACE
4337728Smckusick 	struct iovec ktriov;
4437728Smckusick #endif
457423Sroot 
4647540Skarels 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
47*47974Skarels 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
4837728Smckusick 	    (fp->f_flag & FREAD) == 0)
4944405Skarels 		return (EBADF);
507820Sroot 	aiov.iov_base = (caddr_t)uap->cbuf;
517820Sroot 	aiov.iov_len = uap->count;
527820Sroot 	auio.uio_iov = &aiov;
537820Sroot 	auio.uio_iovcnt = 1;
5437728Smckusick 	auio.uio_resid = uap->count;
5537728Smckusick 	auio.uio_rw = UIO_READ;
5637728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
5737728Smckusick #ifdef KTRACE
5837728Smckusick 	/*
5937728Smckusick 	 * if tracing, save a copy of iovec
6037728Smckusick 	 */
6142922Smckusick 	if (KTRPOINT(p, KTR_GENIO))
6237728Smckusick 		ktriov = aiov;
6337728Smckusick #endif
6437728Smckusick 	cnt = uap->count;
6540703Skarels 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
6640703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
6740703Skarels 		    error == EINTR || error == EWOULDBLOCK))
6840703Skarels 			error = 0;
6937728Smckusick 	cnt -= auio.uio_resid;
7037728Smckusick #ifdef KTRACE
7142922Smckusick 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
7243448Smckusick 		ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
7337728Smckusick #endif
7442922Smckusick 	*retval = cnt;
7544405Skarels 	return (error);
767820Sroot }
777820Sroot 
7842922Smckusick /*
7942922Smckusick  * Scatter read system call.
8042922Smckusick  */
8145122Sbostic /* ARGSUSED */
8242922Smckusick readv(p, uap, retval)
8342922Smckusick 	struct proc *p;
8442922Smckusick 	register struct args {
857820Sroot 		int	fdes;
867820Sroot 		struct	iovec *iovp;
8726474Skarels 		unsigned iovcnt;
8842922Smckusick 	} *uap;
8942922Smckusick 	int *retval;
9042922Smckusick {
9137728Smckusick 	register struct file *fp;
9245914Smckusick 	register struct filedesc *fdp = p->p_fd;
937820Sroot 	struct uio auio;
9437728Smckusick 	register struct iovec *iov;
9544939Skarels 	struct iovec *saveiov;
9637728Smckusick 	struct iovec aiov[UIO_SMALLIOV];
9737728Smckusick 	long i, cnt, error = 0;
9844939Skarels 	unsigned iovlen;
9937728Smckusick #ifdef KTRACE
10037728Smckusick 	struct iovec *ktriov = NULL;
10137728Smckusick #endif
1027820Sroot 
10347540Skarels 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
104*47974Skarels 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
10537728Smckusick 	    (fp->f_flag & FREAD) == 0)
10644405Skarels 		return (EBADF);
10744939Skarels 	/* note: can't use iovlen until iovcnt is validated */
10844939Skarels 	iovlen = uap->iovcnt * sizeof (struct iovec);
10937127Skarels 	if (uap->iovcnt > UIO_SMALLIOV) {
11037728Smckusick 		if (uap->iovcnt > UIO_MAXIOV)
11144405Skarels 			return (EINVAL);
11244939Skarels 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
11344939Skarels 		saveiov = iov;
11437127Skarels 	} else
11537127Skarels 		iov = aiov;
11637127Skarels 	auio.uio_iov = iov;
1177820Sroot 	auio.uio_iovcnt = uap->iovcnt;
11837728Smckusick 	auio.uio_rw = UIO_READ;
11937728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
12044939Skarels 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
12137127Skarels 		goto done;
12237728Smckusick 	auio.uio_resid = 0;
12337728Smckusick 	for (i = 0; i < uap->iovcnt; i++) {
12437728Smckusick 		if (iov->iov_len < 0) {
12537728Smckusick 			error = EINVAL;
12637728Smckusick 			goto done;
12737728Smckusick 		}
12837728Smckusick 		auio.uio_resid += iov->iov_len;
12937728Smckusick 		if (auio.uio_resid < 0) {
13037728Smckusick 			error = EINVAL;
13137728Smckusick 			goto done;
13237728Smckusick 		}
13337728Smckusick 		iov++;
13437728Smckusick 	}
13537728Smckusick #ifdef KTRACE
13637728Smckusick 	/*
13737728Smckusick 	 * if tracing, save a copy of iovec
13837728Smckusick 	 */
13942922Smckusick 	if (KTRPOINT(p, KTR_GENIO))  {
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;
14540703Skarels 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
14640703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
14740703Skarels 		    error == EINTR || error == EWOULDBLOCK))
14840703Skarels 			error = 0;
14937728Smckusick 	cnt -= auio.uio_resid;
15037728Smckusick #ifdef KTRACE
15137728Smckusick 	if (ktriov != NULL) {
15241178Smarc 		if (error == 0)
15343448Smckusick 			ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
15443448Smckusick 			    cnt, error);
15537728Smckusick 		FREE(ktriov, M_TEMP);
15637728Smckusick 	}
15737728Smckusick #endif
15842922Smckusick 	*retval = cnt;
15937127Skarels done:
16037728Smckusick 	if (uap->iovcnt > UIO_SMALLIOV)
16144939Skarels 		FREE(saveiov, M_IOV);
16244405Skarels 	return (error);
1637423Sroot }
1647423Sroot 
1657423Sroot /*
1667423Sroot  * Write system call
1677423Sroot  */
16842922Smckusick write(p, uap, retval)
16942922Smckusick 	struct proc *p;
17042922Smckusick 	register struct args {
1717423Sroot 		int	fdes;
1727423Sroot 		char	*cbuf;
17326474Skarels 		unsigned count;
17442922Smckusick 	} *uap;
17542922Smckusick 	int *retval;
17642922Smckusick {
17737728Smckusick 	register struct file *fp;
17845914Smckusick 	register struct filedesc *fdp = p->p_fd;
1797820Sroot 	struct uio auio;
1807820Sroot 	struct iovec aiov;
18137728Smckusick 	long cnt, error = 0;
18237728Smckusick #ifdef KTRACE
18337728Smckusick 	struct iovec ktriov;
18437728Smckusick #endif
1857423Sroot 
18647540Skarels 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
187*47974Skarels 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
18837728Smckusick 	    (fp->f_flag & FWRITE) == 0)
18944405Skarels 		return (EBADF);
19037728Smckusick 	aiov.iov_base = (caddr_t)uap->cbuf;
19137728Smckusick 	aiov.iov_len = uap->count;
1927820Sroot 	auio.uio_iov = &aiov;
1937820Sroot 	auio.uio_iovcnt = 1;
19437728Smckusick 	auio.uio_resid = uap->count;
19537728Smckusick 	auio.uio_rw = UIO_WRITE;
19637728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
19737728Smckusick #ifdef KTRACE
19837728Smckusick 	/*
19937728Smckusick 	 * if tracing, save a copy of iovec
20037728Smckusick 	 */
20142922Smckusick 	if (KTRPOINT(p, KTR_GENIO))
20237728Smckusick 		ktriov = aiov;
20337728Smckusick #endif
20437728Smckusick 	cnt = uap->count;
20540703Skarels 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
20640703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
20740703Skarels 		    error == EINTR || error == EWOULDBLOCK))
20840703Skarels 			error = 0;
20940703Skarels 		if (error == EPIPE)
21042922Smckusick 			psignal(p, SIGPIPE);
21140703Skarels 	}
21237728Smckusick 	cnt -= auio.uio_resid;
21337728Smckusick #ifdef KTRACE
21442922Smckusick 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
21542922Smckusick 		ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
21643448Smckusick 		    &ktriov, cnt, error);
21737728Smckusick #endif
21842922Smckusick 	*retval = cnt;
21944405Skarels 	return (error);
2207820Sroot }
2217820Sroot 
22242922Smckusick /*
22342922Smckusick  * Gather write system call
22442922Smckusick  */
22542922Smckusick writev(p, uap, retval)
22642922Smckusick 	struct proc *p;
22742922Smckusick 	register struct args {
2287820Sroot 		int	fdes;
2297820Sroot 		struct	iovec *iovp;
23026474Skarels 		unsigned iovcnt;
23142922Smckusick 	} *uap;
23242922Smckusick 	int *retval;
23342922Smckusick {
23437728Smckusick 	register struct file *fp;
23545914Smckusick 	register struct filedesc *fdp = p->p_fd;
2367820Sroot 	struct uio auio;
23737728Smckusick 	register struct iovec *iov;
23844939Skarels 	struct iovec *saveiov;
23937728Smckusick 	struct iovec aiov[UIO_SMALLIOV];
24037728Smckusick 	long i, cnt, error = 0;
24144939Skarels 	unsigned iovlen;
24237728Smckusick #ifdef KTRACE
24337728Smckusick 	struct iovec *ktriov = NULL;
24437728Smckusick #endif
2457820Sroot 
24647540Skarels 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
247*47974Skarels 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
24837728Smckusick 	    (fp->f_flag & FWRITE) == 0)
24944405Skarels 		return (EBADF);
25044939Skarels 	/* note: can't use iovlen until iovcnt is validated */
25144939Skarels 	iovlen = uap->iovcnt * sizeof (struct iovec);
25237127Skarels 	if (uap->iovcnt > UIO_SMALLIOV) {
25337728Smckusick 		if (uap->iovcnt > UIO_MAXIOV)
25444405Skarels 			return (EINVAL);
25544939Skarels 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
25644939Skarels 		saveiov = iov;
25737127Skarels 	} else
25837127Skarels 		iov = aiov;
25937127Skarels 	auio.uio_iov = iov;
2607820Sroot 	auio.uio_iovcnt = uap->iovcnt;
26137728Smckusick 	auio.uio_rw = UIO_WRITE;
26237728Smckusick 	auio.uio_segflg = UIO_USERSPACE;
26344939Skarels 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
26437127Skarels 		goto done;
26537728Smckusick 	auio.uio_resid = 0;
26637728Smckusick 	for (i = 0; i < uap->iovcnt; i++) {
2677820Sroot 		if (iov->iov_len < 0) {
26837728Smckusick 			error = EINVAL;
26937728Smckusick 			goto done;
2707820Sroot 		}
27137728Smckusick 		auio.uio_resid += iov->iov_len;
27237728Smckusick 		if (auio.uio_resid < 0) {
27337728Smckusick 			error = EINVAL;
27437728Smckusick 			goto done;
2757820Sroot 		}
27613270Ssam 		iov++;
2777820Sroot 	}
27837127Skarels #ifdef KTRACE
27937728Smckusick 	/*
28037728Smckusick 	 * if tracing, save a copy of iovec
28137728Smckusick 	 */
28242922Smckusick 	if (KTRPOINT(p, KTR_GENIO))  {
28337127Skarels 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
28437728Smckusick 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
28537127Skarels 	}
28637127Skarels #endif
28737728Smckusick 	cnt = auio.uio_resid;
28840703Skarels 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
28940703Skarels 		if (auio.uio_resid != cnt && (error == ERESTART ||
29040703Skarels 		    error == EINTR || error == EWOULDBLOCK))
29140703Skarels 			error = 0;
29240703Skarels 		if (error == EPIPE)
29342922Smckusick 			psignal(p, SIGPIPE);
29440703Skarels 	}
29537728Smckusick 	cnt -= auio.uio_resid;
29637127Skarels #ifdef KTRACE
29737127Skarels 	if (ktriov != NULL) {
29841178Smarc 		if (error == 0)
29942922Smckusick 			ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
30043448Smckusick 				ktriov, cnt, error);
30137127Skarels 		FREE(ktriov, M_TEMP);
30237127Skarels 	}
30337127Skarels #endif
30442922Smckusick 	*retval = cnt;
30537728Smckusick done:
30637728Smckusick 	if (uap->iovcnt > UIO_SMALLIOV)
30744939Skarels 		FREE(saveiov, M_IOV);
30844405Skarels 	return (error);
3097423Sroot }
3107423Sroot 
3117423Sroot /*
3127423Sroot  * Ioctl system call
3137423Sroot  */
31442922Smckusick /* ARGSUSED */
31542922Smckusick ioctl(p, uap, retval)
31642922Smckusick 	struct proc *p;
31742922Smckusick 	register struct args {
3187423Sroot 		int	fdes;
3197423Sroot 		int	cmd;
3207423Sroot 		caddr_t	cmarg;
32142922Smckusick 	} *uap;
32242922Smckusick 	int *retval;
32342922Smckusick {
32442922Smckusick 	register struct file *fp;
32545914Smckusick 	register struct filedesc *fdp = p->p_fd;
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 
33347540Skarels 	if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
334*47974Skarels 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
33544405Skarels 		return (EBADF);
33640703Skarels 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
33744405Skarels 		return (EBADF);
3387624Ssam 	com = uap->cmd;
3397624Ssam 
3407624Ssam 	if (com == FIOCLEX) {
341*47974Skarels 		fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
34244405Skarels 		return (0);
3437423Sroot 	}
3447624Ssam 	if (com == FIONCLEX) {
345*47974Skarels 		fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
34644405Skarels 		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)
35644405Skarels 		return (ENOTTY);
35733480Skarels 	if (size > sizeof (stkbuf)) {
35843383Smckusick 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
35931653Smckusick 		data = memp;
36030530Skarels 	}
36110601Ssam 	if (com&IOC_IN) {
36210601Ssam 		if (size) {
36340703Skarels 			error = copyin(uap->cmarg, data, (u_int)size);
36440703Skarels 			if (error) {
36531653Smckusick 				if (memp)
36631653Smckusick 					free(memp, M_IOCTLOPS);
36744405Skarels 				return (error);
36831653Smckusick 			}
36910601Ssam 		} else
37010601Ssam 			*(caddr_t *)data = uap->cmarg;
37110601Ssam 	} else if ((com&IOC_OUT) && size)
37210601Ssam 		/*
37337127Skarels 		 * Zero the buffer so the user always
37437127Skarels 		 * gets back something deterministic.
37510601Ssam 		 */
37630530Skarels 		bzero(data, size);
37711284Ssam 	else if (com&IOC_VOID)
37811284Ssam 		*(caddr_t *)data = uap->cmarg;
3797423Sroot 
38012751Ssam 	switch (com) {
3817624Ssam 
38212751Ssam 	case FIONBIO:
38340703Skarels 		error = fset(fp, FNDELAY, *(int *)data);
38430530Skarels 		break;
38512751Ssam 
38612751Ssam 	case FIOASYNC:
38740703Skarels 		error = fset(fp, FASYNC, *(int *)data);
38830530Skarels 		break;
38912751Ssam 
39012751Ssam 	case FIOSETOWN:
39140703Skarels 		error = fsetown(fp, *(int *)data);
39230530Skarels 		break;
39312751Ssam 
39412751Ssam 	case FIOGETOWN:
39540703Skarels 		error = fgetown(fp, (int *)data);
39630530Skarels 		break;
39730530Skarels 	default:
39847540Skarels 		error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
39930530Skarels 		/*
40030530Skarels 		 * Copy any data to user, size was
40130530Skarels 		 * already set and checked above.
40230530Skarels 		 */
40340703Skarels 		if (error == 0 && (com&IOC_OUT) && size)
40440703Skarels 			error = copyout(data, uap->cmarg, (u_int)size);
40530530Skarels 		break;
4067423Sroot 	}
40731653Smckusick 	if (memp)
40831653Smckusick 		free(memp, M_IOCTLOPS);
40944405Skarels 	return (error);
4107423Sroot }
4117423Sroot 
41212751Ssam int	nselcoll;
41317593Skarels 
4147423Sroot /*
41512751Ssam  * Select system call.
4167423Sroot  */
41742922Smckusick select(p, uap, retval)
41842922Smckusick 	register struct proc *p;
41942922Smckusick 	register struct args {
42012751Ssam 		int	nd;
42123523Skarels 		fd_set	*in, *ou, *ex;
42212751Ssam 		struct	timeval *tv;
42342922Smckusick 	} *uap;
42442922Smckusick 	int *retval;
42542922Smckusick {
42623523Skarels 	fd_set ibits[3], obits[3];
42712751Ssam 	struct timeval atv;
42840703Skarels 	int s, ncoll, ni, error = 0, timo;
42912751Ssam 
43026277Skarels 	bzero((caddr_t)ibits, sizeof(ibits));
43126277Skarels 	bzero((caddr_t)obits, sizeof(obits));
43247540Skarels 	if (uap->nd > p->p_fd->fd_nfiles)
43347540Skarels 		uap->nd = p->p_fd->fd_nfiles;	/* forgiving; slightly wrong */
43423523Skarels 	ni = howmany(uap->nd, NFDBITS);
43512751Ssam 
43612751Ssam #define	getbits(name, x) \
43712751Ssam 	if (uap->name) { \
43840703Skarels 		error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
43926277Skarels 		    (unsigned)(ni * sizeof(fd_mask))); \
44040703Skarels 		if (error) \
44112751Ssam 			goto done; \
44217593Skarels 	}
44312751Ssam 	getbits(in, 0);
44412751Ssam 	getbits(ou, 1);
44512751Ssam 	getbits(ex, 2);
44612751Ssam #undef	getbits
44712751Ssam 
44812751Ssam 	if (uap->tv) {
44940703Skarels 		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
45012751Ssam 			sizeof (atv));
45140703Skarels 		if (error)
45212751Ssam 			goto done;
45312751Ssam 		if (itimerfix(&atv)) {
45440703Skarels 			error = EINVAL;
45512751Ssam 			goto done;
45612751Ssam 		}
45717934Skarels 		s = splhigh(); timevaladd(&atv, &time); splx(s);
45840703Skarels 		timo = hzto(&atv);
45940703Skarels 	} else
46040703Skarels 		timo = 0;
46112751Ssam retry:
46212751Ssam 	ncoll = nselcoll;
46342922Smckusick 	p->p_flag |= SSEL;
46447540Skarels 	error = selscan(p, ibits, obits, uap->nd, retval);
46542922Smckusick 	if (error || *retval)
46612751Ssam 		goto done;
46717934Skarels 	s = splhigh();
46812971Ssam 	/* this should be timercmp(&time, &atv, >=) */
46912971Ssam 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
47012971Ssam 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
47112751Ssam 		splx(s);
47212751Ssam 		goto done;
47312751Ssam 	}
47442922Smckusick 	if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
47512751Ssam 		splx(s);
47612751Ssam 		goto retry;
47712751Ssam 	}
47842922Smckusick 	p->p_flag &= ~SSEL;
47940703Skarels 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
48012751Ssam 	splx(s);
48140703Skarels 	if (error == 0)
48240703Skarels 		goto retry;
48312751Ssam done:
48442922Smckusick 	p->p_flag &= ~SSEL;
48540703Skarels 	/* select is not restarted after signals... */
48640703Skarels 	if (error == ERESTART)
48740703Skarels 		error = EINTR;
48840703Skarels 	if (error == EWOULDBLOCK)
48940703Skarels 		error = 0;
49012751Ssam #define	putbits(name, x) \
49112751Ssam 	if (uap->name) { \
49240703Skarels 		int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
49326277Skarels 		    (unsigned)(ni * sizeof(fd_mask))); \
49440703Skarels 		if (error2) \
49540703Skarels 			error = error2; \
49612751Ssam 	}
49740703Skarels 	if (error == 0) {
49821106Skarels 		putbits(in, 0);
49921106Skarels 		putbits(ou, 1);
50021106Skarels 		putbits(ex, 2);
50112751Ssam #undef putbits
50221106Skarels 	}
50344405Skarels 	return (error);
50412751Ssam }
50512751Ssam 
50647540Skarels selscan(p, ibits, obits, nfd, retval)
50747540Skarels 	struct proc *p;
50823523Skarels 	fd_set *ibits, *obits;
50942922Smckusick 	int nfd, *retval;
51012751Ssam {
51147540Skarels 	register struct filedesc *fdp = p->p_fd;
51223523Skarels 	register int which, i, j;
51323523Skarels 	register fd_mask bits;
51412751Ssam 	int flag;
51512751Ssam 	struct file *fp;
51642922Smckusick 	int error = 0, n = 0;
51712751Ssam 
51812751Ssam 	for (which = 0; which < 3; which++) {
51912751Ssam 		switch (which) {
52012751Ssam 
52112751Ssam 		case 0:
52212751Ssam 			flag = FREAD; break;
52312751Ssam 
52412751Ssam 		case 1:
52512751Ssam 			flag = FWRITE; break;
52612751Ssam 
52712751Ssam 		case 2:
52812751Ssam 			flag = 0; break;
52912751Ssam 		}
53023523Skarels 		for (i = 0; i < nfd; i += NFDBITS) {
53123523Skarels 			bits = ibits[which].fds_bits[i/NFDBITS];
53217593Skarels 			while ((j = ffs(bits)) && i + --j < nfd) {
53317593Skarels 				bits &= ~(1 << j);
534*47974Skarels 				fp = fdp->fd_ofiles[i + j];
53517593Skarels 				if (fp == NULL) {
53642922Smckusick 					error = EBADF;
53717593Skarels 					break;
53817593Skarels 				}
53947540Skarels 				if ((*fp->f_ops->fo_select)(fp, flag, p)) {
54023523Skarels 					FD_SET(i + j, &obits[which]);
54117593Skarels 					n++;
54217593Skarels 				}
54312751Ssam 			}
54412751Ssam 		}
54512751Ssam 	}
54642922Smckusick 	*retval = n;
54742922Smckusick 	return (error);
54812751Ssam }
54912751Ssam 
5507423Sroot /*ARGSUSED*/
551*47974Skarels #ifdef __STDC__
552*47974Skarels seltrue(dev_t dev, int which, struct proc *p)
553*47974Skarels #else
55447540Skarels seltrue(dev, flag, p)
55512751Ssam 	dev_t dev;
55612751Ssam 	int flag;
55747540Skarels 	struct proc *p;
558*47974Skarels #endif
5597423Sroot {
5607423Sroot 
56112751Ssam 	return (1);
5627423Sroot }
5638103Sroot 
56412751Ssam selwakeup(p, coll)
56512751Ssam 	register struct proc *p;
56612751Ssam 	int coll;
5678103Sroot {
5688103Sroot 
56912751Ssam 	if (coll) {
57012751Ssam 		nselcoll++;
57112751Ssam 		wakeup((caddr_t)&selwait);
57212751Ssam 	}
57312751Ssam 	if (p) {
57417934Skarels 		int s = splhigh();
57517270Skarels 		if (p->p_wchan == (caddr_t)&selwait) {
57617270Skarels 			if (p->p_stat == SSLEEP)
57717270Skarels 				setrun(p);
57817270Skarels 			else
57917270Skarels 				unsleep(p);
58017270Skarels 		} else if (p->p_flag & SSEL)
58112751Ssam 			p->p_flag &= ~SSEL;
58212751Ssam 		splx(s);
58312751Ssam 	}
5848103Sroot }
585