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