xref: /csrg-svn/sys/kern/sys_generic.c (revision 13041)
1*13041Ssam /*	sys_generic.c	5.39	83/06/12	*/
27423Sroot 
37423Sroot #include "../h/param.h"
47423Sroot #include "../h/systm.h"
57423Sroot #include "../h/dir.h"
67423Sroot #include "../h/user.h"
79560Ssam #include "../h/ioctl.h"
87423Sroot #include "../h/file.h"
97423Sroot #include "../h/proc.h"
107714Sroot #include "../h/uio.h"
1112751Ssam #include "../h/kernel.h"
1212751Ssam #include "../h/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;
1177820Sroot 	uio->uio_segflg = 0;
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 		}
1297820Sroot 	}
1307820Sroot 	count = uio->uio_resid;
13112751Ssam 	uio->uio_offset = fp->f_offset;
13212883Ssam 	if ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) {
1337820Sroot 		if (uio->uio_resid == count)
1347423Sroot 			u.u_eosys = RESTARTSYS;
13512751Ssam 	} else
13612751Ssam 		u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
1377820Sroot 	u.u_r.r_val1 = count - uio->uio_resid;
13812751Ssam 	fp->f_offset += u.u_r.r_val1;
1397423Sroot }
1407423Sroot 
1417423Sroot /*
1427423Sroot  * Ioctl system call
1437423Sroot  */
1447423Sroot ioctl()
1457423Sroot {
1467423Sroot 	register struct file *fp;
1477624Ssam 	struct a {
1487423Sroot 		int	fdes;
1497423Sroot 		int	cmd;
1507423Sroot 		caddr_t	cmarg;
1517423Sroot 	} *uap;
1527820Sroot 	register int com;
1537820Sroot 	register u_int size;
1547624Ssam 	char data[IOCPARM_MASK+1];
1557423Sroot 
1567423Sroot 	uap = (struct a *)u.u_ap;
1577423Sroot 	if ((fp = getf(uap->fdes)) == NULL)
1587423Sroot 		return;
1597423Sroot 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
1607423Sroot 		u.u_error = EBADF;
1617423Sroot 		return;
1627423Sroot 	}
1637624Ssam 	com = uap->cmd;
1647624Ssam 
16512751Ssam #if defined(vax) && !defined(NOCOMPAT)
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;
2437423Sroot /*
24412751Ssam  * Select system call.
2457423Sroot  */
24612751Ssam select()
24712751Ssam {
24812751Ssam 	register struct uap  {
24912751Ssam 		int	nd;
25012751Ssam 		long	*in, *ou, *ex;
25112751Ssam 		struct	timeval *tv;
25212751Ssam 	} *uap = (struct uap *)u.u_ap;
25312751Ssam 	int ibits[3], obits[3];
25412751Ssam 	struct timeval atv;
255*13041Ssam 	int s, ncoll, mask;
25612751Ssam 	label_t lqsave;
25712751Ssam 
25812751Ssam 	obits[0] = obits[1] = obits[2] = 0;
25912751Ssam 	if (uap->nd > NOFILE)
26012751Ssam 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
261*13041Ssam 	mask = (1 << uap->nd) - 1;
26212751Ssam 
26312751Ssam #define	getbits(name, x) \
26412751Ssam 	if (uap->name) { \
26512751Ssam 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
26612751Ssam 		    sizeof (ibits[x])); \
26712751Ssam 		if (u.u_error) \
26812751Ssam 			goto done; \
269*13041Ssam 		ibits[x] &= mask; \
27012751Ssam 	} else \
27112751Ssam 		ibits[x] = 0;
27212751Ssam 	getbits(in, 0);
27312751Ssam 	getbits(ou, 1);
27412751Ssam 	getbits(ex, 2);
27512751Ssam #undef	getbits
27612751Ssam 
27712751Ssam 	if (uap->tv) {
27812751Ssam 		u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
27912751Ssam 			sizeof (atv));
28012751Ssam 		if (u.u_error)
28112751Ssam 			goto done;
28212751Ssam 		if (itimerfix(&atv)) {
28312751Ssam 			u.u_error = EINVAL;
28412751Ssam 			goto done;
28512751Ssam 		}
28612751Ssam 		s = spl7(); timevaladd(&atv, &time); splx(s);
28712751Ssam 	}
28812751Ssam retry:
28912751Ssam 	ncoll = nselcoll;
29012751Ssam 	u.u_procp->p_flag |= SSEL;
29112751Ssam 	u.u_r.r_val1 = selscan(ibits, obits);
29212751Ssam 	if (u.u_error || u.u_r.r_val1)
29312751Ssam 		goto done;
29412751Ssam 	s = spl6();
29512971Ssam 	/* this should be timercmp(&time, &atv, >=) */
29612971Ssam 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
29712971Ssam 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
29812751Ssam 		splx(s);
29912751Ssam 		goto done;
30012751Ssam 	}
30112751Ssam 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
30212751Ssam 		u.u_procp->p_flag &= ~SSEL;
30312751Ssam 		splx(s);
30412751Ssam 		goto retry;
30512751Ssam 	}
30612751Ssam 	u.u_procp->p_flag &= ~SSEL;
30712751Ssam 	if (uap->tv) {
30812751Ssam 		lqsave = u.u_qsave;
30912751Ssam 		if (setjmp(&u.u_qsave)) {
31012751Ssam 			untimeout(unselect, (caddr_t)u.u_procp);
31112751Ssam 			u.u_error = EINTR;
31212751Ssam 			splx(s);
31312751Ssam 			goto done;
31412751Ssam 		}
31512751Ssam 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
31612751Ssam 	}
31712751Ssam 	sleep((caddr_t)&selwait, PZERO+1);
31812751Ssam 	if (uap->tv) {
31912751Ssam 		u.u_qsave = lqsave;
32012751Ssam 		untimeout(unselect, (caddr_t)u.u_procp);
32112751Ssam 	}
32212751Ssam 	splx(s);
32312751Ssam 	goto retry;
32412751Ssam done:
32512751Ssam #define	putbits(name, x) \
32612751Ssam 	if (uap->name) { \
32712751Ssam 		int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
32812751Ssam 		    sizeof (obits[x])); \
32912751Ssam 		if (error) \
33012751Ssam 			u.u_error = error; \
33112751Ssam 	}
33212751Ssam 	putbits(in, 0);
33312751Ssam 	putbits(ou, 1);
33412751Ssam 	putbits(ex, 2);
33512751Ssam #undef putbits
33612751Ssam }
33712751Ssam 
33812751Ssam unselect(p)
33912751Ssam 	register struct proc *p;
34012751Ssam {
34112751Ssam 	register int s = spl6();
34212751Ssam 
34312751Ssam 	switch (p->p_stat) {
34412751Ssam 
34512751Ssam 	case SSLEEP:
34612751Ssam 		setrun(p);
34712751Ssam 		break;
34812751Ssam 
34912751Ssam 	case SSTOP:
35012751Ssam 		unsleep(p);
35112751Ssam 		break;
35212751Ssam 	}
35312751Ssam 	splx(s);
35412751Ssam }
35512751Ssam 
35612751Ssam selscan(ibits, obits)
35712751Ssam 	int *ibits, *obits;
35812751Ssam {
35912751Ssam 	register int which, bits, i;
36012751Ssam 	int flag;
36112751Ssam 	struct file *fp;
36212751Ssam 	int n = 0;
36312751Ssam 
36412751Ssam 	for (which = 0; which < 3; which++) {
36512751Ssam 		bits = ibits[which];
36612751Ssam 		obits[which] = 0;
36712751Ssam 		switch (which) {
36812751Ssam 
36912751Ssam 		case 0:
37012751Ssam 			flag = FREAD; break;
37112751Ssam 
37212751Ssam 		case 1:
37312751Ssam 			flag = FWRITE; break;
37412751Ssam 
37512751Ssam 		case 2:
37612751Ssam 			flag = 0; break;
37712751Ssam 		}
37812751Ssam 		while (i = ffs(bits)) {
37912751Ssam 			bits &= ~(1<<(i-1));
38012751Ssam 			fp = u.u_ofile[i-1];
38112751Ssam 			if (fp == NULL) {
38212751Ssam 				u.u_error = EBADF;
38312751Ssam 				break;
38412751Ssam 			}
38512751Ssam 			if ((*fp->f_ops->fo_select)(fp, flag)) {
38612751Ssam 				obits[which] |= (1<<(i-1));
38712751Ssam 				n++;
38812751Ssam 			}
38912751Ssam 		}
39012751Ssam 	}
39112751Ssam 	return (n);
39212751Ssam }
39312751Ssam 
3947423Sroot /*ARGSUSED*/
39512751Ssam seltrue(dev, flag)
39612751Ssam 	dev_t dev;
39712751Ssam 	int flag;
3987423Sroot {
3997423Sroot 
40012751Ssam 	return (1);
4017423Sroot }
4028103Sroot 
40312751Ssam selwakeup(p, coll)
40412751Ssam 	register struct proc *p;
40512751Ssam 	int coll;
4068103Sroot {
4078103Sroot 
40812751Ssam 	if (coll) {
40912751Ssam 		nselcoll++;
41012751Ssam 		wakeup((caddr_t)&selwait);
41112751Ssam 	}
41212751Ssam 	if (p) {
41312751Ssam 		int s = spl6();
41412751Ssam 		if (p->p_wchan == (caddr_t)&selwait)
41512751Ssam 			setrun(p);
41612751Ssam 		else if (p->p_flag & SSEL)
41712751Ssam 			p->p_flag &= ~SSEL;
41812751Ssam 		splx(s);
41912751Ssam 	}
4208103Sroot }
4218103Sroot 
42212751Ssam fstat()
4238103Sroot {
42412751Ssam 	register struct file *fp;
42512751Ssam 	register struct a {
42612751Ssam 		int	fdes;
42712751Ssam 		struct	stat *sb;
42812751Ssam 	} *uap;
42912751Ssam 	struct stat ub;
4308103Sroot 
43112751Ssam 	uap = (struct a *)u.u_ap;
43212751Ssam 	fp = getf(uap->fdes);
43312751Ssam 	if (fp == 0)
43412751Ssam 		return;
43512751Ssam 	u.u_error = (*fp->f_ops->fo_stat)(fp, &ub);
43612751Ssam 	if (u.u_error == 0)
43712751Ssam 		u.u_error = copyout(&ub, uap->sb, sizeof (ub));
4388103Sroot }
439