xref: /csrg-svn/sys/kern/sys_generic.c (revision 7820)
1*7820Sroot /*	sys_generic.c	5.11	82/08/22	*/
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/inline.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
23*7820Sroot #include "../h/vlimit.h"
247500Sroot #include "../h/descrip.h"
257714Sroot #include "../h/uio.h"
267423Sroot 
277423Sroot /*
287423Sroot  * Read system call.
297423Sroot  */
307423Sroot read()
317423Sroot {
327423Sroot 	register struct a {
337423Sroot 		int	fdes;
347423Sroot 		char	*cbuf;
357423Sroot 		unsigned count;
36*7820Sroot 	} *uap = (struct a *)u.u_ap;
377746Sroot 	struct uio auio;
387746Sroot 	struct iovec aiov;
397423Sroot 
40*7820Sroot 	aiov.iov_base = (caddr_t)uap->cbuf;
41*7820Sroot 	aiov.iov_len = uap->count;
42*7820Sroot 	auio.uio_iov = &aiov;
43*7820Sroot 	auio.uio_iovcnt = 1;
44*7820Sroot 	rwuio(&auio, UIO_READ);
45*7820Sroot }
46*7820Sroot 
47*7820Sroot readv()
48*7820Sroot {
49*7820Sroot 	register struct a {
50*7820Sroot 		int	fdes;
51*7820Sroot 		struct	iovec *iovp;
52*7820Sroot 		int	iovcnt;
53*7820Sroot 	} *uap = (struct a *)u.u_ap;
54*7820Sroot 	struct uio auio;
55*7820Sroot 	struct iovec aiov[16];		/* XXX */
56*7820Sroot 
57*7820Sroot 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
587423Sroot 		u.u_error = EINVAL;
597423Sroot 		return;
607423Sroot 	}
61*7820Sroot 	auio.uio_iov = aiov;
62*7820Sroot 	auio.uio_iovcnt = uap->iovcnt;
63*7820Sroot 	if (copyin((caddr_t)uap->iovp, (caddr_t)aiov,
64*7820Sroot 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)))) {
65*7820Sroot 		u.u_error = EFAULT;
667423Sroot 		return;
677423Sroot 	}
68*7820Sroot 	rwuio(&auio, UIO_READ);
697423Sroot }
707423Sroot 
717423Sroot /*
727423Sroot  * Write system call
737423Sroot  */
747423Sroot write()
757423Sroot {
767423Sroot 	register struct a {
777423Sroot 		int	fdes;
787423Sroot 		char	*cbuf;
79*7820Sroot 		int	count;
80*7820Sroot 	} *uap = (struct a *)u.u_ap;
81*7820Sroot 	struct uio auio;
82*7820Sroot 	struct iovec aiov;
837423Sroot 
84*7820Sroot 	auio.uio_iov = &aiov;
85*7820Sroot 	auio.uio_iovcnt = 1;
86*7820Sroot 	aiov.iov_base = uap->cbuf;
87*7820Sroot 	aiov.iov_len = uap->count;
88*7820Sroot 	rwuio(&auio, UIO_WRITE);
89*7820Sroot }
90*7820Sroot 
91*7820Sroot writev()
92*7820Sroot {
93*7820Sroot 	register struct a {
94*7820Sroot 		int	fdes;
95*7820Sroot 		struct	iovec *iovp;
96*7820Sroot 		int	iovcnt;
97*7820Sroot 	} *uap = (struct a *)u.u_ap;
98*7820Sroot 	struct uio auio;
99*7820Sroot 	struct iovec aiov[16];		/* XXX */
100*7820Sroot 
101*7820Sroot 	if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
1027423Sroot 		u.u_error = EINVAL;
1037423Sroot 		return;
1047423Sroot 	}
105*7820Sroot 	auio.uio_iov = aiov;
106*7820Sroot 	auio.uio_iovcnt = uap->iovcnt;
107*7820Sroot 	if (copyin((caddr_t)uap->iovp, (caddr_t)aiov,
108*7820Sroot 	    (unsigned)(uap->iovcnt * sizeof (struct iovec)))) {
109*7820Sroot 		u.u_error = EFAULT;
110*7820Sroot 		return;
111*7820Sroot 	}
112*7820Sroot 	rwuio(&auio, UIO_WRITE);
113*7820Sroot }
114*7820Sroot 
115*7820Sroot rwuio(uio, rw)
116*7820Sroot 	register struct uio *uio;
117*7820Sroot 	enum uio_rw rw;
118*7820Sroot {
119*7820Sroot 	struct a {
120*7820Sroot 		int	fdes;
121*7820Sroot 	};
122*7820Sroot 	register struct file *fp;
123*7820Sroot 	register struct iovec *iov;
124*7820Sroot 	register struct inode *ip;
125*7820Sroot 	int i, count;
126*7820Sroot 
127*7820Sroot 	GETF(fp, ((struct a *)u.u_ap)->fdes);
128*7820Sroot 	if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
1297423Sroot 		u.u_error = EBADF;
1307423Sroot 		return;
1317423Sroot 	}
132*7820Sroot 	uio->uio_resid = 0;
133*7820Sroot 	uio->uio_segflg = 0;
134*7820Sroot 	iov = uio->uio_iov;
135*7820Sroot 	for (i = 0; i < uio->uio_iovcnt; i++) {
136*7820Sroot 		if (iov->iov_len < 0) {
137*7820Sroot 			u.u_error = EINVAL;
138*7820Sroot 			return;
139*7820Sroot 		}
140*7820Sroot 		uio->uio_resid += iov->iov_len;
141*7820Sroot 		if (uio->uio_resid < 0) {
142*7820Sroot 			u.u_error = EINVAL;
143*7820Sroot 			return;
144*7820Sroot 		}
145*7820Sroot 	}
146*7820Sroot 	count = uio->uio_resid;
1477423Sroot 	if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) {
148*7820Sroot 		if (uio->uio_resid == count)
1497423Sroot 			u.u_eosys = RESTARTSYS;
150*7820Sroot 	} else if (fp->f_type == DTYPE_SOCKET) {
151*7820Sroot 		int sosend(), soreceive();
152*7820Sroot 		u.u_error =
153*7820Sroot 		    (*(rw==UIO_READ?soreceive:sosend))
154*7820Sroot 		      (fp->f_socket, (struct sockaddr *)0, uio);
155*7820Sroot 	} else {
1567423Sroot 		ip = fp->f_inode;
157*7820Sroot 		uio->uio_offset = fp->f_offset;
1587423Sroot 		if ((ip->i_mode&IFMT) == IFREG) {
1597423Sroot 			ilock(ip);
160*7820Sroot 			u.u_error = rwip(ip, uio, rw);
1617423Sroot 			iunlock(ip);
1627423Sroot 		} else
163*7820Sroot 			u.u_error = rwip(ip, uio, rw);
164*7820Sroot 		fp->f_offset += count - uio->uio_resid;
1657423Sroot 	}
166*7820Sroot 	u.u_r.r_val1 = count - uio->uio_resid;
1677423Sroot }
1687423Sroot 
169*7820Sroot rdwri(rw, ip, base, len, offset, segflg, aresid)
170*7820Sroot 	struct inode *ip;
171*7820Sroot 	caddr_t base;
172*7820Sroot 	int len, offset, segflg;
173*7820Sroot 	int *aresid;
174*7820Sroot 	enum uio_rw rw;
1757500Sroot {
176*7820Sroot 	struct uio auio;
177*7820Sroot 	struct iovec aiov;
178*7820Sroot 	int error;
1797423Sroot 
180*7820Sroot 	auio.uio_iov = &aiov;
181*7820Sroot 	auio.uio_iovcnt = 1;
182*7820Sroot 	aiov.iov_base = base;
183*7820Sroot 	aiov.iov_len = len;
184*7820Sroot 	auio.uio_resid = len;
185*7820Sroot 	auio.uio_offset = offset;
186*7820Sroot 	auio.uio_segflg = segflg;
187*7820Sroot 	error = rwip(ip, &auio, rw);
188*7820Sroot 	if (aresid)
189*7820Sroot 		*aresid = auio.uio_resid;
190*7820Sroot 	else
191*7820Sroot 		if (auio.uio_resid)
192*7820Sroot 			error = EIO;
193*7820Sroot 	return (error);
1947500Sroot }
1957500Sroot 
196*7820Sroot rwip(ip, uio, rw)
197*7820Sroot 	register struct inode *ip;
198*7820Sroot 	register struct uio *uio;
199*7820Sroot 	enum uio_rw rw;
2007500Sroot {
201*7820Sroot 	dev_t dev = (dev_t)ip->i_rdev;
202*7820Sroot 	struct buf *bp;
203*7820Sroot 	struct fs *fs;
204*7820Sroot 	daddr_t lbn, bn;
205*7820Sroot 	register int on, type;
206*7820Sroot 	register unsigned n;
207*7820Sroot 	int size;
208*7820Sroot 	long bsize;
209*7820Sroot 	extern int mem_no;
210*7820Sroot 	int error = 0;
2117500Sroot 
212*7820Sroot 	if (rw != UIO_READ && rw != UIO_WRITE)
213*7820Sroot 		panic("rwip");
214*7820Sroot 	if (uio->uio_offset < 0 &&
215*7820Sroot 	    ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)))
216*7820Sroot 		return (EINVAL); if (rw == UIO_READ)
217*7820Sroot 		ip->i_flag |= IACC;
218*7820Sroot 	type = ip->i_mode&IFMT;
219*7820Sroot 	if (type == IFCHR) {
220*7820Sroot #ifdef QUOTA
221*7820Sroot 		register c = uio->uio_resid;
222*7820Sroot #endif
223*7820Sroot 		if (rw == UIO_READ)
224*7820Sroot 			(*cdevsw[major(dev)].d_read)(dev, uio);
225*7820Sroot 		else {
226*7820Sroot 			ip->i_flag |= IUPD|ICHG;
227*7820Sroot 			(*cdevsw[major(dev)].d_write)(dev, uio);
228*7820Sroot 		}
229*7820Sroot 		CHARGE(sc_tio * (c - uio->uio_resid));
230*7820Sroot 		return (u.u_error);
231*7820Sroot 	}
232*7820Sroot 	if (rw == UIO_WRITE && type == IFREG &&
233*7820Sroot 	    uio->uio_offset + uio->uio_resid > u.u_limit[LIM_FSIZE]) {
234*7820Sroot 		psignal(u.u_procp, SIGXFSZ);
235*7820Sroot 		return (EMFILE);
236*7820Sroot 	}
237*7820Sroot 	if (type != IFBLK) {
238*7820Sroot 		dev = ip->i_dev;
239*7820Sroot 		fs = ip->i_fs;
240*7820Sroot 		bsize = fs->fs_bsize;
241*7820Sroot 	} else
242*7820Sroot 		bsize = BLKDEV_IOSIZE;
243*7820Sroot 	do {
244*7820Sroot 		lbn = uio->uio_offset / bsize;
245*7820Sroot 		on = uio->uio_offset % bsize;
246*7820Sroot 		n = MIN((unsigned)(bsize - on), uio->uio_resid);
247*7820Sroot 		if (type != IFBLK) {
248*7820Sroot 			if (rw == UIO_READ) {
249*7820Sroot 				int diff = ip->i_size - uio->uio_offset;
250*7820Sroot 				if (diff <= 0)
251*7820Sroot 					return (0);
252*7820Sroot 				if (diff < n)
253*7820Sroot 					n = diff;
254*7820Sroot 			}
255*7820Sroot 			bn = fsbtodb(fs,
256*7820Sroot 			    bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n)));
257*7820Sroot 			if (u.u_error || rw == UIO_WRITE && (long)bn<0)
258*7820Sroot 				return (u.u_error);
259*7820Sroot 			if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size &&
260*7820Sroot 			   (type == IFDIR || type == IFREG || type == IFLNK))
261*7820Sroot 				ip->i_size = uio->uio_offset + n;
262*7820Sroot 			size = blksize(fs, ip, lbn);
263*7820Sroot 		} else {
264*7820Sroot 			bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE);
265*7820Sroot 			rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE);
266*7820Sroot 			rasize = size = bsize;
267*7820Sroot 		}
268*7820Sroot 		if (rw == UIO_READ) {
269*7820Sroot 			if ((long)bn<0) {
270*7820Sroot 				bp = geteblk(size);
271*7820Sroot 				clrbuf(bp);
272*7820Sroot 			} else if (ip->i_lastr + 1 == lbn)
273*7820Sroot 				bp = breada(dev, bn, size, rablock, rasize);
274*7820Sroot 			else
275*7820Sroot 				bp = bread(dev, bn, size);
276*7820Sroot 			ip->i_lastr = lbn;
277*7820Sroot 		} else {
278*7820Sroot 			int i, count;
279*7820Sroot 
280*7820Sroot 			count = howmany(size, DEV_BSIZE);
281*7820Sroot 			for (i = 0; i < count; i += CLSIZE)
282*7820Sroot 				if (mfind(dev, bn + i))
283*7820Sroot 					munhash(dev, bn + i);
284*7820Sroot 			if (n == bsize)
285*7820Sroot 				bp = getblk(dev, bn, size);
286*7820Sroot 			else
287*7820Sroot 				bp = bread(dev, bn, size);
288*7820Sroot 		}
289*7820Sroot 		n = MIN(n, size - bp->b_resid);
290*7820Sroot 		if (bp->b_flags & B_ERROR) {
291*7820Sroot 			error = EIO;
292*7820Sroot 			brelse(bp);
293*7820Sroot 			goto bad;
294*7820Sroot 		}
295*7820Sroot 		u.u_error =
296*7820Sroot 		    uiomove(bp->b_un.b_addr+on, (u_int)n, rw, uio);
297*7820Sroot 		if (rw == UIO_READ) {
298*7820Sroot 			if (n + on == bsize || uio->uio_offset == ip->i_size)
299*7820Sroot 				bp->b_flags |= B_AGE;
300*7820Sroot 			brelse(bp);
301*7820Sroot 		} else {
302*7820Sroot 			if ((ip->i_mode&IFMT) == IFDIR)
303*7820Sroot 				bwrite(bp);
304*7820Sroot 			else if (n + on == bsize) {
305*7820Sroot 				bp->b_flags |= B_AGE;
306*7820Sroot 				bawrite(bp);
307*7820Sroot 			} else
308*7820Sroot 				bdwrite(bp);
309*7820Sroot 			ip->i_flag |= IUPD|ICHG;
310*7820Sroot 			if (u.u_ruid != 0)
311*7820Sroot 				ip->i_mode &= ~(ISUID|ISGID);
312*7820Sroot 		}
313*7820Sroot 	} while (u.u_error == 0 && uio->uio_resid > 0 && n != 0);
314*7820Sroot bad:
315*7820Sroot 	return (error);
3167500Sroot }
3177500Sroot 
318*7820Sroot uiomove(cp, n, rw, uio)
319*7820Sroot 	register caddr_t cp;
320*7820Sroot 	register int n;
321*7820Sroot 	enum uio_rw rw;
322*7820Sroot 	register struct uio *uio;
323*7820Sroot {
324*7820Sroot 	register struct iovec *iov;
325*7820Sroot 	int error;
326*7820Sroot 	u_int cnt;
327*7820Sroot 
328*7820Sroot 	while (n > 0 && uio->uio_resid) {
329*7820Sroot 		iov = uio->uio_iov;
330*7820Sroot 		cnt = iov->iov_len;
331*7820Sroot 		if (cnt == 0) {
332*7820Sroot 			uio->uio_iov++;
333*7820Sroot 			uio->uio_iovcnt--;
334*7820Sroot 			continue;
335*7820Sroot 		}
336*7820Sroot 		if (cnt > n)
337*7820Sroot 			cnt = n;
338*7820Sroot 		switch (uio->uio_segflg) {
339*7820Sroot 
340*7820Sroot 		case 0:
341*7820Sroot 		case 2:
342*7820Sroot 			if (rw == UIO_READ)
343*7820Sroot 				error = copyout(cp, iov->iov_base, cnt);
344*7820Sroot 			else
345*7820Sroot 				error = copyin(iov->iov_base, cp, cnt);
346*7820Sroot 			if (error)
347*7820Sroot 				return (error);
348*7820Sroot 			break;
349*7820Sroot 
350*7820Sroot 		case 1:
351*7820Sroot 			if (rw == UIO_READ)
352*7820Sroot 				bcopy((caddr_t)cp, iov->iov_base, cnt);
353*7820Sroot 			else
354*7820Sroot 				bcopy(iov->iov_base, (caddr_t)cp, cnt);
355*7820Sroot 			break;
356*7820Sroot 		}
357*7820Sroot 		iov->iov_base += cnt;
358*7820Sroot 		iov->iov_len -= cnt;
359*7820Sroot 		uio->uio_resid -= cnt;
360*7820Sroot 		uio->uio_offset += cnt;
361*7820Sroot 		cp += cnt;
362*7820Sroot 		n -= cnt;
363*7820Sroot 	}
364*7820Sroot 	return (error);
365*7820Sroot }
366*7820Sroot 
3677423Sroot /*
368*7820Sroot  * Give next character to user as result of read.
369*7820Sroot  */
370*7820Sroot ureadc(c, uio)
371*7820Sroot 	register int c;
372*7820Sroot 	register struct uio *uio;
373*7820Sroot {
374*7820Sroot 	register struct iovec *iov;
375*7820Sroot 
376*7820Sroot again:
377*7820Sroot 	if (uio->uio_iovcnt == 0)
378*7820Sroot 		panic("ureadc");
379*7820Sroot 	iov = uio->uio_iov;
380*7820Sroot 	if (iov->iov_len <= 0 || uio->uio_resid <= 0) {
381*7820Sroot 		uio->uio_iovcnt--;
382*7820Sroot 		uio->uio_iov++;
383*7820Sroot 		goto again;
384*7820Sroot 	}
385*7820Sroot 	switch (uio->uio_segflg) {
386*7820Sroot 
387*7820Sroot 	case 0:
388*7820Sroot 		if (subyte(iov->iov_base, c) < 0)
389*7820Sroot 			return (EFAULT);
390*7820Sroot 		break;
391*7820Sroot 
392*7820Sroot 	case 1:
393*7820Sroot 		*iov->iov_base = c;
394*7820Sroot 		break;
395*7820Sroot 
396*7820Sroot 	case 2:
397*7820Sroot 		if (suibyte(iov->iov_base, c) < 0)
398*7820Sroot 			return (EFAULT);
399*7820Sroot 		break;
400*7820Sroot 	}
401*7820Sroot 	iov->iov_base++;
402*7820Sroot 	iov->iov_len--;
403*7820Sroot 	uio->uio_resid--;
404*7820Sroot 	uio->uio_offset++;
405*7820Sroot 	return (0);
406*7820Sroot }
407*7820Sroot 
408*7820Sroot /*
409*7820Sroot  * Get next character written in by user from uio.
410*7820Sroot  */
411*7820Sroot uwritec(uio)
412*7820Sroot 	struct uio *uio;
413*7820Sroot {
414*7820Sroot 	register struct iovec *iov;
415*7820Sroot 	register int c;
416*7820Sroot 
417*7820Sroot again:
418*7820Sroot 	if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0)
419*7820Sroot 		panic("uwritec");
420*7820Sroot 	iov = uio->uio_iov;
421*7820Sroot 	if (iov->iov_len == 0) {
422*7820Sroot 		uio->uio_iovcnt--;
423*7820Sroot 		uio->uio_iov++;
424*7820Sroot 		goto again;
425*7820Sroot 	}
426*7820Sroot 	switch (uio->uio_segflg) {
427*7820Sroot 
428*7820Sroot 	case 0:
429*7820Sroot 		c = fubyte(iov->iov_base);
430*7820Sroot 		break;
431*7820Sroot 
432*7820Sroot 	case 1:
433*7820Sroot 		c = *iov->iov_base & 0377;
434*7820Sroot 		break;
435*7820Sroot 
436*7820Sroot 	case 2:
437*7820Sroot 		c = fuibyte(iov->iov_base);
438*7820Sroot 		break;
439*7820Sroot 	}
440*7820Sroot 	if (c < 0)
441*7820Sroot 		return (-1);
442*7820Sroot 	iov->iov_base++;
443*7820Sroot 	iov->iov_len--;
444*7820Sroot 	uio->uio_resid--;
445*7820Sroot 	uio->uio_offset++;
446*7820Sroot 	return (c & 0377);
447*7820Sroot }
448*7820Sroot 
449*7820Sroot /*
4507423Sroot  * Ioctl system call
4517624Ssam  * Check legality, execute common code,
4527624Ssam  * and switch out to individual device routine.
4537423Sroot  */
4547423Sroot ioctl()
4557423Sroot {
4567423Sroot 	register struct file *fp;
4577624Ssam 	struct a {
4587423Sroot 		int	fdes;
4597423Sroot 		int	cmd;
4607423Sroot 		caddr_t	cmarg;
4617423Sroot 	} *uap;
462*7820Sroot 	register int com;
463*7820Sroot 	register u_int size;
4647624Ssam 	char data[IOCPARM_MASK+1];
4657423Sroot 
4667423Sroot 	uap = (struct a *)u.u_ap;
4677423Sroot 	if ((fp = getf(uap->fdes)) == NULL)
4687423Sroot 		return;
4697423Sroot 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
4707423Sroot 		u.u_error = EBADF;
4717423Sroot 		return;
4727423Sroot 	}
4737624Ssam 	com = uap->cmd;
4747624Ssam 
4757699Ssam #ifndef NOCOMPAT
4767624Ssam 	/*
4777624Ssam 	 * Map old style ioctl's into new for the
4787624Ssam 	 * sake of backwards compatibility (sigh).
4797624Ssam 	 */
4807624Ssam 	if ((com&~0xffff) == 0) {
4817624Ssam 		com = mapioctl(com);
4827624Ssam 		if (com == 0) {
4837624Ssam 			u.u_error = EINVAL;
4847624Ssam 			return;
4857624Ssam 		}
4867624Ssam 	}
4877624Ssam #endif
4887624Ssam 	if (com == FIOCLEX) {
4897423Sroot 		u.u_pofile[uap->fdes] |= EXCLOSE;
4907423Sroot 		return;
4917423Sroot 	}
4927624Ssam 	if (com == FIONCLEX) {
4937423Sroot 		u.u_pofile[uap->fdes] &= ~EXCLOSE;
4947423Sroot 		return;
4957423Sroot 	}
4967624Ssam 
4977624Ssam 	/*
4987624Ssam 	 * Interpret high order word to find
4997624Ssam 	 * amount of data to be copied to/from the
5007624Ssam 	 * user's address space.
5017624Ssam 	 */
5027624Ssam 	size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
5037624Ssam 	if (size > sizeof (data)) {
5047624Ssam 		u.u_error = EFAULT;
5057423Sroot 		return;
5067423Sroot 	}
5077699Ssam 	if (com&IOC_IN && size) {
508*7820Sroot 		if (copyin(uap->cmarg, (caddr_t)data, (u_int)size)) {
5097624Ssam 			u.u_error = EFAULT;
5107624Ssam 			return;
5117624Ssam 		}
5127624Ssam 	} else
5137624Ssam 		*(caddr_t *)data = uap->cmarg;
5147624Ssam 	/*
5157624Ssam 	 * Zero the buffer on the stack so the user
5167624Ssam 	 * always gets back something deterministic.
5177624Ssam 	 */
5187624Ssam 	if ((com&IOC_OUT) && size)
5197624Ssam 		bzero((caddr_t)data, size);
5207423Sroot 
5217624Ssam 	if (fp->f_type == DTYPE_SOCKET)
5227624Ssam 		soioctl(fp->f_socket, com, data);
5237624Ssam 	else {
5247624Ssam 		register struct inode *ip = fp->f_inode;
5257624Ssam 		int fmt = ip->i_mode & IFMT;
5267624Ssam 		dev_t dev;
5277624Ssam 
5287624Ssam 		if (fmt != IFCHR) {
5297624Ssam 			if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) {
5307624Ssam 				*(off_t *)data = ip->i_size - fp->f_offset;
5317624Ssam 				goto returndata;
5327624Ssam 			}
5337624Ssam 			if (com != FIONBIO && com != FIOASYNC)
5347624Ssam 				u.u_error = ENOTTY;
5357423Sroot 			return;
5367624Ssam 		}
5377624Ssam 		dev = ip->i_rdev;
5387624Ssam 		u.u_r.r_val1 = 0;
5397624Ssam 		if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) {
5407624Ssam 			u.u_eosys = RESTARTSYS;
5417624Ssam 			return;
5427624Ssam 		}
5437624Ssam 		(*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0);
5447423Sroot 	}
5457624Ssam 
5467624Ssam returndata:
5477624Ssam 	/*
5487624Ssam 	 * Copy any data to user, size was
5497624Ssam 	 * already set and checked above.
5507624Ssam 	 */
551*7820Sroot 	if (u.u_error == 0 && (com&IOC_OUT))
552*7820Sroot 		if (size && copyout(data, uap->cmarg, (u_int)size))
5537699Ssam 			u.u_error = EFAULT;
5547423Sroot }
5557423Sroot 
5567423Sroot /*
5577423Sroot  * Do nothing specific version of line
5587423Sroot  * discipline specific ioctl command.
5597423Sroot  */
5607423Sroot /*ARGSUSED*/
5617624Ssam nullioctl(tp, cmd, data, flags)
5627423Sroot 	struct tty *tp;
5637624Ssam 	char *data;
5647624Ssam 	int flags;
5657423Sroot {
5667423Sroot 
5677624Ssam #ifdef lint
5687624Ssam 	tp = tp; data = data; flags = flags;
5697624Ssam #endif
5707423Sroot 	return (cmd);
5717423Sroot }
572