xref: /csrg-svn/sys/kern/sys_generic.c (revision 17934)
1*17934Skarels /*	sys_generic.c	6.7	85/02/08	*/
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;
13312883Ssam 	if ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) {
1347820Sroot 		if (uio->uio_resid == count)
1357423Sroot 			u.u_eosys = RESTARTSYS;
13612751Ssam 	} else
13712751Ssam 		u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
1387820Sroot 	u.u_r.r_val1 = count - uio->uio_resid;
13912751Ssam 	fp->f_offset += u.u_r.r_val1;
1407423Sroot }
1417423Sroot 
1427423Sroot /*
1437423Sroot  * Ioctl system call
1447423Sroot  */
1457423Sroot ioctl()
1467423Sroot {
1477423Sroot 	register struct file *fp;
1487624Ssam 	struct a {
1497423Sroot 		int	fdes;
1507423Sroot 		int	cmd;
1517423Sroot 		caddr_t	cmarg;
1527423Sroot 	} *uap;
1537820Sroot 	register int com;
1547820Sroot 	register u_int size;
1557624Ssam 	char data[IOCPARM_MASK+1];
1567423Sroot 
1577423Sroot 	uap = (struct a *)u.u_ap;
15817004Smckusick 	GETF(fp, uap->fdes);
1597423Sroot 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
1607423Sroot 		u.u_error = EBADF;
1617423Sroot 		return;
1627423Sroot 	}
1637624Ssam 	com = uap->cmd;
1647624Ssam 
16513228Ssam #if defined(vax) && defined(COMPAT)
1667624Ssam 	/*
1677624Ssam 	 * Map old style ioctl's into new for the
1687624Ssam 	 * sake of backwards compatibility (sigh).
1697624Ssam 	 */
1707624Ssam 	if ((com&~0xffff) == 0) {
1717624Ssam 		com = mapioctl(com);
1727624Ssam 		if (com == 0) {
1737624Ssam 			u.u_error = EINVAL;
1747624Ssam 			return;
1757624Ssam 		}
1767624Ssam 	}
1777624Ssam #endif
1787624Ssam 	if (com == FIOCLEX) {
1799592Ssam 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
1807423Sroot 		return;
1817423Sroot 	}
1827624Ssam 	if (com == FIONCLEX) {
1839592Ssam 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
1847423Sroot 		return;
1857423Sroot 	}
1867624Ssam 
1877624Ssam 	/*
1887624Ssam 	 * Interpret high order word to find
1897624Ssam 	 * amount of data to be copied to/from the
1907624Ssam 	 * user's address space.
1917624Ssam 	 */
1927624Ssam 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
1937624Ssam 	if (size > sizeof (data)) {
1947624Ssam 		u.u_error = EFAULT;
1957423Sroot 		return;
1967423Sroot 	}
19710601Ssam 	if (com&IOC_IN) {
19810601Ssam 		if (size) {
19910601Ssam 			u.u_error =
20010601Ssam 			    copyin(uap->cmarg, (caddr_t)data, (u_int)size);
20110601Ssam 			if (u.u_error)
20210601Ssam 				return;
20310601Ssam 		} else
20410601Ssam 			*(caddr_t *)data = uap->cmarg;
20510601Ssam 	} else if ((com&IOC_OUT) && size)
20610601Ssam 		/*
20710601Ssam 		 * Zero the buffer on the stack so the user
20810601Ssam 		 * always gets back something deterministic.
20910601Ssam 		 */
2107624Ssam 		bzero((caddr_t)data, size);
21111284Ssam 	else if (com&IOC_VOID)
21211284Ssam 		*(caddr_t *)data = uap->cmarg;
2137423Sroot 
21412751Ssam 	switch (com) {
2157624Ssam 
21612751Ssam 	case FIONBIO:
21712751Ssam 		u.u_error = fset(fp, FNDELAY, *(int *)data);
21812751Ssam 		return;
21912751Ssam 
22012751Ssam 	case FIOASYNC:
22112751Ssam 		u.u_error = fset(fp, FASYNC, *(int *)data);
22212751Ssam 		return;
22312751Ssam 
22412751Ssam 	case FIOSETOWN:
22512751Ssam 		u.u_error = fsetown(fp, *(int *)data);
22612751Ssam 		return;
22712751Ssam 
22812751Ssam 	case FIOGETOWN:
22912751Ssam 		u.u_error = fgetown(fp, (int *)data);
23012751Ssam 		return;
2317423Sroot 	}
23212751Ssam 	u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data);
2337624Ssam 	/*
2347624Ssam 	 * Copy any data to user, size was
2357624Ssam 	 * already set and checked above.
2367624Ssam 	 */
2379999Ssam 	if (u.u_error == 0 && (com&IOC_OUT) && size)
2389999Ssam 		u.u_error = copyout(data, uap->cmarg, (u_int)size);
2397423Sroot }
2407423Sroot 
24112751Ssam int	unselect();
24212751Ssam int	nselcoll;
24317593Skarels 
2447423Sroot /*
24517593Skarels  * Select uses bit masks of file descriptors in ints.
24617593Skarels  * These macros manipulate such bit fields (the filesystem macros use chars).
24717593Skarels  */
24817593Skarels #define NBI		(sizeof(int) * NBBY)		/* bits per int */
24917593Skarels #define	NI		howmany(NOFILE, NBI)
25017593Skarels #define	tbit(p, n)	((p)[(n)/NBI] & (1 << ((n) % NBI)))
25117593Skarels #define	sbit(p, n)	((p)[(n)/NBI] |= (1 << ((n) % NBI)))
25217593Skarels #define	cbit(p, n)	((p)[(n)/NBI] &= ~(1 << ((n) % NBI)))
25317593Skarels 
25417593Skarels /*
25512751Ssam  * Select system call.
2567423Sroot  */
25712751Ssam select()
25812751Ssam {
25912751Ssam 	register struct uap  {
26012751Ssam 		int	nd;
26117593Skarels 		int	*in, *ou, *ex;
26212751Ssam 		struct	timeval *tv;
26312751Ssam 	} *uap = (struct uap *)u.u_ap;
26417593Skarels 	int ibits[3][NI], obits[3][NI];
26512751Ssam 	struct timeval atv;
26617593Skarels 	int s, ncoll, ni;
26712751Ssam 	label_t lqsave;
26812751Ssam 
26917593Skarels 	bzero(ibits, sizeof(ibits));
27017593Skarels 	bzero(obits, sizeof(obits));
27112751Ssam 	if (uap->nd > NOFILE)
27212751Ssam 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
27317593Skarels 	ni = howmany(uap->nd, NBI);
27412751Ssam 
27512751Ssam #define	getbits(name, x) \
27612751Ssam 	if (uap->name) { \
27717593Skarels 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)ibits[x], \
27817593Skarels 		    ni * sizeof(int)); \
27912751Ssam 		if (u.u_error) \
28012751Ssam 			goto done; \
28117593Skarels 	}
28212751Ssam 	getbits(in, 0);
28312751Ssam 	getbits(ou, 1);
28412751Ssam 	getbits(ex, 2);
28512751Ssam #undef	getbits
28612751Ssam 
28712751Ssam 	if (uap->tv) {
28812751Ssam 		u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
28912751Ssam 			sizeof (atv));
29012751Ssam 		if (u.u_error)
29112751Ssam 			goto done;
29212751Ssam 		if (itimerfix(&atv)) {
29312751Ssam 			u.u_error = EINVAL;
29412751Ssam 			goto done;
29512751Ssam 		}
296*17934Skarels 		s = splhigh(); timevaladd(&atv, &time); splx(s);
29712751Ssam 	}
29812751Ssam retry:
29912751Ssam 	ncoll = nselcoll;
30012751Ssam 	u.u_procp->p_flag |= SSEL;
30117593Skarels 	u.u_r.r_val1 = selscan(ibits, obits, uap->nd);
30212751Ssam 	if (u.u_error || u.u_r.r_val1)
30312751Ssam 		goto done;
304*17934Skarels 	s = splhigh();
30512971Ssam 	/* this should be timercmp(&time, &atv, >=) */
30612971Ssam 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
30712971Ssam 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
30812751Ssam 		splx(s);
30912751Ssam 		goto done;
31012751Ssam 	}
31112751Ssam 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
31212751Ssam 		u.u_procp->p_flag &= ~SSEL;
31312751Ssam 		splx(s);
31412751Ssam 		goto retry;
31512751Ssam 	}
31612751Ssam 	u.u_procp->p_flag &= ~SSEL;
31712751Ssam 	if (uap->tv) {
31812751Ssam 		lqsave = u.u_qsave;
31912751Ssam 		if (setjmp(&u.u_qsave)) {
32012751Ssam 			untimeout(unselect, (caddr_t)u.u_procp);
32112751Ssam 			u.u_error = EINTR;
32212751Ssam 			splx(s);
32312751Ssam 			goto done;
32412751Ssam 		}
32512751Ssam 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
32612751Ssam 	}
32712751Ssam 	sleep((caddr_t)&selwait, PZERO+1);
32812751Ssam 	if (uap->tv) {
32912751Ssam 		u.u_qsave = lqsave;
33012751Ssam 		untimeout(unselect, (caddr_t)u.u_procp);
33112751Ssam 	}
33212751Ssam 	splx(s);
33312751Ssam 	goto retry;
33412751Ssam done:
33512751Ssam #define	putbits(name, x) \
33612751Ssam 	if (uap->name) { \
33717593Skarels 		int error = copyout((caddr_t)obits[x], (caddr_t)uap->name, \
33817593Skarels 		    ni * sizeof(int)); \
33912751Ssam 		if (error) \
34012751Ssam 			u.u_error = error; \
34112751Ssam 	}
34212751Ssam 	putbits(in, 0);
34312751Ssam 	putbits(ou, 1);
34412751Ssam 	putbits(ex, 2);
34512751Ssam #undef putbits
34612751Ssam }
34712751Ssam 
34812751Ssam unselect(p)
34912751Ssam 	register struct proc *p;
35012751Ssam {
351*17934Skarels 	register int s = splhigh();
35212751Ssam 
35312751Ssam 	switch (p->p_stat) {
35412751Ssam 
35512751Ssam 	case SSLEEP:
35612751Ssam 		setrun(p);
35712751Ssam 		break;
35812751Ssam 
35912751Ssam 	case SSTOP:
36012751Ssam 		unsleep(p);
36112751Ssam 		break;
36212751Ssam 	}
36312751Ssam 	splx(s);
36412751Ssam }
36512751Ssam 
36617593Skarels selscan(ibits, obits, nfd)
36717593Skarels 	int (*ibits)[NI], (*obits)[NI];
36812751Ssam {
36917593Skarels 	register int which, bits, i, j;
37012751Ssam 	int flag;
37112751Ssam 	struct file *fp;
37212751Ssam 	int n = 0;
37312751Ssam 
37412751Ssam 	for (which = 0; which < 3; which++) {
37512751Ssam 		switch (which) {
37612751Ssam 
37712751Ssam 		case 0:
37812751Ssam 			flag = FREAD; break;
37912751Ssam 
38012751Ssam 		case 1:
38112751Ssam 			flag = FWRITE; break;
38212751Ssam 
38312751Ssam 		case 2:
38412751Ssam 			flag = 0; break;
38512751Ssam 		}
38617593Skarels 		for (i = 0; i < nfd; i += NBI) {
38717593Skarels 			bits = ibits[which][i/NBI];
38817593Skarels 			while ((j = ffs(bits)) && i + --j < nfd) {
38917593Skarels 				bits &= ~(1 << j);
39017593Skarels 				fp = u.u_ofile[i + j];
39117593Skarels 				if (fp == NULL) {
39217593Skarels 					u.u_error = EBADF;
39317593Skarels 					break;
39417593Skarels 				}
39517593Skarels 				if ((*fp->f_ops->fo_select)(fp, flag)) {
39617593Skarels 					sbit(obits[which], i + j);
39717593Skarels 					n++;
39817593Skarels 				}
39912751Ssam 			}
40012751Ssam 		}
40112751Ssam 	}
40212751Ssam 	return (n);
40312751Ssam }
40412751Ssam 
4057423Sroot /*ARGSUSED*/
40612751Ssam seltrue(dev, flag)
40712751Ssam 	dev_t dev;
40812751Ssam 	int flag;
4097423Sroot {
4107423Sroot 
41112751Ssam 	return (1);
4127423Sroot }
4138103Sroot 
41412751Ssam selwakeup(p, coll)
41512751Ssam 	register struct proc *p;
41612751Ssam 	int coll;
4178103Sroot {
4188103Sroot 
41912751Ssam 	if (coll) {
42012751Ssam 		nselcoll++;
42112751Ssam 		wakeup((caddr_t)&selwait);
42212751Ssam 	}
42312751Ssam 	if (p) {
424*17934Skarels 		int s = splhigh();
42517270Skarels 		if (p->p_wchan == (caddr_t)&selwait) {
42617270Skarels 			if (p->p_stat == SSLEEP)
42717270Skarels 				setrun(p);
42817270Skarels 			else
42917270Skarels 				unsleep(p);
43017270Skarels 		} else if (p->p_flag & SSEL)
43112751Ssam 			p->p_flag &= ~SSEL;
43212751Ssam 		splx(s);
43312751Ssam 	}
4348103Sroot }
435