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