Annotation of 41BSD/4.0.upgrade/sys/dev/pty.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.