xref: /csrg-svn/sys/kern/sys_generic.c (revision 9999)
1*9999Ssam /*	sys_generic.c	5.29	82/12/28	*/
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/tty.h"
97423Sroot #include "../h/file.h"
107423Sroot #include "../h/inode.h"
117423Sroot #include "../h/buf.h"
127423Sroot #include "../h/proc.h"
137423Sroot #include "../h/conf.h"
147423Sroot #include "../h/socket.h"
157423Sroot #include "../h/socketvar.h"
167423Sroot #include "../h/fs.h"
177487Skre #ifdef MUSH
187487Skre #include "../h/quota.h"
197487Skre #include "../h/share.h"
207487Skre #else
217487Skre #define	CHARGE(nothing)
227487Skre #endif
237500Sroot #include "../h/descrip.h"
247714Sroot #include "../h/uio.h"
258668Sroot #include "../h/cmap.h"
267423Sroot 
277423Sroot /*
287423Sroot  * Read system call.
297423Sroot  */
307423Sroot read()
317423Sroot {
327423Sroot 	register struct a {
337423Sroot 		int	fdes;
347423Sroot 		char	*cbuf;
357423Sroot 		unsigned count;
367820Sroot 	} *uap = (struct a *)u.u_ap;
377746Sroot 	struct uio auio;
387746Sroot 	struct iovec aiov;
397423Sroot 
407820Sroot 	aiov.iov_base = (caddr_t)uap->cbuf;
417820Sroot 	aiov.iov_len = uap->count;
427820Sroot 	auio.uio_iov = &aiov;
437820Sroot 	auio.uio_iovcnt = 1;
447820Sroot 	rwuio(&auio, UIO_READ);
457820Sroot }
467820Sroot 
477820Sroot readv()
487820Sroot {
497820Sroot 	register struct a {
507820Sroot 		int	fdes;
517820Sroot 		struct	iovec *iovp;
527820Sroot 		int	iovcnt;
537820Sroot 	} *uap = (struct a *)u.u_ap;
547820Sroot 	struct uio auio;
557820Sroot 	struct iovec aiov[16];		/* XXX */
567820Sroot 
577820Sroot 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
587423Sroot 		u.u_error = EINVAL;
597423Sroot 		return;
607423Sroot 	}
617820Sroot 	auio.uio_iov = aiov;
627820Sroot 	auio.uio_iovcnt = uap->iovcnt;
63*9999Ssam 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
64*9999Ssam 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
65*9999Ssam 	if (u.u_error)
667423Sroot 		return;
677820Sroot 	rwuio(&auio, UIO_READ);
687423Sroot }
697423Sroot 
707423Sroot /*
717423Sroot  * Write system call
727423Sroot  */
737423Sroot write()
747423Sroot {
757423Sroot 	register struct a {
767423Sroot 		int	fdes;
777423Sroot 		char	*cbuf;
787820Sroot 		int	count;
797820Sroot 	} *uap = (struct a *)u.u_ap;
807820Sroot 	struct uio auio;
817820Sroot 	struct iovec aiov;
827423Sroot 
837820Sroot 	auio.uio_iov = &aiov;
847820Sroot 	auio.uio_iovcnt = 1;
857820Sroot 	aiov.iov_base = uap->cbuf;
867820Sroot 	aiov.iov_len = uap->count;
877820Sroot 	rwuio(&auio, UIO_WRITE);
887820Sroot }
897820Sroot 
907820Sroot writev()
917820Sroot {
927820Sroot 	register struct a {
937820Sroot 		int	fdes;
947820Sroot 		struct	iovec *iovp;
957820Sroot 		int	iovcnt;
967820Sroot 	} *uap = (struct a *)u.u_ap;
977820Sroot 	struct uio auio;
987820Sroot 	struct iovec aiov[16];		/* XXX */
997820Sroot 
1007820Sroot 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
1017423Sroot 		u.u_error = EINVAL;
1027423Sroot 		return;
1037423Sroot 	}
1047820Sroot 	auio.uio_iov = aiov;
1057820Sroot 	auio.uio_iovcnt = uap->iovcnt;
106*9999Ssam 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
107*9999Ssam 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
108*9999Ssam 	if (u.u_error)
1097820Sroot 		return;
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;
2038668Sroot 	register int n, on, type;
2047820Sroot 	int size;
2057820Sroot 	long bsize;
2067820Sroot 	extern int mem_no;
2077820Sroot 	int error = 0;
2087500Sroot 
2097820Sroot 	if (rw != UIO_READ && rw != UIO_WRITE)
2107820Sroot 		panic("rwip");
2119270Ssam 	if (rw == UIO_READ && uio->uio_resid == 0)
2129270Ssam 		return (0);
2137820Sroot 	if (uio->uio_offset < 0 &&
2147820Sroot 	    ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)))
2159155Ssam 		return (EINVAL);
2169155Ssam 	if (rw == UIO_READ)
2177820Sroot 		ip->i_flag |= IACC;
2187820Sroot 	type = ip->i_mode&IFMT;
2197820Sroot 	if (type == IFCHR) {
2207820Sroot #ifdef QUOTA
2217820Sroot 		register c = uio->uio_resid;
2227820Sroot #endif
2237820Sroot 		if (rw == UIO_READ)
2248519Sroot 			u.u_error = (*cdevsw[major(dev)].d_read)(dev, uio);
2257820Sroot 		else {
2267820Sroot 			ip->i_flag |= IUPD|ICHG;
2278519Sroot 			u.u_error = (*cdevsw[major(dev)].d_write)(dev, uio);
2287820Sroot 		}
2297820Sroot 		CHARGE(sc_tio * (c - uio->uio_resid));
2307820Sroot 		return (u.u_error);
2317820Sroot 	}
2329155Ssam 	if (uio->uio_resid == 0)
2339270Ssam 		return (0);
2347820Sroot 	if (rw == UIO_WRITE && type == IFREG &&
2358036Sroot 	    uio->uio_offset + uio->uio_resid >
2368036Sroot 	      u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
2377820Sroot 		psignal(u.u_procp, SIGXFSZ);
2387820Sroot 		return (EMFILE);
2397820Sroot 	}
2407820Sroot 	if (type != IFBLK) {
2417820Sroot 		dev = ip->i_dev;
2427820Sroot 		fs = ip->i_fs;
2437820Sroot 		bsize = fs->fs_bsize;
2447820Sroot 	} else
2457820Sroot 		bsize = BLKDEV_IOSIZE;
2467820Sroot 	do {
2477820Sroot 		lbn = uio->uio_offset / bsize;
2487820Sroot 		on = uio->uio_offset % bsize;
2497820Sroot 		n = MIN((unsigned)(bsize - on), uio->uio_resid);
2507820Sroot 		if (type != IFBLK) {
2517820Sroot 			if (rw == UIO_READ) {
2527820Sroot 				int diff = ip->i_size - uio->uio_offset;
2537820Sroot 				if (diff <= 0)
2547820Sroot 					return (0);
2557820Sroot 				if (diff < n)
2567820Sroot 					n = diff;
2577820Sroot 			}
2587820Sroot 			bn = fsbtodb(fs,
2597820Sroot 			    bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n)));
2607820Sroot 			if (u.u_error || rw == UIO_WRITE && (long)bn<0)
2617820Sroot 				return (u.u_error);
2627820Sroot 			if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size &&
2637820Sroot 			   (type == IFDIR || type == IFREG || type == IFLNK))
2647820Sroot 				ip->i_size = uio->uio_offset + n;
2657820Sroot 			size = blksize(fs, ip, lbn);
2667820Sroot 		} else {
2677820Sroot 			bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE);
2687820Sroot 			rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE);
2697820Sroot 			rasize = size = bsize;
2707820Sroot 		}
2717820Sroot 		if (rw == UIO_READ) {
2727820Sroot 			if ((long)bn<0) {
2737820Sroot 				bp = geteblk(size);
2747820Sroot 				clrbuf(bp);
2757820Sroot 			} else if (ip->i_lastr + 1 == lbn)
2767820Sroot 				bp = breada(dev, bn, size, rablock, rasize);
2777820Sroot 			else
2787820Sroot 				bp = bread(dev, bn, size);
2797820Sroot 			ip->i_lastr = lbn;
2807820Sroot 		} else {
2817820Sroot 			int i, count;
2828626Sroot 			extern struct cmap *mfind();
2837820Sroot 
2847820Sroot 			count = howmany(size, DEV_BSIZE);
2857820Sroot 			for (i = 0; i < count; i += CLSIZE)
2867820Sroot 				if (mfind(dev, bn + i))
2877820Sroot 					munhash(dev, bn + i);
2887820Sroot 			if (n == bsize)
2897820Sroot 				bp = getblk(dev, bn, size);
2907820Sroot 			else
2917820Sroot 				bp = bread(dev, bn, size);
2927820Sroot 		}
2937820Sroot 		n = MIN(n, size - bp->b_resid);
2947820Sroot 		if (bp->b_flags & B_ERROR) {
2957820Sroot 			error = EIO;
2967820Sroot 			brelse(bp);
2977820Sroot 			goto bad;
2987820Sroot 		}
2997820Sroot 		u.u_error =
3008791Sroot 		    uiomove(bp->b_un.b_addr+on, n, rw, uio);
3017820Sroot 		if (rw == UIO_READ) {
3027820Sroot 			if (n + on == bsize || uio->uio_offset == ip->i_size)
3037820Sroot 				bp->b_flags |= B_AGE;
3047820Sroot 			brelse(bp);
3057820Sroot 		} else {
3067820Sroot 			if ((ip->i_mode&IFMT) == IFDIR)
3077820Sroot 				bwrite(bp);
3087820Sroot 			else if (n + on == bsize) {
3097820Sroot 				bp->b_flags |= B_AGE;
3107820Sroot 				bawrite(bp);
3117820Sroot 			} else
3127820Sroot 				bdwrite(bp);
3137820Sroot 			ip->i_flag |= IUPD|ICHG;
3147820Sroot 			if (u.u_ruid != 0)
3157820Sroot 				ip->i_mode &= ~(ISUID|ISGID);
3167820Sroot 		}
3177820Sroot 	} while (u.u_error == 0 && uio->uio_resid > 0 && n != 0);
3187820Sroot bad:
3197820Sroot 	return (error);
3207500Sroot }
3217500Sroot 
3227820Sroot uiomove(cp, n, rw, uio)
3237820Sroot 	register caddr_t cp;
3247820Sroot 	register int n;
3257820Sroot 	enum uio_rw rw;
3267820Sroot 	register struct uio *uio;
3277820Sroot {
3287820Sroot 	register struct iovec *iov;
3297820Sroot 	u_int cnt;
3309864Ssam 	int error = 0;
3317820Sroot 
3327820Sroot 	while (n > 0 && uio->uio_resid) {
3337820Sroot 		iov = uio->uio_iov;
3347820Sroot 		cnt = iov->iov_len;
3357820Sroot 		if (cnt == 0) {
3367820Sroot 			uio->uio_iov++;
3377820Sroot 			uio->uio_iovcnt--;
3387820Sroot 			continue;
3397820Sroot 		}
3407820Sroot 		if (cnt > n)
3417820Sroot 			cnt = n;
3427820Sroot 		switch (uio->uio_segflg) {
3437820Sroot 
3447820Sroot 		case 0:
3457820Sroot 		case 2:
3467820Sroot 			if (rw == UIO_READ)
3477820Sroot 				error = copyout(cp, iov->iov_base, cnt);
3487820Sroot 			else
3497820Sroot 				error = copyin(iov->iov_base, cp, cnt);
3507820Sroot 			if (error)
351*9999Ssam 				return (error);
3527820Sroot 			break;
3537820Sroot 
3547820Sroot 		case 1:
3557820Sroot 			if (rw == UIO_READ)
3567820Sroot 				bcopy((caddr_t)cp, iov->iov_base, cnt);
3577820Sroot 			else
3587820Sroot 				bcopy(iov->iov_base, (caddr_t)cp, cnt);
3597820Sroot 			break;
3607820Sroot 		}
3617820Sroot 		iov->iov_base += cnt;
3627820Sroot 		iov->iov_len -= cnt;
3637820Sroot 		uio->uio_resid -= cnt;
3647820Sroot 		uio->uio_offset += cnt;
3657820Sroot 		cp += cnt;
3667820Sroot 		n -= cnt;
3677820Sroot 	}
3687820Sroot 	return (error);
3697820Sroot }
3707820Sroot 
3717423Sroot /*
3727820Sroot  * Give next character to user as result of read.
3737820Sroot  */
3747820Sroot ureadc(c, uio)
3757820Sroot 	register int c;
3767820Sroot 	register struct uio *uio;
3777820Sroot {
3787820Sroot 	register struct iovec *iov;
3797820Sroot 
3807820Sroot again:
3817820Sroot 	if (uio->uio_iovcnt == 0)
3827820Sroot 		panic("ureadc");
3837820Sroot 	iov = uio->uio_iov;
3847820Sroot 	if (iov->iov_len <= 0 || uio->uio_resid <= 0) {
3857820Sroot 		uio->uio_iovcnt--;
3867820Sroot 		uio->uio_iov++;
3877820Sroot 		goto again;
3887820Sroot 	}
3897820Sroot 	switch (uio->uio_segflg) {
3907820Sroot 
3917820Sroot 	case 0:
3927820Sroot 		if (subyte(iov->iov_base, c) < 0)
3937820Sroot 			return (EFAULT);
3947820Sroot 		break;
3957820Sroot 
3967820Sroot 	case 1:
3977820Sroot 		*iov->iov_base = c;
3987820Sroot 		break;
3997820Sroot 
4007820Sroot 	case 2:
4017820Sroot 		if (suibyte(iov->iov_base, c) < 0)
4027820Sroot 			return (EFAULT);
4037820Sroot 		break;
4047820Sroot 	}
4057820Sroot 	iov->iov_base++;
4067820Sroot 	iov->iov_len--;
4077820Sroot 	uio->uio_resid--;
4087820Sroot 	uio->uio_offset++;
4097820Sroot 	return (0);
4107820Sroot }
4117820Sroot 
4128767Sroot #ifdef notdef
4137820Sroot /*
4147820Sroot  * Get next character written in by user from uio.
4157820Sroot  */
4167820Sroot uwritec(uio)
4177820Sroot 	struct uio *uio;
4187820Sroot {
4197820Sroot 	register struct iovec *iov;
4207820Sroot 	register int c;
4217820Sroot 
4227820Sroot again:
4237820Sroot 	if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0)
4247820Sroot 		panic("uwritec");
4257820Sroot 	iov = uio->uio_iov;
4267820Sroot 	if (iov->iov_len == 0) {
4277820Sroot 		uio->uio_iovcnt--;
4287820Sroot 		uio->uio_iov++;
4297820Sroot 		goto again;
4307820Sroot 	}
4317820Sroot 	switch (uio->uio_segflg) {
4327820Sroot 
4337820Sroot 	case 0:
4347820Sroot 		c = fubyte(iov->iov_base);
4357820Sroot 		break;
4367820Sroot 
4377820Sroot 	case 1:
4387820Sroot 		c = *iov->iov_base & 0377;
4397820Sroot 		break;
4407820Sroot 
4417820Sroot 	case 2:
4427820Sroot 		c = fuibyte(iov->iov_base);
4437820Sroot 		break;
4447820Sroot 	}
4457820Sroot 	if (c < 0)
4467820Sroot 		return (-1);
4477820Sroot 	iov->iov_base++;
4487820Sroot 	iov->iov_len--;
4497820Sroot 	uio->uio_resid--;
4507820Sroot 	uio->uio_offset++;
4517820Sroot 	return (c & 0377);
4527820Sroot }
4538767Sroot #endif
4547820Sroot 
4557820Sroot /*
4567423Sroot  * Ioctl system call
4577624Ssam  * Check legality, execute common code,
4587624Ssam  * and switch out to individual device routine.
4597423Sroot  */
4607423Sroot ioctl()
4617423Sroot {
4627423Sroot 	register struct file *fp;
4637624Ssam 	struct a {
4647423Sroot 		int	fdes;
4657423Sroot 		int	cmd;
4667423Sroot 		caddr_t	cmarg;
4677423Sroot 	} *uap;
4687820Sroot 	register int com;
4697820Sroot 	register u_int size;
4707624Ssam 	char data[IOCPARM_MASK+1];
4717423Sroot 
4727423Sroot 	uap = (struct a *)u.u_ap;
4737423Sroot 	if ((fp = getf(uap->fdes)) == NULL)
4747423Sroot 		return;
4757423Sroot 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
4767423Sroot 		u.u_error = EBADF;
4777423Sroot 		return;
4787423Sroot 	}
4797624Ssam 	com = uap->cmd;
4807624Ssam 
4817699Ssam #ifndef NOCOMPAT
4827624Ssam 	/*
4837624Ssam 	 * Map old style ioctl's into new for the
4847624Ssam 	 * sake of backwards compatibility (sigh).
4857624Ssam 	 */
4867624Ssam 	if ((com&~0xffff) == 0) {
4877624Ssam 		com = mapioctl(com);
4887624Ssam 		if (com == 0) {
4897624Ssam 			u.u_error = EINVAL;
4907624Ssam 			return;
4917624Ssam 		}
4927624Ssam 	}
4937624Ssam #endif
4947624Ssam 	if (com == FIOCLEX) {
4959592Ssam 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
4967423Sroot 		return;
4977423Sroot 	}
4987624Ssam 	if (com == FIONCLEX) {
4999592Ssam 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
5007423Sroot 		return;
5017423Sroot 	}
5027624Ssam 
5037624Ssam 	/*
5047624Ssam 	 * Interpret high order word to find
5057624Ssam 	 * amount of data to be copied to/from the
5067624Ssam 	 * user's address space.
5077624Ssam 	 */
5087624Ssam 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
5097624Ssam 	if (size > sizeof (data)) {
5107624Ssam 		u.u_error = EFAULT;
5117423Sroot 		return;
5127423Sroot 	}
5137699Ssam 	if (com&IOC_IN && size) {
514*9999Ssam 		u.u_error = copyin(uap->cmarg, (caddr_t)data, (u_int)size);
515*9999Ssam 		if (u.u_error)
5167624Ssam 			return;
5177624Ssam 	} else
5187624Ssam 		*(caddr_t *)data = uap->cmarg;
5197624Ssam 	/*
5207624Ssam 	 * Zero the buffer on the stack so the user
5217624Ssam 	 * always gets back something deterministic.
5227624Ssam 	 */
5237624Ssam 	if ((com&IOC_OUT) && size)
5247624Ssam 		bzero((caddr_t)data, size);
5257423Sroot 
5267624Ssam 	if (fp->f_type == DTYPE_SOCKET)
5278564Sroot 		u.u_error = soioctl(fp->f_socket, com, data);
5287624Ssam 	else {
5297624Ssam 		register struct inode *ip = fp->f_inode;
5307624Ssam 		int fmt = ip->i_mode & IFMT;
5317624Ssam 		dev_t dev;
5327624Ssam 
5337624Ssam 		if (fmt != IFCHR) {
5347624Ssam 			if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) {
5357624Ssam 				*(off_t *)data = ip->i_size - fp->f_offset;
5367624Ssam 				goto returndata;
5377624Ssam 			}
5387624Ssam 			if (com != FIONBIO && com != FIOASYNC)
5397624Ssam 				u.u_error = ENOTTY;
5407423Sroot 			return;
5417624Ssam 		}
5427624Ssam 		dev = ip->i_rdev;
5437624Ssam 		u.u_r.r_val1 = 0;
5448118Sroot 		if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
5457624Ssam 			u.u_eosys = RESTARTSYS;
5467624Ssam 			return;
5477624Ssam 		}
5488564Sroot 		u.u_error = (*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0);
5497423Sroot 	}
5507624Ssam 
5517624Ssam returndata:
5527624Ssam 	/*
5537624Ssam 	 * Copy any data to user, size was
5547624Ssam 	 * already set and checked above.
5557624Ssam 	 */
556*9999Ssam 	if (u.u_error == 0 && (com&IOC_OUT) && size)
557*9999Ssam 		u.u_error = copyout(data, uap->cmarg, (u_int)size);
5587423Sroot }
5597423Sroot 
5607423Sroot /*
5617423Sroot  * Do nothing specific version of line
5627423Sroot  * discipline specific ioctl command.
5637423Sroot  */
5647423Sroot /*ARGSUSED*/
5657624Ssam nullioctl(tp, cmd, data, flags)
5667423Sroot 	struct tty *tp;
5677624Ssam 	char *data;
5687624Ssam 	int flags;
5697423Sroot {
5707423Sroot 
5717624Ssam #ifdef lint
5727624Ssam 	tp = tp; data = data; flags = flags;
5737624Ssam #endif
5748564Sroot 	return (-1);
5757423Sroot }
5768103Sroot 
5778103Sroot ostty()
5788103Sroot {
5798103Sroot 
5808103Sroot }
5818103Sroot 
5828103Sroot ogtty()
5838103Sroot {
5848103Sroot 
5858103Sroot }
586