1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)tty_pty.c 1.3 (2.11BSD GTE) 1997/5/2 7: */ 8: 9: /* 10: * Pseudo-teletype Driver 11: * (Actually two drivers, requiring two entries in 'cdevsw') 12: */ 13: #include "pty.h" 14: 15: #if NPTY > 0 16: #include "param.h" 17: #include "systm.h" 18: #include "ioctl.h" 19: #include "tty.h" 20: #include "user.h" 21: #include "conf.h" 22: #include "file.h" 23: #include "proc.h" 24: #include "uio.h" 25: #include "kernel.h" 26: #include "inode.h" 27: 28: extern int TTYHOG; /* see tty.c */ 29: 30: #if NPTY == 1 31: #undef NPTY 32: #define NPTY 16 /* crude XXX */ 33: #endif 34: 35: #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 36: 37: /* 38: * pts == /dev/tty[pqrs]? 39: * ptc == /dev/pty[pqrs]? 40: */ 41: struct tty pt_tty[NPTY]; 42: struct pt_ioctl { 43: int pt_flags; 44: struct proc *pt_selr, *pt_selw; 45: u_char pt_send; 46: u_char pt_ucntl; 47: } pt_ioctl[NPTY]; 48: int npty = NPTY; /* for pstat -t */ 49: 50: #define PF_RCOLL 0x01 51: #define PF_WCOLL 0x02 52: #define PF_PKT 0x08 /* packet mode */ 53: #define PF_STOPPED 0x10 /* user told stopped */ 54: #define PF_REMOTE 0x20 /* remote and flow controlled input */ 55: #define PF_NOSTOP 0x40 56: #define PF_UCNTL 0x80 /* user control mode */ 57: 58: /*ARGSUSED*/ 59: ptsopen(dev, flag) 60: dev_t dev; 61: { 62: register struct tty *tp; 63: int error; 64: 65: #ifdef lint 66: npty = npty; 67: #endif 68: if (minor(dev) >= NPTY) 69: return (ENXIO); 70: tp = &pt_tty[minor(dev)]; 71: if ((tp->t_state & TS_ISOPEN) == 0) { 72: ttychars(tp); /* Set up default chars */ 73: tp->t_ispeed = tp->t_ospeed = EXTB; 74: tp->t_flags = 0; /* No features (nor raw mode) */ 75: } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 76: return (EBUSY); 77: if (tp->t_oproc) /* Ctrlr still around. */ 78: tp->t_state |= TS_CARR_ON; 79: while ((tp->t_state & TS_CARR_ON) == 0) { 80: tp->t_state |= TS_WOPEN; 81: sleep((caddr_t)&tp->t_rawq, TTIPRI); 82: } 83: error = (*linesw[tp->t_line].l_open)(dev, tp); 84: ptcwakeup(tp, FREAD|FWRITE); 85: return (error); 86: } 87: 88: ptsclose(dev, flag) 89: dev_t dev; 90: int flag; 91: { 92: register struct tty *tp; 93: 94: tp = &pt_tty[minor(dev)]; 95: (*linesw[tp->t_line].l_close)(tp, flag); 96: ttyclose(tp); 97: ptcwakeup(tp, FREAD|FWRITE); 98: } 99: 100: ptsread(dev, uio, flag) 101: dev_t dev; 102: register struct uio *uio; 103: int flag; 104: { 105: register struct tty *tp = &pt_tty[minor(dev)]; 106: register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 107: int error = 0; 108: 109: again: 110: if (pti->pt_flags & PF_REMOTE) { 111: while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 112: if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 113: (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 114: u.u_procp->p_flag&SVFORK) 115: return (EIO); 116: gsignal(u.u_procp->p_pgrp, SIGTTIN); 117: sleep((caddr_t)&lbolt, TTIPRI); 118: } 119: if (tp->t_canq.c_cc == 0) { 120: if (flag & IO_NDELAY) 121: return (EWOULDBLOCK); 122: sleep((caddr_t)&tp->t_canq, TTIPRI); 123: goto again; 124: } 125: while (tp->t_canq.c_cc > 1 && uio->uio_resid) 126: if (ureadc(getc(&tp->t_canq), uio) < 0) { 127: error = EFAULT; 128: break; 129: } 130: if (tp->t_canq.c_cc == 1) 131: (void) getc(&tp->t_canq); 132: if (tp->t_canq.c_cc) 133: return (error); 134: } else 135: if (tp->t_oproc) 136: error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 137: ptcwakeup(tp, FWRITE); 138: return (error); 139: } 140: 141: /* 142: * Write to pseudo-tty. 143: * Wakeups of controlling tty will happen 144: * indirectly, when tty driver calls ptsstart. 145: */ 146: ptswrite(dev, uio, flag) 147: dev_t dev; 148: register struct uio *uio; 149: int flag; 150: { 151: register struct tty *tp; 152: 153: tp = &pt_tty[minor(dev)]; 154: if (tp->t_oproc == 0) 155: return (EIO); 156: return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 157: } 158: 159: /* 160: * Start output on pseudo-tty. 161: * Wake up process selecting or sleeping for input from controlling tty. 162: */ 163: ptsstart(tp) 164: struct tty *tp; 165: { 166: register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 167: 168: if (tp->t_state & TS_TTSTOP) 169: return; 170: if (pti->pt_flags & PF_STOPPED) { 171: pti->pt_flags &= ~PF_STOPPED; 172: pti->pt_send = TIOCPKT_START; 173: } 174: ptcwakeup(tp, FREAD); 175: } 176: 177: ptcwakeup(tp, flag) 178: struct tty *tp; 179: { 180: struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 181: 182: if (flag & FREAD) { 183: if (pti->pt_selr) { 184: selwakeup(pti->pt_selr, (long)(pti->pt_flags & PF_RCOLL)); 185: pti->pt_selr = 0; 186: pti->pt_flags &= ~PF_RCOLL; 187: } 188: wakeup((caddr_t)&tp->t_outq.c_cf); 189: } 190: if (flag & FWRITE) { 191: if (pti->pt_selw) { 192: selwakeup(pti->pt_selw, (long)(pti->pt_flags & PF_WCOLL)); 193: pti->pt_selw = 0; 194: pti->pt_flags &= ~PF_WCOLL; 195: } 196: wakeup((caddr_t)&tp->t_rawq.c_cf); 197: } 198: } 199: 200: /*ARGSUSED*/ 201: ptcopen(dev, flag) 202: dev_t dev; 203: int flag; 204: { 205: register struct tty *tp; 206: struct pt_ioctl *pti; 207: 208: if (minor(dev) >= NPTY) 209: return (ENXIO); 210: tp = &pt_tty[minor(dev)]; 211: if (tp->t_oproc) 212: return (EIO); 213: tp->t_oproc = ptsstart; 214: (void)(*linesw[tp->t_line].l_modem)(tp, 1); 215: pti = &pt_ioctl[minor(dev)]; 216: pti->pt_flags = 0; 217: pti->pt_send = 0; 218: pti->pt_ucntl = 0; 219: return (0); 220: } 221: 222: ptcclose(dev, flag) 223: dev_t dev; 224: int flag; 225: { 226: register struct tty *tp; 227: 228: tp = &pt_tty[minor(dev)]; 229: (void)(*linesw[tp->t_line].l_modem)(tp, 0); 230: tp->t_state &= ~TS_CARR_ON; 231: tp->t_oproc = 0; /* mark closed */ 232: } 233: 234: ptcread(dev, uio, flag) 235: dev_t dev; 236: register struct uio *uio; 237: int flag; 238: { 239: register struct tty *tp = &pt_tty[minor(dev)]; 240: struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 241: char buf[BUFSIZ]; 242: int error = 0, cc; 243: 244: /* 245: * We want to block until the slave 246: * is open, and there's something to read; 247: * but if we lost the slave or we're NBIO, 248: * then return the appropriate error instead. 249: */ 250: for (;;) { 251: if (tp->t_state&TS_ISOPEN) { 252: if (pti->pt_flags&PF_PKT && pti->pt_send) { 253: error = ureadc((int)pti->pt_send, uio); 254: if (error) 255: return (error); 256: pti->pt_send = 0; 257: return (0); 258: } 259: if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 260: error = ureadc((int)pti->pt_ucntl, uio); 261: if (error) 262: return (error); 263: pti->pt_ucntl = 0; 264: return (0); 265: } 266: if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 267: break; 268: } 269: if ((tp->t_state&TS_CARR_ON) == 0) 270: return (0); /* EOF */ 271: if (flag & IO_NDELAY) 272: return (EWOULDBLOCK); 273: sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 274: } 275: if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 276: error = ureadc(0, uio); 277: while (uio->uio_resid && error == 0) { 278: cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 279: if (cc <= 0) 280: break; 281: error = uiomove(buf, cc, uio); 282: } 283: if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 284: if (tp->t_state&TS_ASLEEP) { 285: tp->t_state &= ~TS_ASLEEP; 286: wakeup((caddr_t)&tp->t_outq); 287: } 288: if (tp->t_wsel) { 289: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 290: tp->t_wsel = 0; 291: tp->t_state &= ~TS_WCOLL; 292: } 293: } 294: return (error); 295: } 296: 297: ptsstop(tp, flush) 298: register struct tty *tp; 299: int flush; 300: { 301: struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 302: int flag; 303: 304: /* note: FLUSHREAD and FLUSHWRITE already ok */ 305: if (flush == 0) { 306: flush = TIOCPKT_STOP; 307: pti->pt_flags |= PF_STOPPED; 308: } else 309: pti->pt_flags &= ~PF_STOPPED; 310: pti->pt_send |= flush; 311: /* change of perspective */ 312: flag = 0; 313: if (flush & FREAD) 314: flag |= FWRITE; 315: if (flush & FWRITE) 316: flag |= FREAD; 317: ptcwakeup(tp, flag); 318: } 319: 320: ptcselect(dev, rw) 321: dev_t dev; 322: int rw; 323: { 324: register struct tty *tp = &pt_tty[minor(dev)]; 325: struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 326: struct proc *p; 327: int s; 328: 329: if ((tp->t_state&TS_CARR_ON) == 0) 330: return (1); 331: switch (rw) { 332: 333: case FREAD: 334: /* 335: * Need to block timeouts (ttrstart). 336: */ 337: s = spltty(); 338: if ((tp->t_state&TS_ISOPEN) && 339: tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 340: splx(s); 341: return (1); 342: } 343: splx(s); 344: /* FALLTHROUGH */ 345: 346: case 0: /* exceptional */ 347: if ((tp->t_state&TS_ISOPEN) && 348: (pti->pt_flags&PF_PKT && pti->pt_send || 349: pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 350: return (1); 351: if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 352: pti->pt_flags |= PF_RCOLL; 353: else 354: pti->pt_selr = u.u_procp; 355: break; 356: 357: 358: case FWRITE: 359: if (tp->t_state&TS_ISOPEN) { 360: if (pti->pt_flags & PF_REMOTE) { 361: if (tp->t_canq.c_cc == 0) 362: return (1); 363: } else { 364: if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 365: return (1); 366: if (tp->t_canq.c_cc == 0 && 367: (tp->t_flags & (RAW|CBREAK)) == 0) 368: return (1); 369: } 370: } 371: if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 372: pti->pt_flags |= PF_WCOLL; 373: else 374: pti->pt_selw = u.u_procp; 375: break; 376: 377: } 378: return (0); 379: } 380: 381: ptcwrite(dev, uio, flag) 382: dev_t dev; 383: register struct uio *uio; 384: int flag; 385: { 386: register struct tty *tp = &pt_tty[minor(dev)]; 387: register char *cp; 388: register int cc = 0; 389: char locbuf[BUFSIZ]; 390: int cnt = 0; 391: struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 392: int error = 0; 393: 394: again: 395: if ((tp->t_state&TS_ISOPEN) == 0) 396: goto block; 397: if (pti->pt_flags & PF_REMOTE) { 398: if (tp->t_canq.c_cc) 399: goto block; 400: while (uio->uio_resid && tp->t_canq.c_cc < TTYHOG - 1) { 401: if (cc == 0) { 402: cc = MIN(uio->uio_resid, BUFSIZ); 403: cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 404: cp = locbuf; 405: error = uiomove(cp, cc, uio); 406: if (error) 407: return (error); 408: /* check again for safety */ 409: if ((tp->t_state&TS_ISOPEN) == 0) 410: return (EIO); 411: } 412: if (cc) 413: (void) b_to_q(cp, cc, &tp->t_canq); 414: cc = 0; 415: } 416: (void) putc(0, &tp->t_canq); 417: ttwakeup(tp); 418: wakeup((caddr_t)&tp->t_canq); 419: return (0); 420: } 421: while (uio->uio_resid > 0) { 422: if (cc == 0) { 423: cc = MIN(uio->uio_resid, BUFSIZ); 424: cp = locbuf; 425: error = uiomove(cp, cc, uio); 426: if (error) 427: return (error); 428: /* check again for safety */ 429: if ((tp->t_state&TS_ISOPEN) == 0) 430: return (EIO); 431: } 432: while (cc > 0) { 433: if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 434: (tp->t_canq.c_cc > 0 || 435: tp->t_flags & (RAW|CBREAK))) { 436: wakeup((caddr_t)&tp->t_rawq); 437: goto block; 438: } 439: (*linesw[tp->t_line].l_rint)(*cp++, tp); 440: cnt++; 441: cc--; 442: } 443: cc = 0; 444: } 445: return (0); 446: block: 447: /* 448: * Come here to wait for slave to open, for space 449: * in outq, or space in rawq. 450: */ 451: if ((tp->t_state&TS_CARR_ON) == 0) 452: return (EIO); 453: if (flag & IO_NDELAY) { 454: /* adjust for data copied in but not written */ 455: uio->uio_resid += cc; 456: if (cnt == 0) 457: return (EWOULDBLOCK); 458: return (0); 459: } 460: sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 461: goto again; 462: } 463: 464: /*ARGSUSED*/ 465: ptyioctl(dev, cmd, data, flag) 466: caddr_t data; 467: u_int cmd; 468: dev_t dev; 469: int flag; 470: { 471: register struct tty *tp = &pt_tty[minor(dev)]; 472: register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 473: int stop, error; 474: extern ttyinput(); 475: 476: /* 477: * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 478: * ttywflush(tp) will hang if there are characters in the outq. 479: */ 480: if (cdevsw[major(dev)].d_open == ptcopen) 481: switch (cmd) { 482: 483: case TIOCPKT: 484: if (*(int *)data) { 485: if (pti->pt_flags & PF_UCNTL) 486: return (EINVAL); 487: pti->pt_flags |= PF_PKT; 488: } else 489: pti->pt_flags &= ~PF_PKT; 490: return (0); 491: 492: case TIOCUCNTL: 493: if (*(int *)data) { 494: if (pti->pt_flags & PF_PKT) 495: return (EINVAL); 496: pti->pt_flags |= PF_UCNTL; 497: } else 498: pti->pt_flags &= ~PF_UCNTL; 499: return (0); 500: 501: case TIOCREMOTE: 502: if (*(int *)data) 503: pti->pt_flags |= PF_REMOTE; 504: else 505: pti->pt_flags &= ~PF_REMOTE; 506: ttyflush(tp, FREAD|FWRITE); 507: return (0); 508: 509: case TIOCSETP: 510: case TIOCSETN: 511: case TIOCSETD: 512: while (getc(&tp->t_outq) >= 0) 513: ; 514: break; 515: } 516: /* 517: * Unsure if the comment below still applies or not. For now put the 518: * new code in ifdef'd out. 519: */ 520: 521: #ifdef four_four_bsd 522: error = (*linesw[t->t_line].l_ioctl(tp, cmd, data, flag); 523: if (error < 0) 524: error = ttioctl(tp, cmd, data, flag); 525: #else 526: error = ttioctl(tp, cmd, data, flag); 527: /* 528: * Since we use the tty queues internally, 529: * pty's can't be switched to disciplines which overwrite 530: * the queues. We can't tell anything about the discipline 531: * from here... 532: */ 533: if (linesw[tp->t_line].l_rint != ttyinput) { 534: (*linesw[tp->t_line].l_close)(tp, flag); 535: tp->t_line = 0; 536: (void)(*linesw[tp->t_line].l_open)(dev, tp); 537: error = ENOTTY; 538: } 539: #endif 540: if (error < 0) { 541: if (pti->pt_flags & PF_UCNTL && 542: (cmd & ~0xff) == UIOCCMD(0)) { 543: if (cmd & 0xff) { 544: pti->pt_ucntl = (u_char)cmd; 545: ptcwakeup(tp, FREAD); 546: } 547: return (0); 548: } 549: error = ENOTTY; 550: } 551: stop = (tp->t_flags & RAW) == 0 && 552: tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q); 553: if (pti->pt_flags & PF_NOSTOP) { 554: if (stop) { 555: pti->pt_send &= ~TIOCPKT_NOSTOP; 556: pti->pt_send |= TIOCPKT_DOSTOP; 557: pti->pt_flags &= ~PF_NOSTOP; 558: ptcwakeup(tp, FREAD); 559: } 560: } else { 561: if (!stop) { 562: pti->pt_send &= ~TIOCPKT_DOSTOP; 563: pti->pt_send |= TIOCPKT_NOSTOP; 564: pti->pt_flags |= PF_NOSTOP; 565: ptcwakeup(tp, FREAD); 566: } 567: } 568: return (error); 569: } 570: #endif