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