xref: /csrg-svn/sys/kern/sys_generic.c (revision 8564)
1*8564Sroot /*	sys_generic.c	5.17	82/10/17	*/
27423Sroot 
37423Sroot #include "../h/param.h"
47423Sroot #include "../h/systm.h"
57423Sroot #include "../h/dir.h"
67423Sroot #include "../h/user.h"
77423Sroot #include "../h/tty.h"
87423Sroot #include "../h/file.h"
97423Sroot #include "../h/inode.h"
107423Sroot #include "../h/buf.h"
117423Sroot #include "../h/proc.h"
127423Sroot #include "../h/conf.h"
137423Sroot #include "../h/socket.h"
147423Sroot #include "../h/socketvar.h"
157423Sroot #include "../h/fs.h"
167487Skre #ifdef MUSH
177487Skre #include "../h/quota.h"
187487Skre #include "../h/share.h"
197487Skre #else
207487Skre #define	CHARGE(nothing)
217487Skre #endif
227500Sroot #include "../h/descrip.h"
237714Sroot #include "../h/uio.h"
247423Sroot 
257423Sroot /*
267423Sroot  * Read system call.
277423Sroot  */
287423Sroot read()
297423Sroot {
307423Sroot 	register struct a {
317423Sroot 		int	fdes;
327423Sroot 		char	*cbuf;
337423Sroot 		unsigned count;
347820Sroot 	} *uap = (struct a *)u.u_ap;
357746Sroot 	struct uio auio;
367746Sroot 	struct iovec aiov;
377423Sroot 
387820Sroot 	aiov.iov_base = (caddr_t)uap->cbuf;
397820Sroot 	aiov.iov_len = uap->count;
407820Sroot 	auio.uio_iov = &aiov;
417820Sroot 	auio.uio_iovcnt = 1;
427820Sroot 	rwuio(&auio, UIO_READ);
437820Sroot }
447820Sroot 
457820Sroot readv()
467820Sroot {
477820Sroot 	register struct a {
487820Sroot 		int	fdes;
497820Sroot 		struct	iovec *iovp;
507820Sroot 		int	iovcnt;
517820Sroot 	} *uap = (struct a *)u.u_ap;
527820Sroot 	struct uio auio;
537820Sroot 	struct iovec aiov[16];		/* XXX */
547820Sroot 
557820Sroot 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
567423Sroot 		u.u_error = EINVAL;
577423Sroot 		return;
587423Sroot 	}
597820Sroot 	auio.uio_iov = aiov;
607820Sroot 	auio.uio_iovcnt = uap->iovcnt;
617820Sroot 	if (copyin((caddr_t)uap->iovp, (caddr_t)aiov,
627820Sroot 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)))) {
637820Sroot 		u.u_error = EFAULT;
647423Sroot 		return;
657423Sroot 	}
667820Sroot 	rwuio(&auio, UIO_READ);
677423Sroot }
687423Sroot 
697423Sroot /*
707423Sroot  * Write system call
717423Sroot  */
727423Sroot write()
737423Sroot {
747423Sroot 	register struct a {
757423Sroot 		int	fdes;
767423Sroot 		char	*cbuf;
777820Sroot 		int	count;
787820Sroot 	} *uap = (struct a *)u.u_ap;
797820Sroot 	struct uio auio;
807820Sroot 	struct iovec aiov;
817423Sroot 
827820Sroot 	auio.uio_iov = &aiov;
837820Sroot 	auio.uio_iovcnt = 1;
847820Sroot 	aiov.iov_base = uap->cbuf;
857820Sroot 	aiov.iov_len = uap->count;
867820Sroot 	rwuio(&auio, UIO_WRITE);
877820Sroot }
887820Sroot 
897820Sroot writev()
907820Sroot {
917820Sroot 	register struct a {
927820Sroot 		int	fdes;
937820Sroot 		struct	iovec *iovp;
947820Sroot 		int	iovcnt;
957820Sroot 	} *uap = (struct a *)u.u_ap;
967820Sroot 	struct uio auio;
977820Sroot 	struct iovec aiov[16];		/* XXX */
987820Sroot 
997820Sroot 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
1007423Sroot 		u.u_error = EINVAL;
1017423Sroot 		return;
1027423Sroot 	}
1037820Sroot 	auio.uio_iov = aiov;
1047820Sroot 	auio.uio_iovcnt = uap->iovcnt;
1057820Sroot 	if (copyin((caddr_t)uap->iovp, (caddr_t)aiov,
1067820Sroot 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)))) {
1077820Sroot 		u.u_error = EFAULT;
1087820Sroot 		return;
1097820Sroot 	}
1107820Sroot 	rwuio(&auio, UIO_WRITE);
1117820Sroot }
1127820Sroot 
1137820Sroot rwuio(uio, rw)
1147820Sroot 	register struct uio *uio;
1157820Sroot 	enum uio_rw rw;
1167820Sroot {
1177820Sroot 	struct a {
1187820Sroot 		int	fdes;
1197820Sroot 	};
1207820Sroot 	register struct file *fp;
1217820Sroot 	register struct iovec *iov;
1227820Sroot 	register struct inode *ip;
1237820Sroot 	int i, count;
1247820Sroot 
1257820Sroot 	GETF(fp, ((struct a *)u.u_ap)->fdes);
1267820Sroot 	if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
1277423Sroot 		u.u_error = EBADF;
1287423Sroot 		return;
1297423Sroot 	}
1307820Sroot 	uio->uio_resid = 0;
1317820Sroot 	uio->uio_segflg = 0;
1327820Sroot 	iov = uio->uio_iov;
1337820Sroot 	for (i = 0; i < uio->uio_iovcnt; i++) {
1347820Sroot 		if (iov->iov_len < 0) {
1357820Sroot 			u.u_error = EINVAL;
1367820Sroot 			return;
1377820Sroot 		}
1387820Sroot 		uio->uio_resid += iov->iov_len;
1397820Sroot 		if (uio->uio_resid < 0) {
1407820Sroot 			u.u_error = EINVAL;
1417820Sroot 			return;
1427820Sroot 		}
1437820Sroot 	}
1447820Sroot 	count = uio->uio_resid;
1458118Sroot 	if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
1467820Sroot 		if (uio->uio_resid == count)
1477423Sroot 			u.u_eosys = RESTARTSYS;
1487820Sroot 	} else if (fp->f_type == DTYPE_SOCKET) {
1497820Sroot 		int sosend(), soreceive();
1507820Sroot 		u.u_error =
1517820Sroot 		    (*(rw==UIO_READ?soreceive:sosend))
1528449Sroot 		      (fp->f_socket, (struct sockaddr *)0, uio, 0);
1537820Sroot 	} else {
1547423Sroot 		ip = fp->f_inode;
1557820Sroot 		uio->uio_offset = fp->f_offset;
1567423Sroot 		if ((ip->i_mode&IFMT) == IFREG) {
1578449Sroot 			ILOCK(ip);
1587820Sroot 			u.u_error = rwip(ip, uio, rw);
1598449Sroot 			IUNLOCK(ip);
1607423Sroot 		} else
1617820Sroot 			u.u_error = rwip(ip, uio, rw);
1627820Sroot 		fp->f_offset += count - uio->uio_resid;
1637423Sroot 	}
1647820Sroot 	u.u_r.r_val1 = count - uio->uio_resid;
1657423Sroot }
1667423Sroot 
1677820Sroot rdwri(rw, ip, base, len, offset, segflg, aresid)
1687820Sroot 	struct inode *ip;
1697820Sroot 	caddr_t base;
1707820Sroot 	int len, offset, segflg;
1717820Sroot 	int *aresid;
1727820Sroot 	enum uio_rw rw;
1737500Sroot {
1747820Sroot 	struct uio auio;
1757820Sroot 	struct iovec aiov;
1767820Sroot 	int error;
1777423Sroot 
1787820Sroot 	auio.uio_iov = &aiov;
1797820Sroot 	auio.uio_iovcnt = 1;
1807820Sroot 	aiov.iov_base = base;
1817820Sroot 	aiov.iov_len = len;
1827820Sroot 	auio.uio_resid = len;
1837820Sroot 	auio.uio_offset = offset;
1847820Sroot 	auio.uio_segflg = segflg;
1857820Sroot 	error = rwip(ip, &auio, rw);
1867820Sroot 	if (aresid)
1877820Sroot 		*aresid = auio.uio_resid;
1887820Sroot 	else
1897820Sroot 		if (auio.uio_resid)
1907820Sroot 			error = EIO;
1917820Sroot 	return (error);
1927500Sroot }
1937500Sroot 
1947820Sroot rwip(ip, uio, rw)
1957820Sroot 	register struct inode *ip;
1967820Sroot 	register struct uio *uio;
1977820Sroot 	enum uio_rw rw;
1987500Sroot {
1997820Sroot 	dev_t dev = (dev_t)ip->i_rdev;
2007820Sroot 	struct buf *bp;
2017820Sroot 	struct fs *fs;
2027820Sroot 	daddr_t lbn, bn;
2037820Sroot 	register int on, type;
2047820Sroot 	register unsigned n;
2057820Sroot 	int size;
2067820Sroot 	long bsize;
2077820Sroot 	extern int mem_no;
2087820Sroot 	int error = 0;
2097500Sroot 
2107820Sroot 	if (rw != UIO_READ && rw != UIO_WRITE)
2117820Sroot 		panic("rwip");
2127820Sroot 	if (uio->uio_offset < 0 &&
2137820Sroot 	    ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)))
2147820Sroot 		return (EINVAL); if (rw == UIO_READ)
2157820Sroot 		ip->i_flag |= IACC;
2167820Sroot 	type = ip->i_mode&IFMT;
2177820Sroot 	if (type == IFCHR) {
2187820Sroot #ifdef QUOTA
2197820Sroot 		register c = uio->uio_resid;
2207820Sroot #endif
2217820Sroot 		if (rw == UIO_READ)
2228519Sroot 			u.u_error = (*cdevsw[major(dev)].d_read)(dev, uio);
2237820Sroot 		else {
2247820Sroot 			ip->i_flag |= IUPD|ICHG;
2258519Sroot 			u.u_error = (*cdevsw[major(dev)].d_write)(dev, uio);
2267820Sroot 		}
2277820Sroot 		CHARGE(sc_tio * (c - uio->uio_resid));
2287820Sroot 		return (u.u_error);
2297820Sroot 	}
2307820Sroot 	if (rw == UIO_WRITE && type == IFREG &&
2318036Sroot 	    uio->uio_offset + uio->uio_resid >
2328036Sroot 	      u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
2337820Sroot 		psignal(u.u_procp, SIGXFSZ);
2347820Sroot 		return (EMFILE);
2357820Sroot 	}
2367820Sroot 	if (type != IFBLK) {
2377820Sroot 		dev = ip->i_dev;
2387820Sroot 		fs = ip->i_fs;
2397820Sroot 		bsize = fs->fs_bsize;
2407820Sroot 	} else
2417820Sroot 		bsize = BLKDEV_IOSIZE;
2427820Sroot 	do {
2437820Sroot 		lbn = uio->uio_offset / bsize;
2447820Sroot 		on = uio->uio_offset % bsize;
2457820Sroot 		n = MIN((unsigned)(bsize - on), uio->uio_resid);
2467820Sroot 		if (type != IFBLK) {
2477820Sroot 			if (rw == UIO_READ) {
2487820Sroot 				int diff = ip->i_size - uio->uio_offset;
2497820Sroot 				if (diff <= 0)
2507820Sroot 					return (0);
2517820Sroot 				if (diff < n)
2527820Sroot 					n = diff;
2537820Sroot 			}
2547820Sroot 			bn = fsbtodb(fs,
2557820Sroot 			    bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n)));
2567820Sroot 			if (u.u_error || rw == UIO_WRITE && (long)bn<0)
2577820Sroot 				return (u.u_error);
2587820Sroot 			if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size &&
2597820Sroot 			   (type == IFDIR || type == IFREG || type == IFLNK))
2607820Sroot 				ip->i_size = uio->uio_offset + n;
2617820Sroot 			size = blksize(fs, ip, lbn);
2627820Sroot 		} else {
2637820Sroot 			bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE);
2647820Sroot 			rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE);
2657820Sroot 			rasize = size = bsize;
2667820Sroot 		}
2677820Sroot 		if (rw == UIO_READ) {
2687820Sroot 			if ((long)bn<0) {
2697820Sroot 				bp = geteblk(size);
2707820Sroot 				clrbuf(bp);
2717820Sroot 			} else if (ip->i_lastr + 1 == lbn)
2727820Sroot 				bp = breada(dev, bn, size, rablock, rasize);
2737820Sroot 			else
2747820Sroot 				bp = bread(dev, bn, size);
2757820Sroot 			ip->i_lastr = lbn;
2767820Sroot 		} else {
2777820Sroot 			int i, count;
2787820Sroot 
2797820Sroot 			count = howmany(size, DEV_BSIZE);
2807820Sroot 			for (i = 0; i < count; i += CLSIZE)
2817820Sroot 				if (mfind(dev, bn + i))
2827820Sroot 					munhash(dev, bn + i);
2837820Sroot 			if (n == bsize)
2847820Sroot 				bp = getblk(dev, bn, size);
2857820Sroot 			else
2867820Sroot 				bp = bread(dev, bn, size);
2877820Sroot 		}
2887820Sroot 		n = MIN(n, size - bp->b_resid);
2897820Sroot 		if (bp->b_flags & B_ERROR) {
2907820Sroot 			error = EIO;
2917820Sroot 			brelse(bp);
2927820Sroot 			goto bad;
2937820Sroot 		}
2947820Sroot 		u.u_error =
2957820Sroot 		    uiomove(bp->b_un.b_addr+on, (u_int)n, rw, uio);
2967820Sroot 		if (rw == UIO_READ) {
2977820Sroot 			if (n + on == bsize || uio->uio_offset == ip->i_size)
2987820Sroot 				bp->b_flags |= B_AGE;
2997820Sroot 			brelse(bp);
3007820Sroot 		} else {
3017820Sroot 			if ((ip->i_mode&IFMT) == IFDIR)
3027820Sroot 				bwrite(bp);
3037820Sroot 			else if (n + on == bsize) {
3047820Sroot 				bp->b_flags |= B_AGE;
3057820Sroot 				bawrite(bp);
3067820Sroot 			} else
3077820Sroot 				bdwrite(bp);
3087820Sroot 			ip->i_flag |= IUPD|ICHG;
3097820Sroot 			if (u.u_ruid != 0)
3107820Sroot 				ip->i_mode &= ~(ISUID|ISGID);
3117820Sroot 		}
3127820Sroot 	} while (u.u_error == 0 && uio->uio_resid > 0 && n != 0);
3137820Sroot bad:
3147820Sroot 	return (error);
3157500Sroot }
3167500Sroot 
3177820Sroot uiomove(cp, n, rw, uio)
3187820Sroot 	register caddr_t cp;
3197820Sroot 	register int n;
3207820Sroot 	enum uio_rw rw;
3217820Sroot 	register struct uio *uio;
3227820Sroot {
3237820Sroot 	register struct iovec *iov;
3247820Sroot 	int error;
3257820Sroot 	u_int cnt;
3267820Sroot 
3277820Sroot 	while (n > 0 && uio->uio_resid) {
3287820Sroot 		iov = uio->uio_iov;
3297820Sroot 		cnt = iov->iov_len;
3307820Sroot 		if (cnt == 0) {
3317820Sroot 			uio->uio_iov++;
3327820Sroot 			uio->uio_iovcnt--;
3337820Sroot 			continue;
3347820Sroot 		}
3357820Sroot 		if (cnt > n)
3367820Sroot 			cnt = n;
3377820Sroot 		switch (uio->uio_segflg) {
3387820Sroot 
3397820Sroot 		case 0:
3407820Sroot 		case 2:
3417820Sroot 			if (rw == UIO_READ)
3427820Sroot 				error = copyout(cp, iov->iov_base, cnt);
3437820Sroot 			else
3447820Sroot 				error = copyin(iov->iov_base, cp, cnt);
3457820Sroot 			if (error)
3467820Sroot 				return (error);
3477820Sroot 			break;
3487820Sroot 
3497820Sroot 		case 1:
3507820Sroot 			if (rw == UIO_READ)
3517820Sroot 				bcopy((caddr_t)cp, iov->iov_base, cnt);
3527820Sroot 			else
3537820Sroot 				bcopy(iov->iov_base, (caddr_t)cp, cnt);
3547820Sroot 			break;
3557820Sroot 		}
3567820Sroot 		iov->iov_base += cnt;
3577820Sroot 		iov->iov_len -= cnt;
3587820Sroot 		uio->uio_resid -= cnt;
3597820Sroot 		uio->uio_offset += cnt;
3607820Sroot 		cp += cnt;
3617820Sroot 		n -= cnt;
3627820Sroot 	}
3637820Sroot 	return (error);
3647820Sroot }
3657820Sroot 
3667423Sroot /*
3677820Sroot  * Give next character to user as result of read.
3687820Sroot  */
3697820Sroot ureadc(c, uio)
3707820Sroot 	register int c;
3717820Sroot 	register struct uio *uio;
3727820Sroot {
3737820Sroot 	register struct iovec *iov;
3747820Sroot 
3757820Sroot again:
3767820Sroot 	if (uio->uio_iovcnt == 0)
3777820Sroot 		panic("ureadc");
3787820Sroot 	iov = uio->uio_iov;
3797820Sroot 	if (iov->iov_len <= 0 || uio->uio_resid <= 0) {
3807820Sroot 		uio->uio_iovcnt--;
3817820Sroot 		uio->uio_iov++;
3827820Sroot 		goto again;
3837820Sroot 	}
3847820Sroot 	switch (uio->uio_segflg) {
3857820Sroot 
3867820Sroot 	case 0:
3877820Sroot 		if (subyte(iov->iov_base, c) < 0)
3887820Sroot 			return (EFAULT);
3897820Sroot 		break;
3907820Sroot 
3917820Sroot 	case 1:
3927820Sroot 		*iov->iov_base = c;
3937820Sroot 		break;
3947820Sroot 
3957820Sroot 	case 2:
3967820Sroot 		if (suibyte(iov->iov_base, c) < 0)
3977820Sroot 			return (EFAULT);
3987820Sroot 		break;
3997820Sroot 	}
4007820Sroot 	iov->iov_base++;
4017820Sroot 	iov->iov_len--;
4027820Sroot 	uio->uio_resid--;
4037820Sroot 	uio->uio_offset++;
4047820Sroot 	return (0);
4057820Sroot }
4067820Sroot 
4077820Sroot /*
4087820Sroot  * Get next character written in by user from uio.
4097820Sroot  */
4107820Sroot uwritec(uio)
4117820Sroot 	struct uio *uio;
4127820Sroot {
4137820Sroot 	register struct iovec *iov;
4147820Sroot 	register int c;
4157820Sroot 
4167820Sroot again:
4177820Sroot 	if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0)
4187820Sroot 		panic("uwritec");
4197820Sroot 	iov = uio->uio_iov;
4207820Sroot 	if (iov->iov_len == 0) {
4217820Sroot 		uio->uio_iovcnt--;
4227820Sroot 		uio->uio_iov++;
4237820Sroot 		goto again;
4247820Sroot 	}
4257820Sroot 	switch (uio->uio_segflg) {
4267820Sroot 
4277820Sroot 	case 0:
4287820Sroot 		c = fubyte(iov->iov_base);
4297820Sroot 		break;
4307820Sroot 
4317820Sroot 	case 1:
4327820Sroot 		c = *iov->iov_base & 0377;
4337820Sroot 		break;
4347820Sroot 
4357820Sroot 	case 2:
4367820Sroot 		c = fuibyte(iov->iov_base);
4377820Sroot 		break;
4387820Sroot 	}
4397820Sroot 	if (c < 0)
4407820Sroot 		return (-1);
4417820Sroot 	iov->iov_base++;
4427820Sroot 	iov->iov_len--;
4437820Sroot 	uio->uio_resid--;
4447820Sroot 	uio->uio_offset++;
4457820Sroot 	return (c & 0377);
4467820Sroot }
4477820Sroot 
4487820Sroot /*
4497423Sroot  * Ioctl system call
4507624Ssam  * Check legality, execute common code,
4517624Ssam  * and switch out to individual device routine.
4527423Sroot  */
4537423Sroot ioctl()
4547423Sroot {
4557423Sroot 	register struct file *fp;
4567624Ssam 	struct a {
4577423Sroot 		int	fdes;
4587423Sroot 		int	cmd;
4597423Sroot 		caddr_t	cmarg;
4607423Sroot 	} *uap;
4617820Sroot 	register int com;
4627820Sroot 	register u_int size;
4637624Ssam 	char data[IOCPARM_MASK+1];
4647423Sroot 
4657423Sroot 	uap = (struct a *)u.u_ap;
4667423Sroot 	if ((fp = getf(uap->fdes)) == NULL)
4677423Sroot 		return;
4687423Sroot 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
4697423Sroot 		u.u_error = EBADF;
4707423Sroot 		return;
4717423Sroot 	}
4727624Ssam 	com = uap->cmd;
4737624Ssam 
4747699Ssam #ifndef NOCOMPAT
4757624Ssam 	/*
4767624Ssam 	 * Map old style ioctl's into new for the
4777624Ssam 	 * sake of backwards compatibility (sigh).
4787624Ssam 	 */
4797624Ssam 	if ((com&~0xffff) == 0) {
4807624Ssam 		com = mapioctl(com);
4817624Ssam 		if (com == 0) {
4827624Ssam 			u.u_error = EINVAL;
4837624Ssam 			return;
4847624Ssam 		}
4857624Ssam 	}
4867624Ssam #endif
4877624Ssam 	if (com == FIOCLEX) {
4887423Sroot 		u.u_pofile[uap->fdes] |= EXCLOSE;
4897423Sroot 		return;
4907423Sroot 	}
4917624Ssam 	if (com == FIONCLEX) {
4927423Sroot 		u.u_pofile[uap->fdes] &= ~EXCLOSE;
4937423Sroot 		return;
4947423Sroot 	}
4957624Ssam 
4967624Ssam 	/*
4977624Ssam 	 * Interpret high order word to find
4987624Ssam 	 * amount of data to be copied to/from the
4997624Ssam 	 * user's address space.
5007624Ssam 	 */
5017624Ssam 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
5027624Ssam 	if (size > sizeof (data)) {
5037624Ssam 		u.u_error = EFAULT;
5047423Sroot 		return;
5057423Sroot 	}
5067699Ssam 	if (com&IOC_IN && size) {
5077820Sroot 		if (copyin(uap->cmarg, (caddr_t)data, (u_int)size)) {
5087624Ssam 			u.u_error = EFAULT;
5097624Ssam 			return;
5107624Ssam 		}
5117624Ssam 	} else
5127624Ssam 		*(caddr_t *)data = uap->cmarg;
5137624Ssam 	/*
5147624Ssam 	 * Zero the buffer on the stack so the user
5157624Ssam 	 * always gets back something deterministic.
5167624Ssam 	 */
5177624Ssam 	if ((com&IOC_OUT) && size)
5187624Ssam 		bzero((caddr_t)data, size);
5197423Sroot 
5207624Ssam 	if (fp->f_type == DTYPE_SOCKET)
521*8564Sroot 		u.u_error = soioctl(fp->f_socket, com, data);
5227624Ssam 	else {
5237624Ssam 		register struct inode *ip = fp->f_inode;
5247624Ssam 		int fmt = ip->i_mode & IFMT;
5257624Ssam 		dev_t dev;
5267624Ssam 
5277624Ssam 		if (fmt != IFCHR) {
5287624Ssam 			if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) {
5297624Ssam 				*(off_t *)data = ip->i_size - fp->f_offset;
5307624Ssam 				goto returndata;
5317624Ssam 			}
5327624Ssam 			if (com != FIONBIO && com != FIOASYNC)
5337624Ssam 				u.u_error = ENOTTY;
5347423Sroot 			return;
5357624Ssam 		}
5367624Ssam 		dev = ip->i_rdev;
5377624Ssam 		u.u_r.r_val1 = 0;
5388118Sroot 		if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
5397624Ssam 			u.u_eosys = RESTARTSYS;
5407624Ssam 			return;
5417624Ssam 		}
542*8564Sroot 		u.u_error = (*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0);
5437423Sroot 	}
5447624Ssam 
5457624Ssam returndata:
5467624Ssam 	/*
5477624Ssam 	 * Copy any data to user, size was
5487624Ssam 	 * already set and checked above.
5497624Ssam 	 */
5507820Sroot 	if (u.u_error == 0 && (com&IOC_OUT))
5517820Sroot 		if (size && copyout(data, uap->cmarg, (u_int)size))
5527699Ssam 			u.u_error = EFAULT;
5537423Sroot }
5547423Sroot 
5557423Sroot /*
5567423Sroot  * Do nothing specific version of line
5577423Sroot  * discipline specific ioctl command.
5587423Sroot  */
5597423Sroot /*ARGSUSED*/
5607624Ssam nullioctl(tp, cmd, data, flags)
5617423Sroot 	struct tty *tp;
5627624Ssam 	char *data;
5637624Ssam 	int flags;
5647423Sroot {
5657423Sroot 
5667624Ssam #ifdef lint
5677624Ssam 	tp = tp; data = data; flags = flags;
5687624Ssam #endif
569*8564Sroot 	return (-1);
5707423Sroot }
5718103Sroot 
5728103Sroot ostty()
5738103Sroot {
5748103Sroot 
5758103Sroot }
5768103Sroot 
5778103Sroot ogtty()
5788103Sroot {
5798103Sroot 
5808103Sroot }
581