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