|
|
1.1 ! root 1: /* pty.c 4.8 81/08/14 */ ! 2: ! 3: /* ! 4: * Pseudo-teletype Driver ! 5: * (Actually two drivers, requiring two entries in 'cdevsw') ! 6: */ ! 7: #include "pty.h" ! 8: ! 9: #if NPTY > 0 ! 10: ! 11: #include "../h/param.h" ! 12: #include "../h/systm.h" ! 13: #include "../h/tty.h" ! 14: #include "../h/dir.h" ! 15: #include "../h/user.h" ! 16: #include "../h/conf.h" ! 17: #include "../h/buf.h" ! 18: #include "../h/file.h" ! 19: ! 20: #define NPTY 16 /* Number of pseudo-teletypes */ ! 21: #define BUFSIZ 100 /* Chunk size iomoved from user */ ! 22: #define ALLDELAYS (NLDELAY|TBDELAY|XTABS|CRDELAY|VTDELAY) ! 23: /* ! 24: * A pseudo-teletype is a special device which is not unlike a pipe. ! 25: * It is used to communicate between two processes. However, it allows ! 26: * one to simulate a teletype, including mode setting, interrupt, and ! 27: * multiple end of files (all not possible on a pipe). There are ! 28: * really two drivers here. One is the device which looks like a TTY ! 29: * and can be thought of as the slave device, and hence its routines ! 30: * are prefixed with 'pts' (PTY Slave). The other driver can be ! 31: * thought of as the controlling device, and its routines are prefixed ! 32: * by 'ptc' (PTY Controller). To type on the simulated keyboard of the ! 33: * PTY, one does a 'write' to the controlling device. To get the ! 34: * simulated printout from the PTY, one does a 'read' on the controlling ! 35: * device. Normally, the controlling device is called 'ptyx' and the ! 36: * slave device is called 'ttyx' (to make programs like 'who' happy). ! 37: */ ! 38: ! 39: struct tty pt_tty[NPTY]; /* TTY headers for PTYs */ ! 40: ! 41: /*ARGSUSED*/ ! 42: ptsopen(dev, flag) ! 43: dev_t dev; ! 44: { /* Open for PTY Slave */ ! 45: register struct tty *tp; ! 46: ! 47: if(minor(dev) >= NPTY) { ! 48: u.u_error = ENXIO; ! 49: return; ! 50: } ! 51: tp = &pt_tty[minor(dev)]; ! 52: if((tp->t_state & ISOPEN) == 0) { ! 53: ttychars(tp); /* Set up default chars */ ! 54: tp->t_flags = 0; /* No features (nor raw mode) */ ! 55: } else if(tp->t_state&XCLUDE && u.u_uid != 0) { ! 56: u.u_error = EBUSY; ! 57: return; ! 58: } ! 59: if(tp->t_oproc) /* Ctrlr still around. */ ! 60: tp->t_state |= CARR_ON; ! 61: while((tp->t_state & CARR_ON) == 0) { ! 62: tp->t_state |= WOPEN; ! 63: sleep((caddr_t)&tp->t_rawq, TTIPRI); ! 64: } ! 65: (*linesw[tp->t_line].l_open)(dev, tp); ! 66: } ! 67: ! 68: ptsclose(dev) ! 69: dev_t dev; ! 70: { /* Close slave part of PTY */ ! 71: register struct tty *tp; ! 72: ! 73: tp = &pt_tty[minor(dev)]; ! 74: (*linesw[tp->t_line].l_close)(tp); ! 75: } ! 76: ! 77: ptsread(dev) ! 78: dev_t dev; ! 79: { /* Read from PTY, i.e. from data written by controlling device */ ! 80: register struct tty *tp; ! 81: ! 82: tp = &pt_tty[minor(dev)]; ! 83: if(tp->t_oproc) { ! 84: (*linesw[tp->t_line].l_read)(tp); ! 85: /* Wakeup other half if sleeping */ ! 86: wakeup((caddr_t)&tp->t_rawq.c_cf); ! 87: } ! 88: } ! 89: ! 90: ptswrite(dev) ! 91: dev_t dev; ! 92: { /* Write on PTY, i.e. to be read from ! 93: controlling device */ ! 94: register struct tty *tp; ! 95: ! 96: tp = &pt_tty[minor(dev)]; ! 97: /* Wait for controlling device to be opened */ ! 98: if(tp->t_oproc) ! 99: (*linesw[tp->t_line].l_write)(tp); ! 100: } ! 101: ! 102: ptsstart(tp) ! 103: struct tty *tp; ! 104: { /* Called by 'ttstart' to output a character. ! 105: Merely wakes up controlling half, which ! 106: does actual work */ ! 107: if(tp->t_state & TTSTOP) ! 108: return; ! 109: wakeup((caddr_t)&tp->t_outq.c_cf); ! 110: } ! 111: ! 112: /*ARGSUSED*/ ! 113: ptcopen(dev, flag) ! 114: dev_t dev; ! 115: { /* Open for PTY Controller */ ! 116: register struct tty *tp; ! 117: ! 118: if(minor(dev) >= NPTY) { ! 119: u.u_error = ENXIO; ! 120: return; ! 121: } ! 122: tp = &pt_tty[minor(dev)]; ! 123: if(tp->t_oproc) { ! 124: u.u_error = EIO; ! 125: return; ! 126: } ! 127: tp->t_oproc = ptsstart; /* Set address of start routine */ ! 128: tp->t_iproc = 0; ! 129: if(tp->t_state & WOPEN) ! 130: wakeup((caddr_t)&tp->t_rawq); ! 131: tp->t_state |= CARR_ON; ! 132: } ! 133: ! 134: ptcclose(dev) ! 135: dev_t dev; ! 136: { /* Close controlling part of PTY */ ! 137: register struct tty *tp; ! 138: ! 139: tp = &pt_tty[minor(dev)]; ! 140: if(tp->t_state & ISOPEN) ! 141: gsignal(tp->t_pgrp, SIGHUP); ! 142: tp->t_state &= ~CARR_ON; /* Virtual carrier is gone */ ! 143: flushtty(tp, FREAD|FWRITE); /* Clean things up */ ! 144: tp->t_oproc = 0; /* Mark as closed */ ! 145: } ! 146: ! 147: ptcread(dev) ! 148: dev_t dev; ! 149: { /* Read from PTY's output buffer */ ! 150: register struct tty *tp; ! 151: ! 152: tp = &pt_tty[minor(dev)]; ! 153: if((tp->t_state&(CARR_ON|ISOPEN)) == 0) ! 154: return; ! 155: while(tp->t_outq.c_cc == 0 || /* Wait for something to arrive */ ! 156: (tp->t_state&TTSTOP)) /* (Woken by ptsstart) */ ! 157: sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); ! 158: while(tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0); ! 159: if(tp->t_outq.c_cc <= TTLOWAT(tp) && (tp->t_state&ASLEEP)) { ! 160: tp->t_state &= ~ASLEEP; ! 161: if(tp->t_chan) ! 162: mcstart(tp->t_chan, (caddr_t)&tp->t_outq); ! 163: else ! 164: wakeup((caddr_t)&tp->t_outq); ! 165: } ! 166: } ! 167: ! 168: ptcwrite(dev) ! 169: dev_t dev; ! 170: { /* Stuff characters into PTY's input buffer */ ! 171: register struct tty *tp; ! 172: register char *cp, *ce; ! 173: register int cc; ! 174: char locbuf[BUFSIZ]; ! 175: ! 176: tp = &pt_tty[minor(dev)]; ! 177: if((tp->t_state&(CARR_ON|ISOPEN)) == 0) ! 178: return; ! 179: while(u.u_count) { ! 180: cc = MIN(u.u_count, BUFSIZ); ! 181: cp = locbuf; ! 182: iomove(cp, (unsigned)cc, B_WRITE); ! 183: if(u.u_error) ! 184: break; ! 185: ce = cp + cc; ! 186: while(cp < ce) { ! 187: while(tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) { ! 188: wakeup((caddr_t)&tp->t_rawq); ! 189: /* Better than just flushing it! */ ! 190: /* Wait for something to be read */ ! 191: sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); ! 192: } ! 193: (*linesw[tp->t_line].l_rint)(*cp++, tp); ! 194: } ! 195: } ! 196: } ! 197: ! 198: /* Note: Both slave and controlling device have the same routine for */ ! 199: /* 'ioctl' (but note check for controller - 4/12/78:mob)*/ ! 200: /*ARGSUSED*/ ! 201: ptyioctl(dev, cmd, addr, flag) ! 202: caddr_t addr; ! 203: dev_t dev; ! 204: { /* Read and write status bits */ ! 205: register struct tty *tp; ! 206: register int tbd; ! 207: #ifdef BLAND ! 208: register int nld; ! 209: #endif ! 210: ! 211: tp = &pt_tty[minor(dev)]; ! 212: /* if controller stty then must flush to prevent a hang */ ! 213: if(cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP) ! 214: while(getc(&tp->t_outq) >= 0); ! 215: if(ttioctl(tp, cmd, addr, dev)) { ! 216: if(cmd == TIOCSETP || cmd == TIOCSETN) { ! 217: #ifdef BLAND ! 218: nld = tp->t_flags & NLDELAY; ! 219: #endif ! 220: tbd = tp->t_flags & TBDELAY; ! 221: tp->t_flags &= ~ALLDELAYS; ! 222: if(tbd == TBDELAY) /* Wants tab expansion */ ! 223: tp->t_flags |= tbd; ! 224: #ifdef BLAND ! 225: if(nld == NLDELAY) /* Allow ANN ARBOR mode. */ ! 226: tp->t_flags |= nld; ! 227: #endif ! 228: } ! 229: } else ! 230: u.u_error = ENOTTY; ! 231: } ! 232: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.