tty_pty.c revision 1.35 1 /* $NetBSD: tty_pty.c,v 1.35 1996/07/02 21:19:02 pk 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 int
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 return 0;
282 }
283
284 void
285 ptcwakeup(tp, flag)
286 struct tty *tp;
287 int flag;
288 {
289 struct pt_softc *pti = &pt_softc[minor(tp->t_dev)];
290
291 if (flag & FREAD) {
292 selwakeup(&pti->pt_selr);
293 wakeup((caddr_t)&tp->t_outq.c_cf);
294 }
295 if (flag & FWRITE) {
296 selwakeup(&pti->pt_selw);
297 wakeup((caddr_t)&tp->t_rawq.c_cf);
298 }
299 }
300
301 int ptcopen __P((dev_t, int, int, struct proc *));
302
303 /*ARGSUSED*/
304 int
305 ptcopen(dev, flag, devtype, p)
306 dev_t dev;
307 int flag, devtype;
308 struct proc *p;
309 {
310 struct pt_softc *pti;
311 register struct tty *tp;
312
313 if (minor(dev) >= npty)
314 return (ENXIO);
315 pti = &pt_softc[minor(dev)];
316 if (!pti->pt_tty) {
317 tp = pti->pt_tty = ttymalloc();
318 tty_attach(tp);
319 }
320 else
321 tp = pti->pt_tty;
322 if (tp->t_oproc)
323 return (EIO);
324 tp->t_oproc = ptsstart;
325 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
326 tp->t_lflag &= ~EXTPROC;
327 pti->pt_flags = 0;
328 pti->pt_send = 0;
329 pti->pt_ucntl = 0;
330 return (0);
331 }
332
333 /*ARGSUSED*/
334 int
335 ptcclose(dev, flag, devtype, p)
336 dev_t dev;
337 int flag, devtype;
338 struct proc *p;
339 {
340 register struct pt_softc *pti = &pt_softc[minor(dev)];
341 register struct tty *tp = pti->pt_tty;
342
343 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
344 tp->t_state &= ~TS_CARR_ON;
345 tp->t_oproc = 0; /* mark closed */
346 return (0);
347 }
348
349 int
350 ptcread(dev, uio, flag)
351 dev_t dev;
352 struct uio *uio;
353 int flag;
354 {
355 register struct pt_softc *pti = &pt_softc[minor(dev)];
356 register struct tty *tp = pti->pt_tty;
357 char buf[BUFSIZ];
358 int error = 0, cc;
359
360 /*
361 * We want to block until the slave
362 * is open, and there's something to read;
363 * but if we lost the slave or we're NBIO,
364 * then return the appropriate error instead.
365 */
366 for (;;) {
367 if (tp->t_state&TS_ISOPEN) {
368 if (pti->pt_flags&PF_PKT && pti->pt_send) {
369 error = ureadc((int)pti->pt_send, uio);
370 if (error)
371 return (error);
372 if (pti->pt_send & TIOCPKT_IOCTL) {
373 cc = min(uio->uio_resid,
374 sizeof(tp->t_termios));
375 uiomove((caddr_t) &tp->t_termios,
376 cc, uio);
377 }
378 pti->pt_send = 0;
379 return (0);
380 }
381 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
382 error = ureadc((int)pti->pt_ucntl, uio);
383 if (error)
384 return (error);
385 pti->pt_ucntl = 0;
386 return (0);
387 }
388 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
389 break;
390 }
391 if ((tp->t_state&TS_CARR_ON) == 0)
392 return (0); /* EOF */
393 if (flag & IO_NDELAY)
394 return (EWOULDBLOCK);
395 error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH,
396 ttyin, 0);
397 if (error)
398 return (error);
399 }
400 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
401 error = ureadc(0, uio);
402 while (uio->uio_resid > 0 && error == 0) {
403 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
404 if (cc <= 0)
405 break;
406 error = uiomove(buf, cc, uio);
407 }
408 if (tp->t_outq.c_cc <= tp->t_lowat) {
409 if (tp->t_state&TS_ASLEEP) {
410 tp->t_state &= ~TS_ASLEEP;
411 wakeup((caddr_t)&tp->t_outq);
412 }
413 selwakeup(&tp->t_wsel);
414 }
415 return (error);
416 }
417
418
419 int
420 ptcwrite(dev, uio, flag)
421 dev_t dev;
422 register struct uio *uio;
423 int flag;
424 {
425 register struct pt_softc *pti = &pt_softc[minor(dev)];
426 register struct tty *tp = pti->pt_tty;
427 register u_char *cp = NULL;
428 register int cc = 0;
429 u_char locbuf[BUFSIZ];
430 int cnt = 0;
431 int error = 0;
432
433 again:
434 if ((tp->t_state&TS_ISOPEN) == 0)
435 goto block;
436 if (pti->pt_flags & PF_REMOTE) {
437 if (tp->t_canq.c_cc)
438 goto block;
439 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
440 if (cc == 0) {
441 cc = min(uio->uio_resid, BUFSIZ);
442 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
443 cp = locbuf;
444 error = uiomove((caddr_t)cp, cc, uio);
445 if (error)
446 return (error);
447 /* check again for safety */
448 if ((tp->t_state&TS_ISOPEN) == 0)
449 return (EIO);
450 }
451 if (cc)
452 (void) b_to_q((char *)cp, cc, &tp->t_canq);
453 cc = 0;
454 }
455 (void) putc(0, &tp->t_canq);
456 ttwakeup(tp);
457 wakeup((caddr_t)&tp->t_canq);
458 return (0);
459 }
460 while (uio->uio_resid > 0) {
461 if (cc == 0) {
462 cc = min(uio->uio_resid, BUFSIZ);
463 cp = locbuf;
464 error = uiomove((caddr_t)cp, cc, uio);
465 if (error)
466 return (error);
467 /* check again for safety */
468 if ((tp->t_state&TS_ISOPEN) == 0)
469 return (EIO);
470 }
471 while (cc > 0) {
472 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
473 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
474 wakeup((caddr_t)&tp->t_rawq);
475 goto block;
476 }
477 (*linesw[tp->t_line].l_rint)(*cp++, tp);
478 cnt++;
479 cc--;
480 }
481 cc = 0;
482 }
483 return (0);
484 block:
485 /*
486 * Come here to wait for slave to open, for space
487 * in outq, or space in rawq.
488 */
489 if ((tp->t_state&TS_CARR_ON) == 0)
490 return (EIO);
491 if (flag & IO_NDELAY) {
492 /* adjust for data copied in but not written */
493 uio->uio_resid += cc;
494 if (cnt == 0)
495 return (EWOULDBLOCK);
496 return (0);
497 }
498 error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH,
499 ttyout, 0);
500 if (error) {
501 /* adjust for data copied in but not written */
502 uio->uio_resid += cc;
503 return (error);
504 }
505 goto again;
506 }
507
508 int
509 ptcselect(dev, rw, p)
510 dev_t dev;
511 int rw;
512 struct proc *p;
513 {
514 register struct pt_softc *pti = &pt_softc[minor(dev)];
515 register struct tty *tp = pti->pt_tty;
516 int s;
517
518 if ((tp->t_state&TS_CARR_ON) == 0)
519 return (1);
520 switch (rw) {
521
522 case FREAD:
523 /*
524 * Need to block timeouts (ttrstart).
525 */
526 s = spltty();
527 if ((tp->t_state&TS_ISOPEN) &&
528 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
529 splx(s);
530 return (1);
531 }
532 splx(s);
533 /* FALLTHROUGH */
534
535 case 0: /* exceptional */
536 if ((tp->t_state&TS_ISOPEN) &&
537 (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
538 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)))
539 return (1);
540 selrecord(p, &pti->pt_selr);
541 break;
542
543
544 case FWRITE:
545 if (tp->t_state&TS_ISOPEN) {
546 if (pti->pt_flags & PF_REMOTE) {
547 if (tp->t_canq.c_cc == 0)
548 return (1);
549 } else {
550 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
551 return (1);
552 if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
553 return (1);
554 }
555 }
556 selrecord(p, &pti->pt_selw);
557 break;
558
559 }
560 return (0);
561 }
562
563
564 struct tty *
565 ptytty(dev)
566 dev_t dev;
567 {
568 register struct pt_softc *pti = &pt_softc[minor(dev)];
569 register struct tty *tp = pti->pt_tty;
570
571 return (tp);
572 }
573
574 /*ARGSUSED*/
575 int
576 ptyioctl(dev, cmd, data, flag, p)
577 dev_t dev;
578 u_long cmd;
579 caddr_t data;
580 int flag;
581 struct proc *p;
582 {
583 register struct pt_softc *pti = &pt_softc[minor(dev)];
584 register struct tty *tp = pti->pt_tty;
585 register u_char *cc = tp->t_cc;
586 int stop, error;
587
588 /*
589 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
590 * ttywflush(tp) will hang if there are characters in the outq.
591 */
592 if (cmd == TIOCEXT) {
593 /*
594 * When the EXTPROC bit is being toggled, we need
595 * to send an TIOCPKT_IOCTL if the packet driver
596 * is turned on.
597 */
598 if (*(int *)data) {
599 if (pti->pt_flags & PF_PKT) {
600 pti->pt_send |= TIOCPKT_IOCTL;
601 ptcwakeup(tp, FREAD);
602 }
603 tp->t_lflag |= EXTPROC;
604 } else {
605 if ((tp->t_state & EXTPROC) &&
606 (pti->pt_flags & PF_PKT)) {
607 pti->pt_send |= TIOCPKT_IOCTL;
608 ptcwakeup(tp, FREAD);
609 }
610 tp->t_lflag &= ~EXTPROC;
611 }
612 return(0);
613 } else
614 if (cdevsw[major(dev)].d_open == ptcopen)
615 switch (cmd) {
616
617 case TIOCGPGRP:
618 #ifdef COMPAT_SUNOS
619 {
620 /*
621 * I'm not sure about SunOS TIOCGPGRP semantics
622 * on PTYs, but it's something like this:
623 */
624 extern struct emul emul_sunos;
625 if (p->p_emul == &emul_sunos && tp->t_pgrp == 0)
626 return (EIO);
627 *(int *)data = tp->t_pgrp->pg_id;
628 return (0);
629 }
630 #endif
631 /*
632 * We avoid calling ttioctl on the controller since,
633 * in that case, tp must be the controlling terminal.
634 */
635 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
636 return (0);
637
638 case TIOCPKT:
639 if (*(int *)data) {
640 if (pti->pt_flags & PF_UCNTL)
641 return (EINVAL);
642 pti->pt_flags |= PF_PKT;
643 } else
644 pti->pt_flags &= ~PF_PKT;
645 return (0);
646
647 case TIOCUCNTL:
648 if (*(int *)data) {
649 if (pti->pt_flags & PF_PKT)
650 return (EINVAL);
651 pti->pt_flags |= PF_UCNTL;
652 } else
653 pti->pt_flags &= ~PF_UCNTL;
654 return (0);
655
656 case TIOCREMOTE:
657 if (*(int *)data)
658 pti->pt_flags |= PF_REMOTE;
659 else
660 pti->pt_flags &= ~PF_REMOTE;
661 ttyflush(tp, FREAD|FWRITE);
662 return (0);
663
664 #ifdef COMPAT_OLDTTY
665 case TIOCSETP:
666 case TIOCSETN:
667 #endif
668 case TIOCSETD:
669 case TIOCSETA:
670 case TIOCSETAW:
671 case TIOCSETAF:
672 ndflush(&tp->t_outq, tp->t_outq.c_cc);
673 break;
674
675 case TIOCSIG:
676 if (*(unsigned int *)data >= NSIG)
677 return(EINVAL);
678 if ((tp->t_lflag&NOFLSH) == 0)
679 ttyflush(tp, FREAD|FWRITE);
680 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
681 if ((*(unsigned int *)data == SIGINFO) &&
682 ((tp->t_lflag&NOKERNINFO) == 0))
683 ttyinfo(tp);
684 return(0);
685 }
686 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
687 if (error < 0)
688 error = ttioctl(tp, cmd, data, flag, p);
689 if (error < 0) {
690 if (pti->pt_flags & PF_UCNTL &&
691 (cmd & ~0xff) == UIOCCMD(0)) {
692 if (cmd & 0xff) {
693 pti->pt_ucntl = (u_char)cmd;
694 ptcwakeup(tp, FREAD);
695 }
696 return (0);
697 }
698 error = ENOTTY;
699 }
700 /*
701 * If external processing and packet mode send ioctl packet.
702 */
703 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
704 switch(cmd) {
705 case TIOCSETA:
706 case TIOCSETAW:
707 case TIOCSETAF:
708 #ifdef COMPAT_OLDTTY
709 case TIOCSETP:
710 case TIOCSETN:
711 case TIOCSETC:
712 case TIOCSLTC:
713 case TIOCLBIS:
714 case TIOCLBIC:
715 case TIOCLSET:
716 #endif
717 pti->pt_send |= TIOCPKT_IOCTL;
718 ptcwakeup(tp, FREAD);
719 default:
720 break;
721 }
722 }
723 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
724 && CCEQ(cc[VSTART], CTRL('q'));
725 if (pti->pt_flags & PF_NOSTOP) {
726 if (stop) {
727 pti->pt_send &= ~TIOCPKT_NOSTOP;
728 pti->pt_send |= TIOCPKT_DOSTOP;
729 pti->pt_flags &= ~PF_NOSTOP;
730 ptcwakeup(tp, FREAD);
731 }
732 } else {
733 if (!stop) {
734 pti->pt_send &= ~TIOCPKT_DOSTOP;
735 pti->pt_send |= TIOCPKT_NOSTOP;
736 pti->pt_flags |= PF_NOSTOP;
737 ptcwakeup(tp, FREAD);
738 }
739 }
740 return (error);
741 }
742