|
|
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
1.1.1.4 ! root 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()
1.1 root 49: */
1.1.1.4 ! root 50: static char rcsid[] = "$Header: /cvsroot/src/sys/kern/tty_pty.c,v 1.2 1993/03/21 18:11:42 cgd Exp $";
1.1 root 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: */
81: struct tty pt_tty[NPTY];
82: struct pt_ioctl {
83: int pt_flags;
1.1.1.4 ! root 84: pid_t pt_selr, pt_selw;
1.1 root 85: u_char pt_send;
86: u_char pt_ucntl;
87: } pt_ioctl[NPTY];
88: int 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*/
99: ptsopen(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;
1.1.1.2 root 129: if (error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH,
1.1 root 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:
138: ptsclose(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);
1.1.1.4 ! root 149: return(0);
1.1 root 150: }
151:
152: ptsread(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:
161: again:
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: }
1.1.1.2 root 174: if (RB_LEN(&tp->t_can) == 0) {
1.1 root 175: if (flag & IO_NDELAY)
176: return (EWOULDBLOCK);
1.1.1.2 root 177: if (error = ttysleep(tp, (caddr_t)&tp->t_can,
1.1 root 178: TTIPRI | PCATCH, ttyin, 0))
179: return (error);
180: goto again;
181: }
1.1.1.2 root 182: while (RB_LEN(&tp->t_can) > 1 && uio->uio_resid > 0)
183: if (ureadc(getc(&tp->t_can), uio) < 0) {
1.1 root 184: error = EFAULT;
185: break;
186: }
1.1.1.2 root 187: if (RB_LEN(&tp->t_can) == 1)
188: (void) getc(&tp->t_can);
189: if (RB_LEN(&tp->t_can))
1.1 root 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: */
203: ptswrite(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: */
219: ptsstart(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:
233: ptcwakeup(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: }
1.1.1.4 ! root 244: wakeup((caddr_t)&tp->t_out.rb_tl);
1.1 root 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: }
1.1.1.2 root 252: wakeup((caddr_t)&tp->t_raw.rb_hd);
1.1 root 253: }
254: }
255:
256: /*ARGSUSED*/
257: #ifdef __STDC__
258: ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
259: #else
260: ptcopen(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:
1.1.1.4 ! root 284: extern struct tty *constty; /* -hv- 06.Oct.92*/
1.1 root 285: ptcclose(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;
1.1.1.4 ! root 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);
1.1 root 301: }
302:
303: ptcread(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: }
1.1.1.2 root 339: if (RB_LEN(&tp->t_out) && (tp->t_state&TS_TTSTOP) == 0)
1.1 root 340: break;
341: }
342: if ((tp->t_state&TS_CARR_ON) == 0)
343: return (0); /* EOF */
344: if (flag & IO_NDELAY)
345: return (EWOULDBLOCK);
1.1.1.4 ! root 346: if (error = tsleep((caddr_t)&tp->t_out.rb_tl, TTIPRI | PCATCH,
1.1 root 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) {
1.1.1.2 root 353: #ifdef was
1.1 root 354: cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
1.1.1.2 root 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
1.1 root 363: if (cc <= 0)
364: break;
365: error = uiomove(buf, cc, uio);
366: }
1.1.1.2 root 367: if (RB_LEN(&tp->t_out) <= tp->t_lowat) {
1.1 root 368: if (tp->t_state&TS_ASLEEP) {
369: tp->t_state &= ~TS_ASLEEP;
1.1.1.2 root 370: wakeup((caddr_t)&tp->t_out);
1.1 root 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:
381: ptsstop(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:
404: ptcselect(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) &&
1.1.1.2 root 424: RB_LEN(&tp->t_out) && (tp->t_state&TS_TTSTOP) == 0) {
1.1 root 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);
1.1.1.4 ! root 436: if (pti->pt_selr && (prev = pfind(pti->pt_selr)) && prev->p_wchan == (caddr_t)&selwait)
1.1 root 437: pti->pt_flags |= PF_RCOLL;
438: else
1.1.1.4 ! root 439: pti->pt_selr = p->p_pid;
1.1 root 440: break;
441:
442:
443: case FWRITE:
444: if (tp->t_state&TS_ISOPEN) {
445: if (pti->pt_flags & PF_REMOTE) {
1.1.1.2 root 446: if (RB_LEN(&tp->t_can) == 0)
1.1 root 447: return (1);
448: } else {
1.1.1.2 root 449: if (RB_LEN(&tp->t_raw) + RB_LEN(&tp->t_can) < TTYHOG-2)
1.1 root 450: return (1);
1.1.1.2 root 451: if (RB_LEN(&tp->t_can) == 0 && (tp->t_iflag&ICANON))
1.1 root 452: return (1);
453: }
454: }
1.1.1.4 ! root 455: if (pti->pt_selw && (prev = pfind(pti->pt_selw)) && prev->p_wchan == (caddr_t)&selwait)
1.1 root 456: pti->pt_flags |= PF_WCOLL;
457: else
1.1.1.4 ! root 458: pti->pt_selw = p->p_pid;
1.1 root 459: break;
460:
461: }
462: return (0);
463: }
464:
465: ptcwrite(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:
477: again:
478: if ((tp->t_state&TS_ISOPEN) == 0)
479: goto block;
480: if (pti->pt_flags & PF_REMOTE) {
1.1.1.2 root 481: if (RB_LEN(&tp->t_can))
1.1 root 482: goto block;
1.1.1.2 root 483: while (uio->uio_resid > 0 && RB_LEN(&tp->t_can) < TTYHOG - 1) {
1.1 root 484: if (cc == 0) {
485: cc = min(uio->uio_resid, BUFSIZ);
1.1.1.2 root 486: cc = min(cc, TTYHOG - 1 - RB_CONTIGPUT(&tp->t_can));
1.1 root 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: }
1.1.1.2 root 495: #ifdef was
1.1 root 496: if (cc)
497: (void) b_to_q((char *)cp, cc, &tp->t_canq);
1.1.1.2 root 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
1.1 root 505: cc = 0;
506: }
1.1.1.2 root 507: (void) putc(0, &tp->t_can);
1.1 root 508: ttwakeup(tp);
1.1.1.2 root 509: wakeup((caddr_t)&tp->t_can);
1.1 root 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) {
1.1.1.2 root 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);
1.1 root 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);
536: block:
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: }
1.1.1.2 root 550: if (error = tsleep((caddr_t)&tp->t_raw.rb_hd, TTOPRI | PCATCH,
1.1 root 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*/
560: ptyioctl(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;
1.1.1.3 root 583: ptcwakeup(tp, FREAD);
1.1 root 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;
1.1.1.3 root 590: ptcwakeup(tp, FREAD);
1.1 root 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:
1.1.1.4 ! root 633: #ifdef COMPAT_43
! 634: /* wkt */
1.1 root 635: case TIOCSETP:
636: case TIOCSETN:
1.1.1.4 ! root 637: #endif
1.1 root 638: case TIOCSETD:
639: case TIOCSETA:
640: case TIOCSETAW:
641: case TIOCSETAF:
1.1.1.2 root 642: while (getc(&tp->t_out) >= 0)
1.1 root 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);
658: if (error < 0)
659: error = ttioctl(tp, cmd, data, flag);
660: /*
661: * Since we use the tty queues internally,
662: * pty's can't be switched to disciplines which overwrite
663: * the queues. We can't tell anything about the discipline
664: * from here...
665: */
666: if (linesw[tp->t_line].l_rint != ttyinput) {
667: (*linesw[tp->t_line].l_close)(tp, flag);
668: tp->t_line = TTYDISC;
669: (void)(*linesw[tp->t_line].l_open)(dev, tp, flag);
670: error = ENOTTY;
671: }
672: if (error < 0) {
673: if (pti->pt_flags & PF_UCNTL &&
674: (cmd & ~0xff) == UIOCCMD(0)) {
675: if (cmd & 0xff) {
676: pti->pt_ucntl = (u_char)cmd;
677: ptcwakeup(tp, FREAD);
678: }
679: return (0);
680: }
681: error = ENOTTY;
682: }
683: /*
684: * If external processing and packet mode send ioctl packet.
685: */
686: if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
687: switch(cmd) {
688: case TIOCSETA:
689: case TIOCSETAW:
690: case TIOCSETAF:
1.1.1.4 ! root 691: #ifdef COMPAT_43
! 692: /* wkt */
1.1 root 693: case TIOCSETP:
694: case TIOCSETN:
695: case TIOCSETC:
696: case TIOCSLTC:
697: case TIOCLBIS:
698: case TIOCLBIC:
699: case TIOCLSET:
700: #endif
701: pti->pt_send |= TIOCPKT_IOCTL;
702: default:
703: break;
704: }
705: }
706: stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
707: && CCEQ(cc[VSTART], CTRL('q'));
708: if (pti->pt_flags & PF_NOSTOP) {
709: if (stop) {
710: pti->pt_send &= ~TIOCPKT_NOSTOP;
711: pti->pt_send |= TIOCPKT_DOSTOP;
712: pti->pt_flags &= ~PF_NOSTOP;
713: ptcwakeup(tp, FREAD);
714: }
715: } else {
716: if (!stop) {
717: pti->pt_send &= ~TIOCPKT_DOSTOP;
718: pti->pt_send |= TIOCPKT_NOSTOP;
719: pti->pt_flags |= PF_NOSTOP;
720: ptcwakeup(tp, FREAD);
721: }
722: }
723: return (error);
724: }
725: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.