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