xref: /csrg-svn/sys/kern/tty_pty.c (revision 22731)
1*22731Skarels /*	tty_pty.c	6.11	85/06/07	*/
22283Stoy 
32281Stoy /*
42281Stoy  * Pseudo-teletype Driver
52281Stoy  * (Actually two drivers, requiring two entries in 'cdevsw')
62281Stoy  */
72314Stoy #include "pty.h"
82314Stoy 
93206Swnj #if NPTY > 0
1017096Sbloom #include "param.h"
1117096Sbloom #include "systm.h"
1217096Sbloom #include "ioctl.h"
1317096Sbloom #include "tty.h"
1417096Sbloom #include "dir.h"
1517096Sbloom #include "user.h"
1617096Sbloom #include "conf.h"
1717096Sbloom #include "file.h"
1817096Sbloom #include "proc.h"
1917096Sbloom #include "uio.h"
2017096Sbloom #include "kernel.h"
216239Sroot 
227475Ssam #if NPTY == 1
2318651Sbloom #undef NPTY
246239Sroot #define	NPTY	32		/* crude XXX */
257475Ssam #endif
262281Stoy 
2716788Ssam #define BUFSIZ 100		/* Chunk size iomoved to/from user */
284484Swnj 
292281Stoy /*
3018651Sbloom  * pts == /dev/tty[pqrs]?
3118651Sbloom  * ptc == /dev/pty[pqrs]?
322281Stoy  */
334484Swnj struct	tty pt_tty[NPTY];
344484Swnj struct	pt_ioctl {
355427Swnj 	int	pt_flags;
365427Swnj 	int	pt_gensym;
375427Swnj 	struct	proc *pt_selr, *pt_selw;
3818651Sbloom 	u_char	pt_send;
3918651Sbloom 	u_char	pt_ucntl;
404484Swnj } pt_ioctl[NPTY];
4118651Sbloom int	npty = NPTY;		/* for pstat -t */
422281Stoy 
435427Swnj #define	PF_RCOLL	0x01
445427Swnj #define	PF_WCOLL	0x02
455427Swnj #define	PF_NBIO		0x04
465427Swnj #define	PF_PKT		0x08		/* packet mode */
475574Swnj #define	PF_STOPPED	0x10		/* user told stopped */
485894Swnj #define	PF_REMOTE	0x20		/* remote and flow controlled input */
496119Swnj #define	PF_NOSTOP	0x40
5018651Sbloom #define PF_UCNTL	0x80		/* user control mode */
512281Stoy 
522281Stoy /*ARGSUSED*/
532281Stoy ptsopen(dev, flag)
545396Sroot 	dev_t dev;
554484Swnj {
562281Stoy 	register struct tty *tp;
5718651Sbloom 	int error;
582281Stoy 
5918651Sbloom #ifdef lint
6018651Sbloom 	npty = npty;
6118651Sbloom #endif
628563Sroot 	if (minor(dev) >= NPTY)
638563Sroot 		return (ENXIO);
642281Stoy 	tp = &pt_tty[minor(dev)];
655408Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
662427Swnj 		ttychars(tp);		/* Set up default chars */
6712642Ssam 		tp->t_ispeed = tp->t_ospeed = EXTB;
682427Swnj 		tp->t_flags = 0;	/* No features (nor raw mode) */
698563Sroot 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
708563Sroot 		return (EBUSY);
714484Swnj 	if (tp->t_oproc)			/* Ctrlr still around. */
725408Swnj 		tp->t_state |= TS_CARR_ON;
735408Swnj 	while ((tp->t_state & TS_CARR_ON) == 0) {
745408Swnj 		tp->t_state |= TS_WOPEN;
752281Stoy 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
762281Stoy 	}
7718651Sbloom 	error = (*linesw[tp->t_line].l_open)(dev, tp);
7818651Sbloom 	ptcwakeup(tp, FREAD|FWRITE);
7918651Sbloom 	return (error);
802281Stoy }
812281Stoy 
822281Stoy ptsclose(dev)
835396Sroot 	dev_t dev;
845408Swnj {
852281Stoy 	register struct tty *tp;
862281Stoy 
872281Stoy 	tp = &pt_tty[minor(dev)];
882281Stoy 	(*linesw[tp->t_line].l_close)(tp);
896299Swnj 	ttyclose(tp);
9018651Sbloom 	ptcwakeup(tp, FREAD|FWRITE);
912281Stoy }
922281Stoy 
937823Sroot ptsread(dev, uio)
945396Sroot 	dev_t dev;
957823Sroot 	struct uio *uio;
964484Swnj {
975894Swnj 	register struct tty *tp = &pt_tty[minor(dev)];
985894Swnj 	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
998521Sroot 	int error = 0;
1002281Stoy 
1015894Swnj again:
1025894Swnj 	if (pti->pt_flags & PF_REMOTE) {
1035894Swnj 		while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
10418651Sbloom 			if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
10518651Sbloom 			    (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
1065894Swnj 	/*
1075894Swnj 			    (u.u_procp->p_flag&SDETACH) ||
1085894Swnj 	*/
1095894Swnj 			    u.u_procp->p_flag&SVFORK)
1108521Sroot 				return (EIO);
1115894Swnj 			gsignal(u.u_procp->p_pgrp, SIGTTIN);
1125894Swnj 			sleep((caddr_t)&lbolt, TTIPRI);
1135408Swnj 		}
11418651Sbloom 		if (tp->t_canq.c_cc == 0) {
1158521Sroot 			if (tp->t_state & TS_NBIO)
1168521Sroot 				return (EWOULDBLOCK);
11718651Sbloom 			sleep((caddr_t)&tp->t_canq, TTIPRI);
1185894Swnj 			goto again;
1195894Swnj 		}
12018651Sbloom 		while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
12118651Sbloom 			if (ureadc(getc(&tp->t_canq), uio) < 0) {
1228521Sroot 				error = EFAULT;
1237823Sroot 				break;
1247823Sroot 			}
12518651Sbloom 		if (tp->t_canq.c_cc == 1)
12618651Sbloom 			(void) getc(&tp->t_canq);
12718651Sbloom 		if (tp->t_canq.c_cc)
1288521Sroot 			return (error);
1295894Swnj 	} else
1305894Swnj 		if (tp->t_oproc)
1318521Sroot 			error = (*linesw[tp->t_line].l_read)(tp, uio);
13218651Sbloom 	ptcwakeup(tp, FWRITE);
1338521Sroot 	return (error);
1342281Stoy }
1352281Stoy 
1365408Swnj /*
1375408Swnj  * Write to pseudo-tty.
1385408Swnj  * Wakeups of controlling tty will happen
1395408Swnj  * indirectly, when tty driver calls ptsstart.
1405408Swnj  */
1417823Sroot ptswrite(dev, uio)
1425396Sroot 	dev_t dev;
1437823Sroot 	struct uio *uio;
1444484Swnj {
1452281Stoy 	register struct tty *tp;
1462281Stoy 
1472281Stoy 	tp = &pt_tty[minor(dev)];
1488521Sroot 	if (tp->t_oproc == 0)
1498521Sroot 		return (EIO);
1508521Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
1512281Stoy }
1522281Stoy 
1535408Swnj /*
1545408Swnj  * Start output on pseudo-tty.
1555408Swnj  * Wake up process selecting or sleeping for input from controlling tty.
1565408Swnj  */
1572281Stoy ptsstart(tp)
1584484Swnj 	struct tty *tp;
1594484Swnj {
1605574Swnj 	register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
1614484Swnj 
1625408Swnj 	if (tp->t_state & TS_TTSTOP)
1632281Stoy 		return;
1645574Swnj 	if (pti->pt_flags & PF_STOPPED) {
1655574Swnj 		pti->pt_flags &= ~PF_STOPPED;
1665574Swnj 		pti->pt_send = TIOCPKT_START;
1675574Swnj 	}
16818651Sbloom 	ptcwakeup(tp, FREAD);
1695430Swnj }
1705430Swnj 
17118651Sbloom ptcwakeup(tp, flag)
1725430Swnj 	struct tty *tp;
1735430Swnj {
1745430Swnj 	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
1755430Swnj 
17618651Sbloom 	if (flag & FREAD) {
17718651Sbloom 		if (pti->pt_selr) {
17818651Sbloom 			selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL);
17918651Sbloom 			pti->pt_selr = 0;
18018651Sbloom 			pti->pt_flags &= ~PF_RCOLL;
18118651Sbloom 		}
18218651Sbloom 		wakeup((caddr_t)&tp->t_outq.c_cf);
1834484Swnj 	}
18418651Sbloom 	if (flag & FWRITE) {
18518651Sbloom 		if (pti->pt_selw) {
18618651Sbloom 			selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL);
18718651Sbloom 			pti->pt_selw = 0;
18818651Sbloom 			pti->pt_flags &= ~PF_WCOLL;
18918651Sbloom 		}
19018651Sbloom 		wakeup((caddr_t)&tp->t_rawq.c_cf);
19118651Sbloom 	}
1922281Stoy }
1932281Stoy 
1942281Stoy /*ARGSUSED*/
1952281Stoy ptcopen(dev, flag)
1964484Swnj 	dev_t dev;
1974484Swnj 	int flag;
1984484Swnj {
1992281Stoy 	register struct tty *tp;
2005427Swnj 	struct pt_ioctl *pti;
2012281Stoy 
2028563Sroot 	if (minor(dev) >= NPTY)
2038563Sroot 		return (ENXIO);
2042281Stoy 	tp = &pt_tty[minor(dev)];
2058563Sroot 	if (tp->t_oproc)
2068563Sroot 		return (EIO);
2074484Swnj 	tp->t_oproc = ptsstart;
2085408Swnj 	if (tp->t_state & TS_WOPEN)
2092281Stoy 		wakeup((caddr_t)&tp->t_rawq);
2105408Swnj 	tp->t_state |= TS_CARR_ON;
2115427Swnj 	pti = &pt_ioctl[minor(dev)];
2125427Swnj 	pti->pt_flags = 0;
2135427Swnj 	pti->pt_send = 0;
21418651Sbloom 	pti->pt_ucntl = 0;
2158563Sroot 	return (0);
2162281Stoy }
2172281Stoy 
2182281Stoy ptcclose(dev)
2194484Swnj 	dev_t dev;
2204484Swnj {
2212281Stoy 	register struct tty *tp;
2222281Stoy 
2232281Stoy 	tp = &pt_tty[minor(dev)];
2245408Swnj 	if (tp->t_state & TS_ISOPEN)
2252281Stoy 		gsignal(tp->t_pgrp, SIGHUP);
2265408Swnj 	tp->t_state &= ~TS_CARR_ON;	/* virtual carrier gone */
22712753Ssam 	ttyflush(tp, FREAD|FWRITE);
2284484Swnj 	tp->t_oproc = 0;		/* mark closed */
2292281Stoy }
2302281Stoy 
2317823Sroot ptcread(dev, uio)
2325427Swnj 	dev_t dev;
2337823Sroot 	struct uio *uio;
2344484Swnj {
2358521Sroot 	register struct tty *tp = &pt_tty[minor(dev)];
23618651Sbloom 	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
23716788Ssam 	char buf[BUFSIZ];
23816788Ssam 	int error = 0, cc;
2392281Stoy 
24018651Sbloom 	/*
24118651Sbloom 	 * We want to block until the slave
24218651Sbloom 	 * is open, and there's something to read;
24318651Sbloom 	 * but if we lost the slave or we're NBIO,
24418651Sbloom 	 * then return the appropriate error instead.
24518651Sbloom 	 */
24618651Sbloom 	for (;;) {
24718651Sbloom 		if (tp->t_state&TS_ISOPEN) {
24818651Sbloom 			if (pti->pt_flags&PF_PKT && pti->pt_send) {
24918651Sbloom 				error = ureadc(pti->pt_send, uio);
25018651Sbloom 				if (error)
25118651Sbloom 					return (error);
25218651Sbloom 				pti->pt_send = 0;
25318651Sbloom 				return (0);
25418651Sbloom 			}
25518651Sbloom 			if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
25618651Sbloom 				error = ureadc(pti->pt_ucntl, uio);
25718651Sbloom 				if (error)
25818651Sbloom 					return (error);
25918651Sbloom 				pti->pt_ucntl = 0;
26018651Sbloom 				return (0);
26118651Sbloom 			}
26218651Sbloom 			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
26318651Sbloom 				break;
2645427Swnj 		}
26516788Ssam 		if ((tp->t_state&TS_CARR_ON) == 0)
26616788Ssam 			return (EIO);
2678521Sroot 		if (pti->pt_flags&PF_NBIO)
2688521Sroot 			return (EWOULDBLOCK);
2692281Stoy 		sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI);
2705411Swnj 	}
27118651Sbloom 	if (pti->pt_flags & (PF_PKT|PF_UCNTL))
27218651Sbloom 		error = ureadc(0, uio);
27316788Ssam 	while (uio->uio_resid > 0 && error == 0) {
27416788Ssam 		cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
27516788Ssam 		if (cc <= 0)
2767823Sroot 			break;
27716788Ssam 		error = uiomove(buf, cc, UIO_READ, uio);
27816788Ssam 	}
2795408Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
2805408Swnj 		if (tp->t_state&TS_ASLEEP) {
2815408Swnj 			tp->t_state &= ~TS_ASLEEP;
2825408Swnj 			wakeup((caddr_t)&tp->t_outq);
2835408Swnj 		}
2845408Swnj 		if (tp->t_wsel) {
2855408Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
2865408Swnj 			tp->t_wsel = 0;
2875408Swnj 			tp->t_state &= ~TS_WCOLL;
2885408Swnj 		}
2892281Stoy 	}
2908521Sroot 	return (error);
2912281Stoy }
2922281Stoy 
2935427Swnj ptsstop(tp, flush)
2945427Swnj 	register struct tty *tp;
2955427Swnj 	int flush;
2965427Swnj {
2975427Swnj 	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
29818651Sbloom 	int flag;
2995427Swnj 
3005574Swnj 	/* note: FLUSHREAD and FLUSHWRITE already ok */
3015574Swnj 	if (flush == 0) {
3025574Swnj 		flush = TIOCPKT_STOP;
3035574Swnj 		pti->pt_flags |= PF_STOPPED;
30418651Sbloom 	} else
3055574Swnj 		pti->pt_flags &= ~PF_STOPPED;
3066119Swnj 	pti->pt_send |= flush;
30718651Sbloom 	/* change of perspective */
30818651Sbloom 	flag = 0;
30918651Sbloom 	if (flush & FREAD)
31018651Sbloom 		flag |= FWRITE;
31118651Sbloom 	if (flush & FWRITE)
31218651Sbloom 		flag |= FREAD;
31318651Sbloom 	ptcwakeup(tp, flush);
3145427Swnj }
3155427Swnj 
3165408Swnj ptcselect(dev, rw)
3174484Swnj 	dev_t dev;
3185408Swnj 	int rw;
3194484Swnj {
3204484Swnj 	register struct tty *tp = &pt_tty[minor(dev)];
3215894Swnj 	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
3224484Swnj 	struct proc *p;
3235430Swnj 	int s;
3244484Swnj 
32518651Sbloom 	if ((tp->t_state&TS_CARR_ON) == 0)
3264484Swnj 		return (1);
3275430Swnj 	s = spl5();
3285408Swnj 	switch (rw) {
3295408Swnj 
3305408Swnj 	case FREAD:
33118651Sbloom 		if ((tp->t_state&TS_ISOPEN) &&
33218651Sbloom 		    (pti->pt_flags&PF_PKT && pti->pt_send ||
33318651Sbloom 		     pti->pt_flags&PF_UCNTL && pti->pt_ucntl ||
33418651Sbloom 		     tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)) {
3355430Swnj 			splx(s);
3365408Swnj 			return (1);
3375430Swnj 		}
3385427Swnj 		if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait)
3395427Swnj 			pti->pt_flags |= PF_RCOLL;
3405408Swnj 		else
3415427Swnj 			pti->pt_selr = u.u_procp;
3425430Swnj 		break;
3435408Swnj 
3445408Swnj 	case FWRITE:
34518651Sbloom 		if ((tp->t_state&TS_ISOPEN) &&
346*22731Skarels 		    ((pti->pt_flags&PF_REMOTE) == 0 || tp->t_canq.c_cc == 0)) {
3475430Swnj 			splx(s);
3485408Swnj 			return (1);
3495430Swnj 		}
3505427Swnj 		if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait)
3515427Swnj 			pti->pt_flags |= PF_WCOLL;
3525408Swnj 		else
3535427Swnj 			pti->pt_selw = u.u_procp;
3545430Swnj 		break;
3555408Swnj 	}
3565430Swnj 	splx(s);
3575430Swnj 	return (0);
3585396Sroot }
3594484Swnj 
3607823Sroot ptcwrite(dev, uio)
3615408Swnj 	dev_t dev;
36218651Sbloom 	register struct uio *uio;
3634484Swnj {
3648521Sroot 	register struct tty *tp = &pt_tty[minor(dev)];
36518651Sbloom 	register struct iovec *iov;
36618651Sbloom 	register char *cp;
36718651Sbloom 	register int cc = 0;
3682281Stoy 	char locbuf[BUFSIZ];
3695408Swnj 	int cnt = 0;
3705894Swnj 	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
3718521Sroot 	int error = 0;
3722281Stoy 
37318651Sbloom again:
37418651Sbloom 	if ((tp->t_state&TS_ISOPEN) == 0)
37518651Sbloom 		goto block;
37618651Sbloom 	if (cnt == 0 && pti->pt_flags & PF_REMOTE) {
37718651Sbloom 		if (uio->uio_iovcnt <= 0)
37818651Sbloom 			return (0);
37918651Sbloom 		if (tp->t_canq.c_cc)
38018651Sbloom 			goto block;
3817823Sroot 		iov = uio->uio_iov;
38218651Sbloom 		if (cc == 0 && iov->iov_len) {
38318651Sbloom 			cc = MIN(iov->iov_len, BUFSIZ);
38418651Sbloom 			cp = locbuf;
38518651Sbloom 			error = uiomove(cp, cc, UIO_WRITE, uio);
38618651Sbloom 			if (error)
38718651Sbloom 				return (error);
38818651Sbloom 			/* check again for safety */
38918651Sbloom 			if ((tp->t_state&TS_ISOPEN) == 0)
39018651Sbloom 				return (EIO);
39118651Sbloom 			if (tp->t_canq.c_cc)
39218651Sbloom 				goto block;
3937823Sroot 		}
39418651Sbloom 		if (cc)
39518651Sbloom 			(void) b_to_q(cp, cc, &tp->t_canq);
39618651Sbloom 		(void) putc(0, &tp->t_canq);
39718651Sbloom 		ttwakeup(tp);
39818651Sbloom 		wakeup((caddr_t)&tp->t_canq);
39918651Sbloom 		return (0);
40018651Sbloom 	}
40118651Sbloom 	while (uio->uio_iovcnt > 0) {
40218651Sbloom 		iov = uio->uio_iov;
40318651Sbloom 		if (cc == 0) {
40418651Sbloom 			if (iov->iov_len == 0) {
40518651Sbloom 				uio->uio_iovcnt--;
40618651Sbloom 				uio->uio_iov++;
40718651Sbloom 				continue;
4085894Swnj 			}
40918651Sbloom 			cc = MIN(iov->iov_len, BUFSIZ);
41018651Sbloom 			cp = locbuf;
41118651Sbloom 			error = uiomove(cp, cc, UIO_WRITE, uio);
41218651Sbloom 			if (error)
41318651Sbloom 				return (error);
41418651Sbloom 			/* check again for safety */
41518651Sbloom 			if ((tp->t_state&TS_ISOPEN) == 0)
41618651Sbloom 				return (EIO);
4175894Swnj 		}
41818651Sbloom 		while (--cc >= 0) {
4194141Secc 			(*linesw[tp->t_line].l_rint)(*cp++, tp);
4205408Swnj 			cnt++;
4212281Stoy 		}
42218651Sbloom 		cc = 0;
42318651Sbloom 	}
42418651Sbloom 	return (0);
42518651Sbloom block:
42618651Sbloom 	/*
42718651Sbloom 	 * Come here to wait for slave to open or for space
42818651Sbloom 	 * in outq.
42918651Sbloom 	 */
43018651Sbloom 	if ((tp->t_state&TS_CARR_ON) == 0)
43118651Sbloom 		return (EIO);
43218651Sbloom 	if (pti->pt_flags & PF_NBIO) {
43318651Sbloom 		if (cnt == 0)
43418651Sbloom 			return (EWOULDBLOCK);
43518651Sbloom 		iov->iov_base -= cc;
43618651Sbloom 		iov->iov_len += cc;
43718651Sbloom 		uio->uio_resid += cc;
43818651Sbloom 		uio->uio_offset -= cc;
43918651Sbloom 		return (0);
44018651Sbloom 	}
44118651Sbloom 	sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI);
44218651Sbloom 	goto again;
4432281Stoy }
4442281Stoy 
4452281Stoy /*ARGSUSED*/
4467626Ssam ptyioctl(dev, cmd, data, flag)
4477626Ssam 	caddr_t data;
4484484Swnj 	dev_t dev;
4494484Swnj {
4506119Swnj 	register struct tty *tp = &pt_tty[minor(dev)];
4516119Swnj 	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
45218651Sbloom 	int stop, error;
4532281Stoy 
4544484Swnj 	/* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */
4557626Ssam 	if (cdevsw[major(dev)].d_open == ptcopen)
4567626Ssam 		switch (cmd) {
4577626Ssam 
4587626Ssam 		case TIOCPKT:
45918651Sbloom 			if (*(int *)data) {
46018651Sbloom 				if (pti->pt_flags & PF_UCNTL)
46118651Sbloom 					return (EINVAL);
4625427Swnj 				pti->pt_flags |= PF_PKT;
46318651Sbloom 			} else
4645427Swnj 				pti->pt_flags &= ~PF_PKT;
4658563Sroot 			return (0);
4667626Ssam 
46718651Sbloom 		case TIOCUCNTL:
46818651Sbloom 			if (*(int *)data) {
46918651Sbloom 				if (pti->pt_flags & PF_PKT)
47018651Sbloom 					return (EINVAL);
47118651Sbloom 				pti->pt_flags |= PF_UCNTL;
47218651Sbloom 			} else
47318651Sbloom 				pti->pt_flags &= ~PF_UCNTL;
47418651Sbloom 			return (0);
47518651Sbloom 
4767626Ssam 		case TIOCREMOTE:
4777626Ssam 			if (*(int *)data)
4785894Swnj 				pti->pt_flags |= PF_REMOTE;
4795894Swnj 			else
4805894Swnj 				pti->pt_flags &= ~PF_REMOTE;
48112753Ssam 			ttyflush(tp, FREAD|FWRITE);
4828563Sroot 			return (0);
4837626Ssam 
4847626Ssam 		case FIONBIO:
4857626Ssam 			if (*(int *)data)
4865427Swnj 				pti->pt_flags |= PF_NBIO;
4875411Swnj 			else
4885427Swnj 				pti->pt_flags &= ~PF_NBIO;
4898563Sroot 			return (0);
4907626Ssam 
4917626Ssam 		case TIOCSETP:
4927626Ssam 			while (getc(&tp->t_outq) >= 0)
4937626Ssam 				;
4947626Ssam 			break;
4955411Swnj 		}
49617182Smckusick 	error = ttioctl(tp, cmd, data, flag);
49718651Sbloom 	if (error < 0) {
49818651Sbloom 		if (pti->pt_flags & PF_UCNTL &&
49918651Sbloom 		    (cmd & ~0xff) == _IO(u,0)) {
50018651Sbloom 			if (cmd & 0xff) {
50118651Sbloom 				pti->pt_ucntl = (u_char)cmd;
50218651Sbloom 				ptcwakeup(tp, FREAD);
50318651Sbloom 			}
50418651Sbloom 			return (0);
50518651Sbloom 		}
5068563Sroot 		error = ENOTTY;
50718651Sbloom 	}
50818651Sbloom 	stop = (tp->t_flags & RAW) == 0 &&
50918651Sbloom 	    tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q);
5106119Swnj 	if (pti->pt_flags & PF_NOSTOP) {
5116119Swnj 		if (stop) {
5126119Swnj 			pti->pt_send &= TIOCPKT_NOSTOP;
5136119Swnj 			pti->pt_send |= TIOCPKT_DOSTOP;
5146119Swnj 			pti->pt_flags &= ~PF_NOSTOP;
51518651Sbloom 			ptcwakeup(tp, FREAD);
5166119Swnj 		}
5176119Swnj 	} else {
51818651Sbloom 		if (!stop) {
5196119Swnj 			pti->pt_send &= ~TIOCPKT_DOSTOP;
5206119Swnj 			pti->pt_send |= TIOCPKT_NOSTOP;
5216119Swnj 			pti->pt_flags |= PF_NOSTOP;
52218651Sbloom 			ptcwakeup(tp, FREAD);
5236119Swnj 		}
5246119Swnj 	}
5258563Sroot 	return (error);
5262281Stoy }
5272313Stoy #endif
528