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