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