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