xref: /csrg-svn/sys/kern/sys_generic.c (revision 21009)
1*21009Smckusick /*	sys_generic.c	6.9	85/05/22	*/
27423Sroot 
317094Sbloom #include "param.h"
417094Sbloom #include "systm.h"
517094Sbloom #include "dir.h"
617094Sbloom #include "user.h"
717094Sbloom #include "ioctl.h"
817094Sbloom #include "file.h"
917094Sbloom #include "proc.h"
1017094Sbloom #include "uio.h"
1117094Sbloom #include "kernel.h"
1217094Sbloom #include "stat.h"
137423Sroot 
147423Sroot /*
157423Sroot  * Read system call.
167423Sroot  */
177423Sroot read()
187423Sroot {
197423Sroot 	register struct a {
207423Sroot 		int	fdes;
217423Sroot 		char	*cbuf;
227423Sroot 		unsigned count;
237820Sroot 	} *uap = (struct a *)u.u_ap;
247746Sroot 	struct uio auio;
257746Sroot 	struct iovec aiov;
267423Sroot 
277820Sroot 	aiov.iov_base = (caddr_t)uap->cbuf;
287820Sroot 	aiov.iov_len = uap->count;
297820Sroot 	auio.uio_iov = &aiov;
307820Sroot 	auio.uio_iovcnt = 1;
317820Sroot 	rwuio(&auio, UIO_READ);
327820Sroot }
337820Sroot 
347820Sroot readv()
357820Sroot {
367820Sroot 	register struct a {
377820Sroot 		int	fdes;
387820Sroot 		struct	iovec *iovp;
397820Sroot 		int	iovcnt;
407820Sroot 	} *uap = (struct a *)u.u_ap;
417820Sroot 	struct uio auio;
427820Sroot 	struct iovec aiov[16];		/* XXX */
437820Sroot 
447820Sroot 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
457423Sroot 		u.u_error = EINVAL;
467423Sroot 		return;
477423Sroot 	}
487820Sroot 	auio.uio_iov = aiov;
497820Sroot 	auio.uio_iovcnt = uap->iovcnt;
509999Ssam 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
519999Ssam 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
529999Ssam 	if (u.u_error)
537423Sroot 		return;
547820Sroot 	rwuio(&auio, UIO_READ);
557423Sroot }
567423Sroot 
577423Sroot /*
587423Sroot  * Write system call
597423Sroot  */
607423Sroot write()
617423Sroot {
627423Sroot 	register struct a {
637423Sroot 		int	fdes;
647423Sroot 		char	*cbuf;
657820Sroot 		int	count;
667820Sroot 	} *uap = (struct a *)u.u_ap;
677820Sroot 	struct uio auio;
687820Sroot 	struct iovec aiov;
697423Sroot 
707820Sroot 	auio.uio_iov = &aiov;
717820Sroot 	auio.uio_iovcnt = 1;
727820Sroot 	aiov.iov_base = uap->cbuf;
737820Sroot 	aiov.iov_len = uap->count;
747820Sroot 	rwuio(&auio, UIO_WRITE);
757820Sroot }
767820Sroot 
777820Sroot writev()
787820Sroot {
797820Sroot 	register struct a {
807820Sroot 		int	fdes;
817820Sroot 		struct	iovec *iovp;
827820Sroot 		int	iovcnt;
837820Sroot 	} *uap = (struct a *)u.u_ap;
847820Sroot 	struct uio auio;
857820Sroot 	struct iovec aiov[16];		/* XXX */
867820Sroot 
877820Sroot 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
887423Sroot 		u.u_error = EINVAL;
897423Sroot 		return;
907423Sroot 	}
917820Sroot 	auio.uio_iov = aiov;
927820Sroot 	auio.uio_iovcnt = uap->iovcnt;
939999Ssam 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
949999Ssam 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
959999Ssam 	if (u.u_error)
967820Sroot 		return;
977820Sroot 	rwuio(&auio, UIO_WRITE);
987820Sroot }
997820Sroot 
1007820Sroot rwuio(uio, rw)
1017820Sroot 	register struct uio *uio;
1027820Sroot 	enum uio_rw rw;
1037820Sroot {
1047820Sroot 	struct a {
1057820Sroot 		int	fdes;
1067820Sroot 	};
1077820Sroot 	register struct file *fp;
1087820Sroot 	register struct iovec *iov;
1097820Sroot 	int i, count;
1107820Sroot 
1117820Sroot 	GETF(fp, ((struct a *)u.u_ap)->fdes);
1127820Sroot 	if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
1137423Sroot 		u.u_error = EBADF;
1147423Sroot 		return;
1157423Sroot 	}
1167820Sroot 	uio->uio_resid = 0;
11716702Smckusick 	uio->uio_segflg = UIO_USERSPACE;
1187820Sroot 	iov = uio->uio_iov;
1197820Sroot 	for (i = 0; i < uio->uio_iovcnt; i++) {
1207820Sroot 		if (iov->iov_len < 0) {
1217820Sroot 			u.u_error = EINVAL;
1227820Sroot 			return;
1237820Sroot 		}
1247820Sroot 		uio->uio_resid += iov->iov_len;
1257820Sroot 		if (uio->uio_resid < 0) {
1267820Sroot 			u.u_error = EINVAL;
1277820Sroot 			return;
1287820Sroot 		}
12913270Ssam 		iov++;
1307820Sroot 	}
1317820Sroot 	count = uio->uio_resid;
13212751Ssam 	uio->uio_offset = fp->f_offset;
13318309Smckusick 	if (setjmp(&u.u_qsave)) {
13418309Smckusick 		if (uio->uio_resid == count) {
135*21009Smckusick 			if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
13618309Smckusick 				u.u_error = EINTR;
13718309Smckusick 			else
13818309Smckusick 				u.u_eosys = RESTARTSYS;
13918309Smckusick 		}
14012751Ssam 	} else
14112751Ssam 		u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
1427820Sroot 	u.u_r.r_val1 = count - uio->uio_resid;
14312751Ssam 	fp->f_offset += u.u_r.r_val1;
1447423Sroot }
1457423Sroot 
1467423Sroot /*
1477423Sroot  * Ioctl system call
1487423Sroot  */
1497423Sroot ioctl()
1507423Sroot {
1517423Sroot 	register struct file *fp;
1527624Ssam 	struct a {
1537423Sroot 		int	fdes;
1547423Sroot 		int	cmd;
1557423Sroot 		caddr_t	cmarg;
1567423Sroot 	} *uap;
1577820Sroot 	register int com;
1587820Sroot 	register u_int size;
1597624Ssam 	char data[IOCPARM_MASK+1];
1607423Sroot 
1617423Sroot 	uap = (struct a *)u.u_ap;
16217004Smckusick 	GETF(fp, uap->fdes);
1637423Sroot 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
1647423Sroot 		u.u_error = EBADF;
1657423Sroot 		return;
1667423Sroot 	}
1677624Ssam 	com = uap->cmd;
1687624Ssam 
16913228Ssam #if defined(vax) && defined(COMPAT)
1707624Ssam 	/*
1717624Ssam 	 * Map old style ioctl's into new for the
1727624Ssam 	 * sake of backwards compatibility (sigh).
1737624Ssam 	 */
1747624Ssam 	if ((com&~0xffff) == 0) {
1757624Ssam 		com = mapioctl(com);
1767624Ssam 		if (com == 0) {
1777624Ssam 			u.u_error = EINVAL;
1787624Ssam 			return;
1797624Ssam 		}
1807624Ssam 	}
1817624Ssam #endif
1827624Ssam 	if (com == FIOCLEX) {
1839592Ssam 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
1847423Sroot 		return;
1857423Sroot 	}
1867624Ssam 	if (com == FIONCLEX) {
1879592Ssam 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
1887423Sroot 		return;
1897423Sroot 	}
1907624Ssam 
1917624Ssam 	/*
1927624Ssam 	 * Interpret high order word to find
1937624Ssam 	 * amount of data to be copied to/from the
1947624Ssam 	 * user's address space.
1957624Ssam 	 */
1967624Ssam 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
1977624Ssam 	if (size > sizeof (data)) {
1987624Ssam 		u.u_error = EFAULT;
1997423Sroot 		return;
2007423Sroot 	}
20110601Ssam 	if (com&IOC_IN) {
20210601Ssam 		if (size) {
20310601Ssam 			u.u_error =
20410601Ssam 			    copyin(uap->cmarg, (caddr_t)data, (u_int)size);
20510601Ssam 			if (u.u_error)
20610601Ssam 				return;
20710601Ssam 		} else
20810601Ssam 			*(caddr_t *)data = uap->cmarg;
20910601Ssam 	} else if ((com&IOC_OUT) && size)
21010601Ssam 		/*
21110601Ssam 		 * Zero the buffer on the stack so the user
21210601Ssam 		 * always gets back something deterministic.
21310601Ssam 		 */
2147624Ssam 		bzero((caddr_t)data, size);
21511284Ssam 	else if (com&IOC_VOID)
21611284Ssam 		*(caddr_t *)data = uap->cmarg;
2177423Sroot 
21812751Ssam 	switch (com) {
2197624Ssam 
22012751Ssam 	case FIONBIO:
22112751Ssam 		u.u_error = fset(fp, FNDELAY, *(int *)data);
22212751Ssam 		return;
22312751Ssam 
22412751Ssam 	case FIOASYNC:
22512751Ssam 		u.u_error = fset(fp, FASYNC, *(int *)data);
22612751Ssam 		return;
22712751Ssam 
22812751Ssam 	case FIOSETOWN:
22912751Ssam 		u.u_error = fsetown(fp, *(int *)data);
23012751Ssam 		return;
23112751Ssam 
23212751Ssam 	case FIOGETOWN:
23312751Ssam 		u.u_error = fgetown(fp, (int *)data);
23412751Ssam 		return;
2357423Sroot 	}
23612751Ssam 	u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data);
2377624Ssam 	/*
2387624Ssam 	 * Copy any data to user, size was
2397624Ssam 	 * already set and checked above.
2407624Ssam 	 */
2419999Ssam 	if (u.u_error == 0 && (com&IOC_OUT) && size)
2429999Ssam 		u.u_error = copyout(data, uap->cmarg, (u_int)size);
2437423Sroot }
2447423Sroot 
24512751Ssam int	unselect();
24612751Ssam int	nselcoll;
24717593Skarels 
2487423Sroot /*
24917593Skarels  * Select uses bit masks of file descriptors in ints.
25017593Skarels  * These macros manipulate such bit fields (the filesystem macros use chars).
25117593Skarels  */
25217593Skarels #define NBI		(sizeof(int) * NBBY)		/* bits per int */
25317593Skarels #define	NI		howmany(NOFILE, NBI)
25417593Skarels #define	tbit(p, n)	((p)[(n)/NBI] & (1 << ((n) % NBI)))
25517593Skarels #define	sbit(p, n)	((p)[(n)/NBI] |= (1 << ((n) % NBI)))
25617593Skarels #define	cbit(p, n)	((p)[(n)/NBI] &= ~(1 << ((n) % NBI)))
25717593Skarels 
25817593Skarels /*
25912751Ssam  * Select system call.
2607423Sroot  */
26112751Ssam select()
26212751Ssam {
26312751Ssam 	register struct uap  {
26412751Ssam 		int	nd;
26517593Skarels 		int	*in, *ou, *ex;
26612751Ssam 		struct	timeval *tv;
26712751Ssam 	} *uap = (struct uap *)u.u_ap;
26817593Skarels 	int ibits[3][NI], obits[3][NI];
26912751Ssam 	struct timeval atv;
27017593Skarels 	int s, ncoll, ni;
27112751Ssam 	label_t lqsave;
27212751Ssam 
27317593Skarels 	bzero(ibits, sizeof(ibits));
27417593Skarels 	bzero(obits, sizeof(obits));
27512751Ssam 	if (uap->nd > NOFILE)
27612751Ssam 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
27717593Skarels 	ni = howmany(uap->nd, NBI);
27812751Ssam 
27912751Ssam #define	getbits(name, x) \
28012751Ssam 	if (uap->name) { \
28117593Skarels 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)ibits[x], \
28217593Skarels 		    ni * sizeof(int)); \
28312751Ssam 		if (u.u_error) \
28412751Ssam 			goto done; \
28517593Skarels 	}
28612751Ssam 	getbits(in, 0);
28712751Ssam 	getbits(ou, 1);
28812751Ssam 	getbits(ex, 2);
28912751Ssam #undef	getbits
29012751Ssam 
29112751Ssam 	if (uap->tv) {
29212751Ssam 		u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
29312751Ssam 			sizeof (atv));
29412751Ssam 		if (u.u_error)
29512751Ssam 			goto done;
29612751Ssam 		if (itimerfix(&atv)) {
29712751Ssam 			u.u_error = EINVAL;
29812751Ssam 			goto done;
29912751Ssam 		}
30017934Skarels 		s = splhigh(); timevaladd(&atv, &time); splx(s);
30112751Ssam 	}
30212751Ssam retry:
30312751Ssam 	ncoll = nselcoll;
30412751Ssam 	u.u_procp->p_flag |= SSEL;
30517593Skarels 	u.u_r.r_val1 = selscan(ibits, obits, uap->nd);
30612751Ssam 	if (u.u_error || u.u_r.r_val1)
30712751Ssam 		goto done;
30817934Skarels 	s = splhigh();
30912971Ssam 	/* this should be timercmp(&time, &atv, >=) */
31012971Ssam 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
31112971Ssam 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
31212751Ssam 		splx(s);
31312751Ssam 		goto done;
31412751Ssam 	}
31512751Ssam 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
31612751Ssam 		u.u_procp->p_flag &= ~SSEL;
31712751Ssam 		splx(s);
31812751Ssam 		goto retry;
31912751Ssam 	}
32012751Ssam 	u.u_procp->p_flag &= ~SSEL;
32112751Ssam 	if (uap->tv) {
32212751Ssam 		lqsave = u.u_qsave;
32312751Ssam 		if (setjmp(&u.u_qsave)) {
32412751Ssam 			untimeout(unselect, (caddr_t)u.u_procp);
32512751Ssam 			u.u_error = EINTR;
32612751Ssam 			splx(s);
32712751Ssam 			goto done;
32812751Ssam 		}
32912751Ssam 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
33012751Ssam 	}
33112751Ssam 	sleep((caddr_t)&selwait, PZERO+1);
33212751Ssam 	if (uap->tv) {
33312751Ssam 		u.u_qsave = lqsave;
33412751Ssam 		untimeout(unselect, (caddr_t)u.u_procp);
33512751Ssam 	}
33612751Ssam 	splx(s);
33712751Ssam 	goto retry;
33812751Ssam done:
33912751Ssam #define	putbits(name, x) \
34012751Ssam 	if (uap->name) { \
34117593Skarels 		int error = copyout((caddr_t)obits[x], (caddr_t)uap->name, \
34217593Skarels 		    ni * sizeof(int)); \
34312751Ssam 		if (error) \
34412751Ssam 			u.u_error = error; \
34512751Ssam 	}
34612751Ssam 	putbits(in, 0);
34712751Ssam 	putbits(ou, 1);
34812751Ssam 	putbits(ex, 2);
34912751Ssam #undef putbits
35012751Ssam }
35112751Ssam 
35212751Ssam unselect(p)
35312751Ssam 	register struct proc *p;
35412751Ssam {
35517934Skarels 	register int s = splhigh();
35612751Ssam 
35712751Ssam 	switch (p->p_stat) {
35812751Ssam 
35912751Ssam 	case SSLEEP:
36012751Ssam 		setrun(p);
36112751Ssam 		break;
36212751Ssam 
36312751Ssam 	case SSTOP:
36412751Ssam 		unsleep(p);
36512751Ssam 		break;
36612751Ssam 	}
36712751Ssam 	splx(s);
36812751Ssam }
36912751Ssam 
37017593Skarels selscan(ibits, obits, nfd)
37117593Skarels 	int (*ibits)[NI], (*obits)[NI];
37212751Ssam {
37317593Skarels 	register int which, bits, i, j;
37412751Ssam 	int flag;
37512751Ssam 	struct file *fp;
37612751Ssam 	int n = 0;
37712751Ssam 
37812751Ssam 	for (which = 0; which < 3; which++) {
37912751Ssam 		switch (which) {
38012751Ssam 
38112751Ssam 		case 0:
38212751Ssam 			flag = FREAD; break;
38312751Ssam 
38412751Ssam 		case 1:
38512751Ssam 			flag = FWRITE; break;
38612751Ssam 
38712751Ssam 		case 2:
38812751Ssam 			flag = 0; break;
38912751Ssam 		}
39017593Skarels 		for (i = 0; i < nfd; i += NBI) {
39117593Skarels 			bits = ibits[which][i/NBI];
39217593Skarels 			while ((j = ffs(bits)) && i + --j < nfd) {
39317593Skarels 				bits &= ~(1 << j);
39417593Skarels 				fp = u.u_ofile[i + j];
39517593Skarels 				if (fp == NULL) {
39617593Skarels 					u.u_error = EBADF;
39717593Skarels 					break;
39817593Skarels 				}
39917593Skarels 				if ((*fp->f_ops->fo_select)(fp, flag)) {
40017593Skarels 					sbit(obits[which], i + j);
40117593Skarels 					n++;
40217593Skarels 				}
40312751Ssam 			}
40412751Ssam 		}
40512751Ssam 	}
40612751Ssam 	return (n);
40712751Ssam }
40812751Ssam 
4097423Sroot /*ARGSUSED*/
41012751Ssam seltrue(dev, flag)
41112751Ssam 	dev_t dev;
41212751Ssam 	int flag;
4137423Sroot {
4147423Sroot 
41512751Ssam 	return (1);
4167423Sroot }
4178103Sroot 
41812751Ssam selwakeup(p, coll)
41912751Ssam 	register struct proc *p;
42012751Ssam 	int coll;
4218103Sroot {
4228103Sroot 
42312751Ssam 	if (coll) {
42412751Ssam 		nselcoll++;
42512751Ssam 		wakeup((caddr_t)&selwait);
42612751Ssam 	}
42712751Ssam 	if (p) {
42817934Skarels 		int s = splhigh();
42917270Skarels 		if (p->p_wchan == (caddr_t)&selwait) {
43017270Skarels 			if (p->p_stat == SSLEEP)
43117270Skarels 				setrun(p);
43217270Skarels 			else
43317270Skarels 				unsleep(p);
43417270Skarels 		} else if (p->p_flag & SSEL)
43512751Ssam 			p->p_flag &= ~SSEL;
43612751Ssam 		splx(s);
43712751Ssam 	}
4388103Sroot }
439