Annotation of 41BSD/4.0.upgrade/sys/dev/pty.c, revision 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.