xref: /csrg-svn/sys/kern/sys_generic.c (revision 11148)
1*11148Ssam /*	sys_generic.c	5.31	83/02/18	*/
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;
639999Ssam 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
649999Ssam 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
659999Ssam 	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;
1069999Ssam 	u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
1079999Ssam 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)));
1089999Ssam 	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);
158*11148Ssam 			if (fp->f_flag&FAPPEND && rw == UIO_WRITE)
159*11148Ssam 				uio->uio_offset = fp->f_offset = ip->i_size;
1607820Sroot 			u.u_error = rwip(ip, uio, rw);
1618449Sroot 			IUNLOCK(ip);
1627423Sroot 		} else
1637820Sroot 			u.u_error = rwip(ip, uio, rw);
1647820Sroot 		fp->f_offset += count - uio->uio_resid;
1657423Sroot 	}
1667820Sroot 	u.u_r.r_val1 = count - uio->uio_resid;
1677423Sroot }
1687423Sroot 
1697820Sroot rdwri(rw, ip, base, len, offset, segflg, aresid)
1707820Sroot 	struct inode *ip;
1717820Sroot 	caddr_t base;
1727820Sroot 	int len, offset, segflg;
1737820Sroot 	int *aresid;
1747820Sroot 	enum uio_rw rw;
1757500Sroot {
1767820Sroot 	struct uio auio;
1777820Sroot 	struct iovec aiov;
1787820Sroot 	int error;
1797423Sroot 
1807820Sroot 	auio.uio_iov = &aiov;
1817820Sroot 	auio.uio_iovcnt = 1;
1827820Sroot 	aiov.iov_base = base;
1837820Sroot 	aiov.iov_len = len;
1847820Sroot 	auio.uio_resid = len;
1857820Sroot 	auio.uio_offset = offset;
1867820Sroot 	auio.uio_segflg = segflg;
1877820Sroot 	error = rwip(ip, &auio, rw);
1887820Sroot 	if (aresid)
1897820Sroot 		*aresid = auio.uio_resid;
1907820Sroot 	else
1917820Sroot 		if (auio.uio_resid)
1927820Sroot 			error = EIO;
1937820Sroot 	return (error);
1947500Sroot }
1957500Sroot 
1967820Sroot rwip(ip, uio, rw)
1977820Sroot 	register struct inode *ip;
1987820Sroot 	register struct uio *uio;
1997820Sroot 	enum uio_rw rw;
2007500Sroot {
2017820Sroot 	dev_t dev = (dev_t)ip->i_rdev;
2027820Sroot 	struct buf *bp;
2037820Sroot 	struct fs *fs;
2047820Sroot 	daddr_t lbn, bn;
2058668Sroot 	register int n, on, type;
2067820Sroot 	int size;
2077820Sroot 	long bsize;
2087820Sroot 	extern int mem_no;
2097820Sroot 	int error = 0;
2107500Sroot 
2117820Sroot 	if (rw != UIO_READ && rw != UIO_WRITE)
2127820Sroot 		panic("rwip");
2139270Ssam 	if (rw == UIO_READ && uio->uio_resid == 0)
2149270Ssam 		return (0);
2157820Sroot 	if (uio->uio_offset < 0 &&
2167820Sroot 	    ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)))
2179155Ssam 		return (EINVAL);
2189155Ssam 	if (rw == UIO_READ)
2197820Sroot 		ip->i_flag |= IACC;
2207820Sroot 	type = ip->i_mode&IFMT;
2217820Sroot 	if (type == IFCHR) {
2227820Sroot #ifdef QUOTA
2237820Sroot 		register c = uio->uio_resid;
2247820Sroot #endif
2257820Sroot 		if (rw == UIO_READ)
2268519Sroot 			u.u_error = (*cdevsw[major(dev)].d_read)(dev, uio);
2277820Sroot 		else {
2287820Sroot 			ip->i_flag |= IUPD|ICHG;
2298519Sroot 			u.u_error = (*cdevsw[major(dev)].d_write)(dev, uio);
2307820Sroot 		}
2317820Sroot 		CHARGE(sc_tio * (c - uio->uio_resid));
2327820Sroot 		return (u.u_error);
2337820Sroot 	}
2349155Ssam 	if (uio->uio_resid == 0)
2359270Ssam 		return (0);
2367820Sroot 	if (rw == UIO_WRITE && type == IFREG &&
2378036Sroot 	    uio->uio_offset + uio->uio_resid >
2388036Sroot 	      u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
2397820Sroot 		psignal(u.u_procp, SIGXFSZ);
2407820Sroot 		return (EMFILE);
2417820Sroot 	}
2427820Sroot 	if (type != IFBLK) {
2437820Sroot 		dev = ip->i_dev;
2447820Sroot 		fs = ip->i_fs;
2457820Sroot 		bsize = fs->fs_bsize;
2467820Sroot 	} else
2477820Sroot 		bsize = BLKDEV_IOSIZE;
2487820Sroot 	do {
2497820Sroot 		lbn = uio->uio_offset / bsize;
2507820Sroot 		on = uio->uio_offset % bsize;
2517820Sroot 		n = MIN((unsigned)(bsize - on), uio->uio_resid);
2527820Sroot 		if (type != IFBLK) {
2537820Sroot 			if (rw == UIO_READ) {
2547820Sroot 				int diff = ip->i_size - uio->uio_offset;
2557820Sroot 				if (diff <= 0)
2567820Sroot 					return (0);
2577820Sroot 				if (diff < n)
2587820Sroot 					n = diff;
2597820Sroot 			}
2607820Sroot 			bn = fsbtodb(fs,
2617820Sroot 			    bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n)));
2627820Sroot 			if (u.u_error || rw == UIO_WRITE && (long)bn<0)
2637820Sroot 				return (u.u_error);
2647820Sroot 			if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size &&
2657820Sroot 			   (type == IFDIR || type == IFREG || type == IFLNK))
2667820Sroot 				ip->i_size = uio->uio_offset + n;
2677820Sroot 			size = blksize(fs, ip, lbn);
2687820Sroot 		} else {
2697820Sroot 			bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE);
2707820Sroot 			rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE);
2717820Sroot 			rasize = size = bsize;
2727820Sroot 		}
2737820Sroot 		if (rw == UIO_READ) {
2747820Sroot 			if ((long)bn<0) {
2757820Sroot 				bp = geteblk(size);
2767820Sroot 				clrbuf(bp);
2777820Sroot 			} else if (ip->i_lastr + 1 == lbn)
2787820Sroot 				bp = breada(dev, bn, size, rablock, rasize);
2797820Sroot 			else
2807820Sroot 				bp = bread(dev, bn, size);
2817820Sroot 			ip->i_lastr = lbn;
2827820Sroot 		} else {
2837820Sroot 			int i, count;
2848626Sroot 			extern struct cmap *mfind();
2857820Sroot 
2867820Sroot 			count = howmany(size, DEV_BSIZE);
2877820Sroot 			for (i = 0; i < count; i += CLSIZE)
2887820Sroot 				if (mfind(dev, bn + i))
2897820Sroot 					munhash(dev, bn + i);
2907820Sroot 			if (n == bsize)
2917820Sroot 				bp = getblk(dev, bn, size);
2927820Sroot 			else
2937820Sroot 				bp = bread(dev, bn, size);
2947820Sroot 		}
2957820Sroot 		n = MIN(n, size - bp->b_resid);
2967820Sroot 		if (bp->b_flags & B_ERROR) {
2977820Sroot 			error = EIO;
2987820Sroot 			brelse(bp);
2997820Sroot 			goto bad;
3007820Sroot 		}
3017820Sroot 		u.u_error =
3028791Sroot 		    uiomove(bp->b_un.b_addr+on, n, rw, uio);
3037820Sroot 		if (rw == UIO_READ) {
3047820Sroot 			if (n + on == bsize || uio->uio_offset == ip->i_size)
3057820Sroot 				bp->b_flags |= B_AGE;
3067820Sroot 			brelse(bp);
3077820Sroot 		} else {
3087820Sroot 			if ((ip->i_mode&IFMT) == IFDIR)
3097820Sroot 				bwrite(bp);
3107820Sroot 			else if (n + on == bsize) {
3117820Sroot 				bp->b_flags |= B_AGE;
3127820Sroot 				bawrite(bp);
3137820Sroot 			} else
3147820Sroot 				bdwrite(bp);
3157820Sroot 			ip->i_flag |= IUPD|ICHG;
3167820Sroot 			if (u.u_ruid != 0)
3177820Sroot 				ip->i_mode &= ~(ISUID|ISGID);
3187820Sroot 		}
3197820Sroot 	} while (u.u_error == 0 && uio->uio_resid > 0 && n != 0);
3207820Sroot bad:
3217820Sroot 	return (error);
3227500Sroot }
3237500Sroot 
3247820Sroot uiomove(cp, n, rw, uio)
3257820Sroot 	register caddr_t cp;
3267820Sroot 	register int n;
3277820Sroot 	enum uio_rw rw;
3287820Sroot 	register struct uio *uio;
3297820Sroot {
3307820Sroot 	register struct iovec *iov;
3317820Sroot 	u_int cnt;
3329864Ssam 	int error = 0;
3337820Sroot 
3347820Sroot 	while (n > 0 && uio->uio_resid) {
3357820Sroot 		iov = uio->uio_iov;
3367820Sroot 		cnt = iov->iov_len;
3377820Sroot 		if (cnt == 0) {
3387820Sroot 			uio->uio_iov++;
3397820Sroot 			uio->uio_iovcnt--;
3407820Sroot 			continue;
3417820Sroot 		}
3427820Sroot 		if (cnt > n)
3437820Sroot 			cnt = n;
3447820Sroot 		switch (uio->uio_segflg) {
3457820Sroot 
3467820Sroot 		case 0:
3477820Sroot 		case 2:
3487820Sroot 			if (rw == UIO_READ)
3497820Sroot 				error = copyout(cp, iov->iov_base, cnt);
3507820Sroot 			else
3517820Sroot 				error = copyin(iov->iov_base, cp, cnt);
3527820Sroot 			if (error)
3539999Ssam 				return (error);
3547820Sroot 			break;
3557820Sroot 
3567820Sroot 		case 1:
3577820Sroot 			if (rw == UIO_READ)
3587820Sroot 				bcopy((caddr_t)cp, iov->iov_base, cnt);
3597820Sroot 			else
3607820Sroot 				bcopy(iov->iov_base, (caddr_t)cp, cnt);
3617820Sroot 			break;
3627820Sroot 		}
3637820Sroot 		iov->iov_base += cnt;
3647820Sroot 		iov->iov_len -= cnt;
3657820Sroot 		uio->uio_resid -= cnt;
3667820Sroot 		uio->uio_offset += cnt;
3677820Sroot 		cp += cnt;
3687820Sroot 		n -= cnt;
3697820Sroot 	}
3707820Sroot 	return (error);
3717820Sroot }
3727820Sroot 
3737423Sroot /*
3747820Sroot  * Give next character to user as result of read.
3757820Sroot  */
3767820Sroot ureadc(c, uio)
3777820Sroot 	register int c;
3787820Sroot 	register struct uio *uio;
3797820Sroot {
3807820Sroot 	register struct iovec *iov;
3817820Sroot 
3827820Sroot again:
3837820Sroot 	if (uio->uio_iovcnt == 0)
3847820Sroot 		panic("ureadc");
3857820Sroot 	iov = uio->uio_iov;
3867820Sroot 	if (iov->iov_len <= 0 || uio->uio_resid <= 0) {
3877820Sroot 		uio->uio_iovcnt--;
3887820Sroot 		uio->uio_iov++;
3897820Sroot 		goto again;
3907820Sroot 	}
3917820Sroot 	switch (uio->uio_segflg) {
3927820Sroot 
3937820Sroot 	case 0:
3947820Sroot 		if (subyte(iov->iov_base, c) < 0)
3957820Sroot 			return (EFAULT);
3967820Sroot 		break;
3977820Sroot 
3987820Sroot 	case 1:
3997820Sroot 		*iov->iov_base = c;
4007820Sroot 		break;
4017820Sroot 
4027820Sroot 	case 2:
4037820Sroot 		if (suibyte(iov->iov_base, c) < 0)
4047820Sroot 			return (EFAULT);
4057820Sroot 		break;
4067820Sroot 	}
4077820Sroot 	iov->iov_base++;
4087820Sroot 	iov->iov_len--;
4097820Sroot 	uio->uio_resid--;
4107820Sroot 	uio->uio_offset++;
4117820Sroot 	return (0);
4127820Sroot }
4137820Sroot 
4148767Sroot #ifdef notdef
4157820Sroot /*
4167820Sroot  * Get next character written in by user from uio.
4177820Sroot  */
4187820Sroot uwritec(uio)
4197820Sroot 	struct uio *uio;
4207820Sroot {
4217820Sroot 	register struct iovec *iov;
4227820Sroot 	register int c;
4237820Sroot 
4247820Sroot again:
4257820Sroot 	if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0)
4267820Sroot 		panic("uwritec");
4277820Sroot 	iov = uio->uio_iov;
4287820Sroot 	if (iov->iov_len == 0) {
4297820Sroot 		uio->uio_iovcnt--;
4307820Sroot 		uio->uio_iov++;
4317820Sroot 		goto again;
4327820Sroot 	}
4337820Sroot 	switch (uio->uio_segflg) {
4347820Sroot 
4357820Sroot 	case 0:
4367820Sroot 		c = fubyte(iov->iov_base);
4377820Sroot 		break;
4387820Sroot 
4397820Sroot 	case 1:
4407820Sroot 		c = *iov->iov_base & 0377;
4417820Sroot 		break;
4427820Sroot 
4437820Sroot 	case 2:
4447820Sroot 		c = fuibyte(iov->iov_base);
4457820Sroot 		break;
4467820Sroot 	}
4477820Sroot 	if (c < 0)
4487820Sroot 		return (-1);
4497820Sroot 	iov->iov_base++;
4507820Sroot 	iov->iov_len--;
4517820Sroot 	uio->uio_resid--;
4527820Sroot 	uio->uio_offset++;
4537820Sroot 	return (c & 0377);
4547820Sroot }
4558767Sroot #endif
4567820Sroot 
4577820Sroot /*
4587423Sroot  * Ioctl system call
4597624Ssam  * Check legality, execute common code,
4607624Ssam  * and switch out to individual device routine.
4617423Sroot  */
4627423Sroot ioctl()
4637423Sroot {
4647423Sroot 	register struct file *fp;
4657624Ssam 	struct a {
4667423Sroot 		int	fdes;
4677423Sroot 		int	cmd;
4687423Sroot 		caddr_t	cmarg;
4697423Sroot 	} *uap;
4707820Sroot 	register int com;
4717820Sroot 	register u_int size;
4727624Ssam 	char data[IOCPARM_MASK+1];
4737423Sroot 
4747423Sroot 	uap = (struct a *)u.u_ap;
4757423Sroot 	if ((fp = getf(uap->fdes)) == NULL)
4767423Sroot 		return;
4777423Sroot 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
4787423Sroot 		u.u_error = EBADF;
4797423Sroot 		return;
4807423Sroot 	}
4817624Ssam 	com = uap->cmd;
4827624Ssam 
4837699Ssam #ifndef NOCOMPAT
4847624Ssam 	/*
4857624Ssam 	 * Map old style ioctl's into new for the
4867624Ssam 	 * sake of backwards compatibility (sigh).
4877624Ssam 	 */
4887624Ssam 	if ((com&~0xffff) == 0) {
4897624Ssam 		com = mapioctl(com);
4907624Ssam 		if (com == 0) {
4917624Ssam 			u.u_error = EINVAL;
4927624Ssam 			return;
4937624Ssam 		}
4947624Ssam 	}
4957624Ssam #endif
4967624Ssam 	if (com == FIOCLEX) {
4979592Ssam 		u.u_pofile[uap->fdes] |= UF_EXCLOSE;
4987423Sroot 		return;
4997423Sroot 	}
5007624Ssam 	if (com == FIONCLEX) {
5019592Ssam 		u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
5027423Sroot 		return;
5037423Sroot 	}
5047624Ssam 
5057624Ssam 	/*
5067624Ssam 	 * Interpret high order word to find
5077624Ssam 	 * amount of data to be copied to/from the
5087624Ssam 	 * user's address space.
5097624Ssam 	 */
5107624Ssam 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
5117624Ssam 	if (size > sizeof (data)) {
5127624Ssam 		u.u_error = EFAULT;
5137423Sroot 		return;
5147423Sroot 	}
51510601Ssam 	if (com&IOC_IN) {
51610601Ssam 		if (size) {
51710601Ssam 			u.u_error =
51810601Ssam 			    copyin(uap->cmarg, (caddr_t)data, (u_int)size);
51910601Ssam 			if (u.u_error)
52010601Ssam 				return;
52110601Ssam 		} else
52210601Ssam 			*(caddr_t *)data = uap->cmarg;
52310601Ssam 	} else if ((com&IOC_OUT) && size)
52410601Ssam 		/*
52510601Ssam 		 * Zero the buffer on the stack so the user
52610601Ssam 		 * always gets back something deterministic.
52710601Ssam 		 */
5287624Ssam 		bzero((caddr_t)data, size);
5297423Sroot 
5307624Ssam 	if (fp->f_type == DTYPE_SOCKET)
5318564Sroot 		u.u_error = soioctl(fp->f_socket, com, data);
5327624Ssam 	else {
5337624Ssam 		register struct inode *ip = fp->f_inode;
5347624Ssam 		int fmt = ip->i_mode & IFMT;
5357624Ssam 		dev_t dev;
5367624Ssam 
5377624Ssam 		if (fmt != IFCHR) {
5387624Ssam 			if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) {
5397624Ssam 				*(off_t *)data = ip->i_size - fp->f_offset;
5407624Ssam 				goto returndata;
5417624Ssam 			}
5427624Ssam 			if (com != FIONBIO && com != FIOASYNC)
5437624Ssam 				u.u_error = ENOTTY;
5447423Sroot 			return;
5457624Ssam 		}
5467624Ssam 		dev = ip->i_rdev;
5477624Ssam 		u.u_r.r_val1 = 0;
5488118Sroot 		if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
5497624Ssam 			u.u_eosys = RESTARTSYS;
5507624Ssam 			return;
5517624Ssam 		}
5528564Sroot 		u.u_error = (*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0);
5537423Sroot 	}
5547624Ssam 
5557624Ssam returndata:
5567624Ssam 	/*
5577624Ssam 	 * Copy any data to user, size was
5587624Ssam 	 * already set and checked above.
5597624Ssam 	 */
5609999Ssam 	if (u.u_error == 0 && (com&IOC_OUT) && size)
5619999Ssam 		u.u_error = copyout(data, uap->cmarg, (u_int)size);
5627423Sroot }
5637423Sroot 
5647423Sroot /*
5657423Sroot  * Do nothing specific version of line
5667423Sroot  * discipline specific ioctl command.
5677423Sroot  */
5687423Sroot /*ARGSUSED*/
5697624Ssam nullioctl(tp, cmd, data, flags)
5707423Sroot 	struct tty *tp;
5717624Ssam 	char *data;
5727624Ssam 	int flags;
5737423Sroot {
5747423Sroot 
5757624Ssam #ifdef lint
5767624Ssam 	tp = tp; data = data; flags = flags;
5777624Ssam #endif
5788564Sroot 	return (-1);
5797423Sroot }
5808103Sroot 
5818103Sroot ostty()
5828103Sroot {
5838103Sroot 
5848103Sroot }
5858103Sroot 
5868103Sroot ogtty()
5878103Sroot {
5888103Sroot 
5898103Sroot }
590