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