pty.c revision 9624
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	@(#)tty_pty.c	8.2 (Berkeley) 9/23/93
34 * $Id: tty_pty.c,v 1.12 1995/07/21 16:30:52 bde Exp $
35 */
36
37/*
38 * Pseudo-teletype Driver
39 * (Actually two drivers, requiring two entries in 'cdevsw')
40 */
41#include "pty.h"		/* XXX */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/ioctl.h>
46#include <sys/proc.h>
47#include <sys/tty.h>
48#include <sys/conf.h>
49#include <sys/file.h>
50#include <sys/uio.h>
51#include <sys/kernel.h>
52#include <sys/vnode.h>
53#include <sys/signalvar.h>
54
55#if NPTY == 1
56#undef NPTY
57#define	NPTY	32		/* crude XXX */
58#endif
59
60#define BUFSIZ 100		/* Chunk size iomoved to/from user */
61
62/*
63 * pts == /dev/tty[pqrs]?
64 * ptc == /dev/pty[pqrs]?
65 */
66struct	tty pt_tty[NPTY];	/* XXX */
67struct	pt_ioctl {
68	int	pt_flags;
69	struct	selinfo pt_selr, pt_selw;
70	u_char	pt_send;
71	u_char	pt_ucntl;
72} pt_ioctl[NPTY];		/* XXX */
73int	npty = NPTY;		/* for pstat -t */
74
75#define	PF_PKT		0x08		/* packet mode */
76#define	PF_STOPPED	0x10		/* user told stopped */
77#define	PF_REMOTE	0x20		/* remote and flow controlled input */
78#define	PF_NOSTOP	0x40
79#define PF_UCNTL	0x80		/* user control mode */
80
81void	ptsstop		__P((struct tty *, int));
82void	ptcwakeup	__P((struct tty *, int));
83
84/*
85 * Establish n (or default if n is 1) ptys in the system.
86 *
87 * XXX cdevsw & pstat require the array `pty[]' to be an array
88 */
89void
90ptyattach(n)
91	int n;
92{
93#ifdef notyet
94	char *mem;
95	register u_long ntb;
96#define	DEFAULT_NPTY	32
97
98	/* maybe should allow 0 => none? */
99	if (n <= 1)
100		n = DEFAULT_NPTY;
101	ntb = n * sizeof(struct tty);
102	mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),
103	    M_DEVBUF, M_WAITOK);
104	pt_tty = (struct tty *)mem;
105	mem = (char *)ALIGN(mem + ntb);
106	pt_ioctl = (struct pt_ioctl *)mem;
107	npty = n;
108#endif
109}
110
111/*ARGSUSED*/
112int
113ptsopen(dev, flag, devtype, p)
114	dev_t dev;
115	int flag, devtype;
116	struct proc *p;
117{
118	register struct tty *tp;
119	int error;
120
121	if (minor(dev) >= npty)
122		return (ENXIO);
123	tp = &pt_tty[minor(dev)];
124	if ((tp->t_state & TS_ISOPEN) == 0) {
125		ttychars(tp);		/* Set up default chars */
126		tp->t_iflag = TTYDEF_IFLAG;
127		tp->t_oflag = TTYDEF_OFLAG;
128		tp->t_lflag = TTYDEF_LFLAG;
129		tp->t_cflag = TTYDEF_CFLAG;
130		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
131		ttsetwater(tp);		/* would be done in xxparam() */
132	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
133		return (EBUSY);
134	if (tp->t_oproc)			/* Ctrlr still around. */
135		tp->t_state |= TS_CARR_ON;
136	while ((tp->t_state & TS_CARR_ON) == 0) {
137		if (flag&FNONBLOCK)
138			break;
139		error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
140				 "ptsopn", 0);
141		if (error)
142			return (error);
143	}
144	error = (*linesw[tp->t_line].l_open)(dev, tp);
145	if (error == 0)
146		ptcwakeup(tp, FREAD|FWRITE);
147	return (error);
148}
149
150int
151ptsclose(dev, flag, mode, p)
152	dev_t dev;
153	int flag, mode;
154	struct proc *p;
155{
156	register struct tty *tp;
157	int err;
158
159	tp = &pt_tty[minor(dev)];
160	err = (*linesw[tp->t_line].l_close)(tp, flag);
161	ptsstop(tp, FREAD|FWRITE);
162	(void) ttyclose(tp);
163	return (err);
164}
165
166int
167ptsread(dev, uio, flag)
168	dev_t dev;
169	struct uio *uio;
170	int flag;
171{
172	struct proc *p = curproc;
173	register struct tty *tp = &pt_tty[minor(dev)];
174	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
175	int error = 0;
176
177again:
178	if (pti->pt_flags & PF_REMOTE) {
179		while (isbackground(p, tp)) {
180			if ((p->p_sigignore & sigmask(SIGTTIN)) ||
181			    (p->p_sigmask & sigmask(SIGTTIN)) ||
182			    p->p_pgrp->pg_jobc == 0 ||
183			    p->p_flag & P_PPWAIT)
184				return (EIO);
185			pgsignal(p->p_pgrp, SIGTTIN, 1);
186			error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
187					 0);
188			if (error)
189				return (error);
190		}
191		if (tp->t_canq.c_cc == 0) {
192			if (flag & IO_NDELAY)
193				return (EWOULDBLOCK);
194			error = ttysleep(tp, &tp->t_canq, TTIPRI | PCATCH,
195					 "ptsin", 0);
196			if (error)
197				return (error);
198			goto again;
199		}
200		while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
201			if (ureadc(getc(&tp->t_canq), uio) < 0) {
202				error = EFAULT;
203				break;
204			}
205		if (tp->t_canq.c_cc == 1)
206			(void) getc(&tp->t_canq);
207		if (tp->t_canq.c_cc)
208			return (error);
209	} else
210		if (tp->t_oproc)
211			error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
212	ptcwakeup(tp, FWRITE);
213	return (error);
214}
215
216/*
217 * Write to pseudo-tty.
218 * Wakeups of controlling tty will happen
219 * indirectly, when tty driver calls ptsstart.
220 */
221int
222ptswrite(dev, uio, flag)
223	dev_t dev;
224	struct uio *uio;
225	int flag;
226{
227	register struct tty *tp;
228
229	tp = &pt_tty[minor(dev)];
230	if (tp->t_oproc == 0)
231		return (EIO);
232	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
233}
234
235/*
236 * Start output on pseudo-tty.
237 * Wake up process selecting or sleeping for input from controlling tty.
238 */
239void
240ptsstart(tp)
241	struct tty *tp;
242{
243	register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
244
245	if (tp->t_state & TS_TTSTOP)
246		return;
247	if (pti->pt_flags & PF_STOPPED) {
248		pti->pt_flags &= ~PF_STOPPED;
249		pti->pt_send = TIOCPKT_START;
250	}
251	ptcwakeup(tp, FREAD);
252}
253
254void
255ptcwakeup(tp, flag)
256	struct tty *tp;
257	int flag;
258{
259	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
260
261	if (flag & FREAD) {
262		selwakeup(&pti->pt_selr);
263		wakeup((caddr_t)&tp->t_outq.c_cf);
264	}
265	if (flag & FWRITE) {
266		selwakeup(&pti->pt_selw);
267		wakeup((caddr_t)&tp->t_rawq.c_cl);
268	}
269}
270
271/*ARGSUSED*/
272#ifdef __STDC__
273int
274ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
275#else
276int
277ptcopen(dev, flag, devtype, p)
278	dev_t dev;
279	int flag, devtype;
280	struct proc *p;
281#endif
282{
283	register struct tty *tp;
284	struct pt_ioctl *pti;
285
286	if (minor(dev) >= npty)
287		return (ENXIO);
288	tp = &pt_tty[minor(dev)];
289	if (tp->t_oproc)
290		return (EIO);
291	tp->t_oproc = ptsstart;
292#ifdef sun4c
293	tp->t_stop = ptsstop;
294#endif
295	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
296	tp->t_lflag &= ~EXTPROC;
297	pti = &pt_ioctl[minor(dev)];
298	pti->pt_flags = 0;
299	pti->pt_send = 0;
300	pti->pt_ucntl = 0;
301	return (0);
302}
303
304int
305ptcclose(dev)
306	dev_t dev;
307{
308	register struct tty *tp;
309
310	tp = &pt_tty[minor(dev)];
311	(void)(*linesw[tp->t_line].l_modem)(tp, 0);
312	tp->t_state &= ~TS_CARR_ON;
313	tp->t_oproc = 0;		/* mark closed */
314	tp->t_session = 0;
315	return (0);
316}
317
318int
319ptcread(dev, uio, flag)
320	dev_t dev;
321	struct uio *uio;
322	int flag;
323{
324	register struct tty *tp = &pt_tty[minor(dev)];
325	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
326	char buf[BUFSIZ];
327	int error = 0, cc;
328
329	/*
330	 * We want to block until the slave
331	 * is open, and there's something to read;
332	 * but if we lost the slave or we're NBIO,
333	 * then return the appropriate error instead.
334	 */
335	for (;;) {
336		if (tp->t_state&TS_ISOPEN) {
337			if (pti->pt_flags&PF_PKT && pti->pt_send) {
338				error = ureadc((int)pti->pt_send, uio);
339				if (error)
340					return (error);
341				if (pti->pt_send & TIOCPKT_IOCTL) {
342					cc = min(uio->uio_resid,
343						sizeof(tp->t_termios));
344					uiomove((caddr_t)&tp->t_termios, cc,
345						uio);
346				}
347				pti->pt_send = 0;
348				return (0);
349			}
350			if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
351				error = ureadc((int)pti->pt_ucntl, uio);
352				if (error)
353					return (error);
354				pti->pt_ucntl = 0;
355				return (0);
356			}
357			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
358				break;
359		}
360		if ((tp->t_state&TS_CARR_ON) == 0)
361			return (0);	/* EOF */
362		if (flag & IO_NDELAY)
363			return (EWOULDBLOCK);
364		error = tsleep(&tp->t_outq.c_cf, TTIPRI | PCATCH, "ptcin", 0);
365		if (error)
366			return (error);
367	}
368	if (pti->pt_flags & (PF_PKT|PF_UCNTL))
369		error = ureadc(0, uio);
370	while (uio->uio_resid > 0 && error == 0) {
371		cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
372		if (cc <= 0)
373			break;
374		error = uiomove(buf, cc, uio);
375	}
376	if (tp->t_outq.c_cc <= tp->t_lowat) {
377		if (tp->t_state&TS_ASLEEP) {
378			tp->t_state &= ~TS_ASLEEP;
379			wakeup((caddr_t)&tp->t_outq);
380		}
381		selwakeup(&tp->t_wsel);
382	}
383	return (error);
384}
385
386void
387ptsstop(tp, flush)
388	register struct tty *tp;
389	int flush;
390{
391	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
392	int flag;
393
394	/* note: FLUSHREAD and FLUSHWRITE already ok */
395	if (flush == 0) {
396		flush = TIOCPKT_STOP;
397		pti->pt_flags |= PF_STOPPED;
398	} else
399		pti->pt_flags &= ~PF_STOPPED;
400	pti->pt_send |= flush;
401	/* change of perspective */
402	flag = 0;
403	if (flush & FREAD)
404		flag |= FWRITE;
405	if (flush & FWRITE)
406		flag |= FREAD;
407	ptcwakeup(tp, flag);
408}
409
410int
411ptcselect(dev, rw, p)
412	dev_t dev;
413	int rw;
414	struct proc *p;
415{
416	register struct tty *tp = &pt_tty[minor(dev)];
417	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
418	int s;
419
420	if ((tp->t_state&TS_CARR_ON) == 0)
421		return (1);
422	switch (rw) {
423
424	case FREAD:
425		/*
426		 * Need to block timeouts (ttrstart).
427		 */
428		s = spltty();
429		if ((tp->t_state&TS_ISOPEN) &&
430		     tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
431			splx(s);
432			return (1);
433		}
434		splx(s);
435		/* FALLTHROUGH */
436
437	case 0:					/* exceptional */
438		if ((tp->t_state&TS_ISOPEN) &&
439		    ((pti->pt_flags&PF_PKT && pti->pt_send) ||
440		     (pti->pt_flags&PF_UCNTL && pti->pt_ucntl)))
441			return (1);
442		selrecord(p, &pti->pt_selr);
443		break;
444
445
446	case FWRITE:
447		if (tp->t_state&TS_ISOPEN) {
448			if (pti->pt_flags & PF_REMOTE) {
449			    if (tp->t_canq.c_cc == 0)
450				return (1);
451			} else {
452			    if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
453				    return (1);
454			    if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
455				    return (1);
456			}
457		}
458		selrecord(p, &pti->pt_selw);
459		break;
460
461	}
462	return (0);
463}
464
465int
466ptcwrite(dev, uio, flag)
467	dev_t dev;
468	register struct uio *uio;
469	int flag;
470{
471	register struct tty *tp = &pt_tty[minor(dev)];
472	register u_char *cp = 0;
473	register int cc = 0;
474	u_char locbuf[BUFSIZ];
475	int cnt = 0;
476	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
477	int error = 0;
478
479again:
480	if ((tp->t_state&TS_ISOPEN) == 0)
481		goto block;
482	if (pti->pt_flags & PF_REMOTE) {
483		if (tp->t_canq.c_cc)
484			goto block;
485		while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
486			if (cc == 0) {
487				cc = min(uio->uio_resid, BUFSIZ);
488				cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
489				cp = locbuf;
490				error = uiomove((caddr_t)cp, cc, uio);
491				if (error)
492					return (error);
493				/* check again for safety */
494				if ((tp->t_state&TS_ISOPEN) == 0)
495					return (EIO);
496			}
497			if (cc)
498				(void) b_to_q((char *)cp, cc, &tp->t_canq);
499			cc = 0;
500		}
501		(void) putc(0, &tp->t_canq);
502		ttwakeup(tp);
503		wakeup((caddr_t)&tp->t_canq);
504		return (0);
505	}
506	while (uio->uio_resid > 0) {
507		if (cc == 0) {
508			cc = min(uio->uio_resid, BUFSIZ);
509			cp = locbuf;
510			error = uiomove((caddr_t)cp, cc, uio);
511			if (error)
512				return (error);
513			/* check again for safety */
514			if ((tp->t_state&TS_ISOPEN) == 0)
515				return (EIO);
516		}
517		while (cc > 0) {
518			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
519			   (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
520				wakeup((caddr_t)&tp->t_rawq);
521				goto block;
522			}
523			(*linesw[tp->t_line].l_rint)(*cp++, tp);
524			cnt++;
525			cc--;
526		}
527		cc = 0;
528	}
529	return (0);
530block:
531	/*
532	 * Come here to wait for slave to open, for space
533	 * in outq, or space in rawq.
534	 */
535	if ((tp->t_state&TS_CARR_ON) == 0)
536		return (EIO);
537	if (flag & IO_NDELAY) {
538		/* adjust for data copied in but not written */
539		uio->uio_resid += cc;
540		if (cnt == 0)
541			return (EWOULDBLOCK);
542		return (0);
543	}
544	error = tsleep(&tp->t_rawq.c_cl, TTOPRI | PCATCH, "ptcout", 0);
545	if (error) {
546		/* adjust for data copied in but not written */
547		uio->uio_resid += cc;
548		return (error);
549	}
550	goto again;
551}
552
553struct tty *
554ptydevtotty(dev)
555	dev_t		dev;
556{
557	if (minor(dev) >= npty)
558		return (NULL);
559
560	return &pt_tty[minor(dev)];
561}
562
563/*ARGSUSED*/
564int
565ptyioctl(dev, cmd, data, flag, p)
566	dev_t dev;
567	int cmd;
568	caddr_t data;
569	int flag;
570	struct proc *p;
571{
572	register struct tty *tp = &pt_tty[minor(dev)];
573	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
574	register u_char *cc = tp->t_cc;
575	int stop, error;
576
577	/*
578	 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
579	 * ttywflush(tp) will hang if there are characters in the outq.
580	 */
581	if (cmd == TIOCEXT) {
582		/*
583		 * When the EXTPROC bit is being toggled, we need
584		 * to send an TIOCPKT_IOCTL if the packet driver
585		 * is turned on.
586		 */
587		if (*(int *)data) {
588			if (pti->pt_flags & PF_PKT) {
589				pti->pt_send |= TIOCPKT_IOCTL;
590				ptcwakeup(tp, FREAD);
591			}
592			tp->t_lflag |= EXTPROC;
593		} else {
594			if ((tp->t_state & EXTPROC) &&
595			    (pti->pt_flags & PF_PKT)) {
596				pti->pt_send |= TIOCPKT_IOCTL;
597				ptcwakeup(tp, FREAD);
598			}
599			tp->t_lflag &= ~EXTPROC;
600		}
601		return(0);
602	} else
603	if (cdevsw[major(dev)].d_open == ptcopen)
604		switch (cmd) {
605
606		case TIOCGPGRP:
607			/*
608			 * We aviod calling ttioctl on the controller since,
609			 * in that case, tp must be the controlling terminal.
610			 */
611			*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
612			return (0);
613
614		case TIOCPKT:
615			if (*(int *)data) {
616				if (pti->pt_flags & PF_UCNTL)
617					return (EINVAL);
618				pti->pt_flags |= PF_PKT;
619			} else
620				pti->pt_flags &= ~PF_PKT;
621			return (0);
622
623		case TIOCUCNTL:
624			if (*(int *)data) {
625				if (pti->pt_flags & PF_PKT)
626					return (EINVAL);
627				pti->pt_flags |= PF_UCNTL;
628			} else
629				pti->pt_flags &= ~PF_UCNTL;
630			return (0);
631
632		case TIOCREMOTE:
633			if (*(int *)data)
634				pti->pt_flags |= PF_REMOTE;
635			else
636				pti->pt_flags &= ~PF_REMOTE;
637			ttyflush(tp, FREAD|FWRITE);
638			return (0);
639
640#ifdef COMPAT_43
641		case TIOCSETP:
642		case TIOCSETN:
643#endif
644		case TIOCSETD:
645		case TIOCSETA:
646		case TIOCSETAW:
647		case TIOCSETAF:
648			ndflush(&tp->t_outq, tp->t_outq.c_cc);
649			break;
650
651		case TIOCSIG:
652			if (*(unsigned int *)data >= NSIG)
653				return(EINVAL);
654			if ((tp->t_lflag&NOFLSH) == 0)
655				ttyflush(tp, FREAD|FWRITE);
656			pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
657			if ((*(unsigned int *)data == SIGINFO) &&
658			    ((tp->t_lflag&NOKERNINFO) == 0))
659				ttyinfo(tp);
660			return(0);
661		}
662	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
663	if (error < 0)
664		 error = ttioctl(tp, cmd, data, flag);
665	if (error < 0) {
666		if (pti->pt_flags & PF_UCNTL &&
667		    (cmd & ~0xff) == UIOCCMD(0)) {
668			if (cmd & 0xff) {
669				pti->pt_ucntl = (u_char)cmd;
670				ptcwakeup(tp, FREAD);
671			}
672			return (0);
673		}
674		error = ENOTTY;
675	}
676	/*
677	 * If external processing and packet mode send ioctl packet.
678	 */
679	if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
680		switch(cmd) {
681		case TIOCSETA:
682		case TIOCSETAW:
683		case TIOCSETAF:
684#ifdef COMPAT_43
685		case TIOCSETP:
686		case TIOCSETN:
687#endif
688#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
689		case TIOCSETC:
690		case TIOCSLTC:
691		case TIOCLBIS:
692		case TIOCLBIC:
693		case TIOCLSET:
694#endif
695			pti->pt_send |= TIOCPKT_IOCTL;
696			ptcwakeup(tp, FREAD);
697		default:
698			break;
699		}
700	}
701	stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
702		&& CCEQ(cc[VSTART], CTRL('q'));
703	if (pti->pt_flags & PF_NOSTOP) {
704		if (stop) {
705			pti->pt_send &= ~TIOCPKT_NOSTOP;
706			pti->pt_send |= TIOCPKT_DOSTOP;
707			pti->pt_flags &= ~PF_NOSTOP;
708			ptcwakeup(tp, FREAD);
709		}
710	} else {
711		if (!stop) {
712			pti->pt_send &= ~TIOCPKT_DOSTOP;
713			pti->pt_send |= TIOCPKT_NOSTOP;
714			pti->pt_flags |= PF_NOSTOP;
715			ptcwakeup(tp, FREAD);
716		}
717	}
718	return (error);
719}
720