xref: /csrg-svn/sys/kern/sys_generic.c (revision 12751)
1*12751Ssam /*	sys_generic.c	5.36	83/05/27	*/
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"
11*12751Ssam #include "../h/kernel.h"
12*12751Ssam #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;
131*12751Ssam 	uio->uio_offset = fp->f_offset;
1328118Sroot 	if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
1337820Sroot 		if (uio->uio_resid == count)
1347423Sroot 			u.u_eosys = RESTARTSYS;
135*12751Ssam 	} else
136*12751Ssam 		u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
1377820Sroot 	u.u_r.r_val1 = count - uio->uio_resid;
138*12751Ssam 	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 
165*12751Ssam #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 
214*12751Ssam 	switch (com) {
2157624Ssam 
216*12751Ssam 	case FIONBIO:
217*12751Ssam 		u.u_error = fset(fp, FNDELAY, *(int *)data);
218*12751Ssam 		return;
219*12751Ssam 
220*12751Ssam 	case FIOASYNC:
221*12751Ssam 		u.u_error = fset(fp, FASYNC, *(int *)data);
222*12751Ssam 		return;
223*12751Ssam 
224*12751Ssam 	case FIOSETOWN:
225*12751Ssam 		u.u_error = fsetown(fp, *(int *)data);
226*12751Ssam 		return;
227*12751Ssam 
228*12751Ssam 	case FIOGETOWN:
229*12751Ssam 		u.u_error = fgetown(fp, (int *)data);
230*12751Ssam 		return;
2317423Sroot 	}
232*12751Ssam 	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 
241*12751Ssam int	unselect();
242*12751Ssam int	nselcoll;
2437423Sroot /*
244*12751Ssam  * Select system call.
2457423Sroot  */
246*12751Ssam select()
247*12751Ssam {
248*12751Ssam 	register struct uap  {
249*12751Ssam 		int	nd;
250*12751Ssam 		long	*in, *ou, *ex;
251*12751Ssam 		struct	timeval *tv;
252*12751Ssam 	} *uap = (struct uap *)u.u_ap;
253*12751Ssam 	int ibits[3], obits[3];
254*12751Ssam 	struct timeval atv;
255*12751Ssam 	int s, ncoll;
256*12751Ssam 	label_t lqsave;
257*12751Ssam 
258*12751Ssam 	obits[0] = obits[1] = obits[2] = 0;
259*12751Ssam 	if (uap->nd > NOFILE)
260*12751Ssam 		uap->nd = NOFILE;	/* forgiving, if slightly wrong */
261*12751Ssam 
262*12751Ssam #define	getbits(name, x) \
263*12751Ssam 	if (uap->name) { \
264*12751Ssam 		u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
265*12751Ssam 		    sizeof (ibits[x])); \
266*12751Ssam 		if (u.u_error) \
267*12751Ssam 			goto done; \
268*12751Ssam 	} else \
269*12751Ssam 		ibits[x] = 0;
270*12751Ssam 	getbits(in, 0);
271*12751Ssam 	getbits(ou, 1);
272*12751Ssam 	getbits(ex, 2);
273*12751Ssam #undef	getbits
274*12751Ssam 
275*12751Ssam 	if (uap->tv) {
276*12751Ssam 		u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
277*12751Ssam 			sizeof (atv));
278*12751Ssam 		if (u.u_error)
279*12751Ssam 			goto done;
280*12751Ssam 		if (itimerfix(&atv)) {
281*12751Ssam 			u.u_error = EINVAL;
282*12751Ssam 			goto done;
283*12751Ssam 		}
284*12751Ssam 		s = spl7(); timevaladd(&atv, &time); splx(s);
285*12751Ssam 	}
286*12751Ssam retry:
287*12751Ssam 	ncoll = nselcoll;
288*12751Ssam 	u.u_procp->p_flag |= SSEL;
289*12751Ssam 	u.u_r.r_val1 = selscan(ibits, obits);
290*12751Ssam 	if (u.u_error || u.u_r.r_val1)
291*12751Ssam 		goto done;
292*12751Ssam 	s = spl6();
293*12751Ssam 	if (uap->tv && timercmp(&time, &atv, >=)) {
294*12751Ssam 		splx(s);
295*12751Ssam 		goto done;
296*12751Ssam 	}
297*12751Ssam 	if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
298*12751Ssam 		u.u_procp->p_flag &= ~SSEL;
299*12751Ssam 		splx(s);
300*12751Ssam 		goto retry;
301*12751Ssam 	}
302*12751Ssam 	u.u_procp->p_flag &= ~SSEL;
303*12751Ssam 	if (uap->tv) {
304*12751Ssam 		lqsave = u.u_qsave;
305*12751Ssam 		if (setjmp(&u.u_qsave)) {
306*12751Ssam 			untimeout(unselect, (caddr_t)u.u_procp);
307*12751Ssam 			u.u_error = EINTR;
308*12751Ssam 			splx(s);
309*12751Ssam 			goto done;
310*12751Ssam 		}
311*12751Ssam 		timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
312*12751Ssam 	}
313*12751Ssam 	sleep((caddr_t)&selwait, PZERO+1);
314*12751Ssam 	if (uap->tv) {
315*12751Ssam 		u.u_qsave = lqsave;
316*12751Ssam 		untimeout(unselect, (caddr_t)u.u_procp);
317*12751Ssam 	}
318*12751Ssam 	splx(s);
319*12751Ssam 	goto retry;
320*12751Ssam done:
321*12751Ssam #define	putbits(name, x) \
322*12751Ssam 	if (uap->name) { \
323*12751Ssam 		int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
324*12751Ssam 		    sizeof (obits[x])); \
325*12751Ssam 		if (error) \
326*12751Ssam 			u.u_error = error; \
327*12751Ssam 	}
328*12751Ssam 	putbits(in, 0);
329*12751Ssam 	putbits(ou, 1);
330*12751Ssam 	putbits(ex, 2);
331*12751Ssam #undef putbits
332*12751Ssam }
333*12751Ssam 
334*12751Ssam unselect(p)
335*12751Ssam 	register struct proc *p;
336*12751Ssam {
337*12751Ssam 	register int s = spl6();
338*12751Ssam 
339*12751Ssam 	switch (p->p_stat) {
340*12751Ssam 
341*12751Ssam 	case SSLEEP:
342*12751Ssam 		setrun(p);
343*12751Ssam 		break;
344*12751Ssam 
345*12751Ssam 	case SSTOP:
346*12751Ssam 		unsleep(p);
347*12751Ssam 		break;
348*12751Ssam 	}
349*12751Ssam 	splx(s);
350*12751Ssam }
351*12751Ssam 
352*12751Ssam selscan(ibits, obits)
353*12751Ssam 	int *ibits, *obits;
354*12751Ssam {
355*12751Ssam 	register int which, bits, i;
356*12751Ssam 	int flag;
357*12751Ssam 	struct file *fp;
358*12751Ssam 	int n = 0;
359*12751Ssam 
360*12751Ssam 	for (which = 0; which < 3; which++) {
361*12751Ssam 		bits = ibits[which];
362*12751Ssam 		obits[which] = 0;
363*12751Ssam 		switch (which) {
364*12751Ssam 
365*12751Ssam 		case 0:
366*12751Ssam 			flag = FREAD; break;
367*12751Ssam 
368*12751Ssam 		case 1:
369*12751Ssam 			flag = FWRITE; break;
370*12751Ssam 
371*12751Ssam 		case 2:
372*12751Ssam 			flag = 0; break;
373*12751Ssam 		}
374*12751Ssam 		while (i = ffs(bits)) {
375*12751Ssam 			bits &= ~(1<<(i-1));
376*12751Ssam 			fp = u.u_ofile[i-1];
377*12751Ssam 			if (fp == NULL) {
378*12751Ssam 				u.u_error = EBADF;
379*12751Ssam 				break;
380*12751Ssam 			}
381*12751Ssam 			if ((*fp->f_ops->fo_select)(fp, flag)) {
382*12751Ssam 				obits[which] |= (1<<(i-1));
383*12751Ssam 				n++;
384*12751Ssam 			}
385*12751Ssam 		}
386*12751Ssam 	}
387*12751Ssam 	return (n);
388*12751Ssam }
389*12751Ssam 
3907423Sroot /*ARGSUSED*/
391*12751Ssam seltrue(dev, flag)
392*12751Ssam 	dev_t dev;
393*12751Ssam 	int flag;
3947423Sroot {
3957423Sroot 
396*12751Ssam 	return (1);
3977423Sroot }
3988103Sroot 
399*12751Ssam selwakeup(p, coll)
400*12751Ssam 	register struct proc *p;
401*12751Ssam 	int coll;
4028103Sroot {
4038103Sroot 
404*12751Ssam 	if (coll) {
405*12751Ssam 		nselcoll++;
406*12751Ssam 		wakeup((caddr_t)&selwait);
407*12751Ssam 	}
408*12751Ssam 	if (p) {
409*12751Ssam 		int s = spl6();
410*12751Ssam 		if (p->p_wchan == (caddr_t)&selwait)
411*12751Ssam 			setrun(p);
412*12751Ssam 		else if (p->p_flag & SSEL)
413*12751Ssam 			p->p_flag &= ~SSEL;
414*12751Ssam 		splx(s);
415*12751Ssam 	}
4168103Sroot }
4178103Sroot 
418*12751Ssam fstat()
4198103Sroot {
420*12751Ssam 	register struct file *fp;
421*12751Ssam 	register struct a {
422*12751Ssam 		int	fdes;
423*12751Ssam 		struct	stat *sb;
424*12751Ssam 	} *uap;
425*12751Ssam 	struct stat ub;
4268103Sroot 
427*12751Ssam 	uap = (struct a *)u.u_ap;
428*12751Ssam 	fp = getf(uap->fdes);
429*12751Ssam 	if (fp == 0)
430*12751Ssam 		return;
431*12751Ssam 	u.u_error = (*fp->f_ops->fo_stat)(fp, &ub);
432*12751Ssam 	if (u.u_error == 0)
433*12751Ssam 		u.u_error = copyout(&ub, uap->sb, sizeof (ub));
4348103Sroot }
435