1*2313Stoy /* tty_pty.c 4.3 01/29/81 */ 22283Stoy 32281Stoy /* 42281Stoy * Pseudo-teletype Driver 52281Stoy * (Actually two drivers, requiring two entries in 'cdevsw') 62281Stoy */ 72281Stoy #include "../h/param.h" 82281Stoy #include "../h/systm.h" 92281Stoy #include "../h/tty.h" 102281Stoy #include "../h/dir.h" 112281Stoy #include "../h/user.h" 122281Stoy #include "../h/conf.h" 132281Stoy #include "../h/buf.h" 14*2313Stoy #include "../pty.h" 152281Stoy 16*2313Stoy #if WANTPTY > 0 17*2313Stoy 182281Stoy #define NPTY 16 /* Number of pseudo-teletypes */ 192281Stoy #define BUFSIZ 100 /* Chunk size iomoved from user */ 202281Stoy #define ALLDELAYS (NLDELAY|TBDELAY|XTABS|CRDELAY|VTDELAY) 212281Stoy /* 222281Stoy * A pseudo-teletype is a special device which is not unlike a pipe. 232281Stoy * It is used to communicate between two processes. However, it allows 242281Stoy * one to simulate a teletype, including mode setting, interrupt, and 252281Stoy * multiple end of files (all not possible on a pipe). There are 262281Stoy * really two drivers here. One is the device which looks like a TTY 272281Stoy * and can be thought of as the slave device, and hence its routines 282281Stoy * are prefixed with 'pts' (PTY Slave). The other driver can be 292281Stoy * thought of as the controlling device, and its routines are prefixed 302281Stoy * by 'ptc' (PTY Controller). To type on the simulated keyboard of the 312281Stoy * PTY, one does a 'write' to the controlling device. To get the 322281Stoy * simulated printout from the PTY, one does a 'read' on the controlling 332281Stoy * device. Normally, the controlling device is called 'ptyx' and the 342281Stoy * slave device is called 'ttyx' (to make programs like 'who' happy). 352281Stoy */ 362281Stoy 372281Stoy struct tty pt_tty[NPTY]; /* TTY headers for PTYs */ 382281Stoy 392281Stoy /*ARGSUSED*/ 402281Stoy ptsopen(dev, flag) 412281Stoy dev_t dev; 422281Stoy { /* Open for PTY Slave */ 432281Stoy register struct tty *tp; 442281Stoy 452281Stoy if(minor(dev) >= NPTY) { 462281Stoy u.u_error = ENXIO; 472281Stoy return; 482281Stoy } 492281Stoy tp = &pt_tty[minor(dev)]; 502281Stoy if((tp->t_state & ISOPEN) == 0) { 512281Stoy ttychars(tp); /* Set up default chars */ 522281Stoy tp->t_flags = 0; /* No features (nor raw mode) */ 532281Stoy } else if(tp->t_state&XCLUDE && u.u_uid != 0) { 542281Stoy u.u_error = EBUSY; 552281Stoy return; 562281Stoy } 572281Stoy if(tp->t_oproc) /* Ctrlr still around. */ 582281Stoy tp->t_state |= CARR_ON; 592281Stoy while((tp->t_state & CARR_ON) == 0) { 602281Stoy tp->t_state |= WOPEN; 612281Stoy sleep((caddr_t)&tp->t_rawq, TTIPRI); 622281Stoy } 632281Stoy (*linesw[tp->t_line].l_open)(dev, tp); 642281Stoy } 652281Stoy 662281Stoy ptsclose(dev) 672281Stoy dev_t dev; 682281Stoy { /* Close slave part of PTY */ 692281Stoy register struct tty *tp; 702281Stoy 712281Stoy tp = &pt_tty[minor(dev)]; 722281Stoy (*linesw[tp->t_line].l_close)(tp); 732281Stoy } 742281Stoy 752281Stoy ptsread(dev) 762281Stoy dev_t dev; 772281Stoy { /* Read from PTY, i.e. from data written by controlling device */ 782281Stoy register struct tty *tp; 792281Stoy 802281Stoy tp = &pt_tty[minor(dev)]; 812281Stoy if(tp->t_oproc) { 822281Stoy (*linesw[tp->t_line].l_read)(tp); 832281Stoy /* Wakeup other half if sleeping */ 842281Stoy wakeup((caddr_t)&tp->t_rawq.c_cf); 852281Stoy } 862281Stoy } 872281Stoy 882281Stoy ptswrite(dev) 892281Stoy dev_t dev; 902281Stoy { /* Write on PTY, i.e. to be read from 912281Stoy controlling device */ 922281Stoy register struct tty *tp; 932281Stoy 942281Stoy tp = &pt_tty[minor(dev)]; 952281Stoy /* Wait for controlling device to be opened */ 962281Stoy if(tp->t_oproc) 972281Stoy (*linesw[tp->t_line].l_write)(tp); 982281Stoy } 992281Stoy 1002281Stoy ptsstart(tp) 1012281Stoy struct tty *tp; 1022281Stoy { /* Called by 'ttstart' to output a character. 1032281Stoy Merely wakes up controlling half, which 1042281Stoy does actual work */ 1052281Stoy if(tp->t_state & TTSTOP) 1062281Stoy return; 1072281Stoy wakeup((caddr_t)&tp->t_outq.c_cf); 1082281Stoy } 1092281Stoy 1102281Stoy /*ARGSUSED*/ 1112281Stoy ptcopen(dev, flag) 1122281Stoy dev_t dev; 1132281Stoy { /* Open for PTY Controller */ 1142281Stoy register struct tty *tp; 1152281Stoy 1162281Stoy if(minor(dev) >= NPTY) { 1172281Stoy u.u_error = ENXIO; 1182281Stoy return; 1192281Stoy } 1202281Stoy tp = &pt_tty[minor(dev)]; 1212281Stoy if(tp->t_oproc) { 1222281Stoy u.u_error = EIO; 1232281Stoy return; 1242281Stoy } 1252281Stoy tp->t_oproc = ptsstart; /* Set address of start routine */ 1262281Stoy tp->t_iproc = 0; 1272281Stoy if(tp->t_state & WOPEN) 1282281Stoy wakeup((caddr_t)&tp->t_rawq); 1292281Stoy tp->t_state |= CARR_ON; 1302281Stoy } 1312281Stoy 1322281Stoy ptcclose(dev) 1332281Stoy dev_t dev; 1342281Stoy { /* Close controlling part of PTY */ 1352281Stoy register struct tty *tp; 1362281Stoy 1372281Stoy tp = &pt_tty[minor(dev)]; 1382281Stoy if(tp->t_state & ISOPEN) 1392281Stoy gsignal(tp->t_pgrp, SIGHUP); 1402281Stoy tp->t_state &= ~CARR_ON; /* Virtual carrier is gone */ 1412281Stoy flushtty(tp); /* Clean things up */ 1422281Stoy tp->t_oproc = 0; /* Mark as closed */ 1432281Stoy } 1442281Stoy 1452281Stoy ptcread(dev) 1462281Stoy dev_t dev; 1472281Stoy { /* Read from PTY's output buffer */ 1482281Stoy register struct tty *tp; 1492281Stoy 1502281Stoy tp = &pt_tty[minor(dev)]; 1512281Stoy if((tp->t_state&(CARR_ON|ISOPEN)) == 0) 1522281Stoy return; 1532281Stoy while(tp->t_outq.c_cc == 0 || /* Wait for something to arrive */ 1542281Stoy (tp->t_state&TTSTOP)) /* (Woken by ptsstart) */ 1552281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 1562281Stoy while(tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0); 1572281Stoy if(tp->t_outq.c_cc <= TTLOWAT(tp) && (tp->t_state&ASLEEP)) { 1582281Stoy tp->t_state &= ~ASLEEP; 1592281Stoy if(tp->t_chan) 1602281Stoy mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 1612281Stoy else 1622281Stoy wakeup((caddr_t)&tp->t_outq); 1632281Stoy } 1642281Stoy } 1652281Stoy 1662281Stoy ptcwrite(dev) 1672281Stoy dev_t dev; 1682281Stoy { /* Stuff characters into PTY's input buffer */ 1692281Stoy register struct tty *tp; 1702281Stoy register char *cp, *ce; 1712281Stoy register int cc; 1722281Stoy char locbuf[BUFSIZ]; 1732281Stoy 1742281Stoy tp = &pt_tty[minor(dev)]; 1752281Stoy if((tp->t_state&(CARR_ON|ISOPEN)) == 0) 1762281Stoy return; 1772281Stoy while(u.u_count) { 1782281Stoy cc = MIN(u.u_count, BUFSIZ); 1792281Stoy cp = locbuf; 1802281Stoy iomove(cp, (unsigned)cc, B_WRITE); 1812281Stoy if(u.u_error) 1822281Stoy break; 1832281Stoy ce = cp + cc; 1842281Stoy while(cp < ce) { 1852281Stoy while(tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) { 1862281Stoy wakeup((caddr_t)&tp->t_rawq); 1872281Stoy /* Better than just flushing it! */ 1882281Stoy /* Wait for something to be read */ 1892281Stoy sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 1902281Stoy } 1912281Stoy ttyinput(*cp++, tp); 1922281Stoy } 1932281Stoy } 1942281Stoy } 1952281Stoy 1962281Stoy /* Note: Both slave and controlling device have the same routine for */ 1972281Stoy /* 'ioctl' (but note check for controller - 4/12/78:mob)*/ 1982281Stoy /*ARGSUSED*/ 1992281Stoy ptyioctl(dev, cmd, addr, flag) 2002281Stoy caddr_t addr; 2012281Stoy dev_t dev; 2022281Stoy { /* Read and write status bits */ 2032281Stoy register struct tty *tp; 2042281Stoy register int tbd; 2052281Stoy #ifdef BLAND 2062281Stoy register int nld; 2072281Stoy #endif 2082281Stoy 2092281Stoy tp = &pt_tty[minor(dev)]; 2102281Stoy /* if controller stty then must flush to prevent a hang */ 2112281Stoy if(cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP) 2122281Stoy while(getc(&tp->t_outq) >= 0); 2132281Stoy if(ttioctl(tp, cmd, addr, dev)) { 2142281Stoy if(cmd == TIOCSETP || cmd == TIOCSETN) { 2152281Stoy #ifdef BLAND 2162281Stoy nld = tp->t_flags & NLDELAY; 2172281Stoy #endif 2182281Stoy tbd = tp->t_flags & TBDELAY; 2192281Stoy tp->t_flags &= ~ALLDELAYS; 2202281Stoy if(tbd == TBDELAY) /* Wants tab expansion */ 2212281Stoy tp->t_flags |= tbd; 2222281Stoy #ifdef BLAND 2232281Stoy if(nld == NLDELAY) /* Allow ANN ARBOR mode. */ 2242281Stoy tp->t_flags |= nld; 2252281Stoy #endif 2262281Stoy } 2272281Stoy } else 2282281Stoy u.u_error = ENOTTY; 2292281Stoy } 230*2313Stoy #endif 231