minor fixes
[unix-history] / usr / src / sys / kern / tty_pty.c
index a84dc05..86e2cec 100644 (file)
@@ -1,13 +1,13 @@
-#
-/*     tty_pty.c       1.3     %G%     */
+/*     tty_pty.c       4.11    82/01/13        */
 
 /*
  * Pseudo-teletype Driver
  * (Actually two drivers, requiring two entries in 'cdevsw')
 
 /*
  * Pseudo-teletype Driver
  * (Actually two drivers, requiring two entries in 'cdevsw')
- *
- * Overhauled, and ported to VAX/VMUNIX (V7) Bruce Borden, July 80
- * Modified and integrated into 4bsd by Kipp Hickman and Michael Toy
  */
  */
+#include "pty.h"
+
+#if NPTY > 0
+
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/tty.h"
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/tty.h"
 #include "../h/user.h"
 #include "../h/conf.h"
 #include "../h/buf.h"
 #include "../h/user.h"
 #include "../h/conf.h"
 #include "../h/buf.h"
+#include "../h/file.h"
+#include "../h/proc.h"
+
+#undef NPTY
+#define NPTY 16
+
+#define BUFSIZ 100             /* Chunk size iomoved from user */
 
 
-#define NPTY 16                 /* Number of pseudo-teletypes */
-#define BUFSIZ 100              /* Chunk size iomoved from user */
-#define ALLDELAYS (NLDELAY|TBDELAY|XTABS|CRDELAY|VTDELAY)
 /*
 /*
- * A pseudo-teletype is a special device which is not unlike a pipe.
- * It is used to communicate between two processes.  However, it allows
- * one to simulate a teletype, including mode setting, interrupt, and
- * multiple end of files (all not possible on a pipe).  There are
- * really two drivers here.  One is the device which looks like a TTY
- * and can be thought of as the slave device, and hence its routines
- * are prefixed with 'pts' (PTY Slave).  The other driver can be
- * thought of as the controlling device, and its routines are prefixed
- * by 'ptc' (PTY Controller).  To type on the simulated keyboard of the
- * PTY, one does a 'write' to the controlling device.  To get the
- * simulated printout from the PTY, one does a 'read' on the controlling
- * device.  Normally, the controlling device is called 'ptyx' and the
- * slave device is called 'ttyx' (to make programs like 'who' happy).
+ * pts == /dev/tty[pP]?
+ * ptc == /dev/ptp[pP]?
  */
  */
+struct tty pt_tty[NPTY];
+struct pt_ioctl {
+       int     pti_flags;
+       struct  clist pti_ioctl, pti_ioans;
+       int     pti_gensym;
+       struct  proc *pti_selr;
+} pt_ioctl[NPTY];
 
 
-struct tty pt_tty[NPTY];                /* TTY headers for PTYs */
+#define        PTCRCOLL        0x01
 
 /*ARGSUSED*/
 ptsopen(dev, flag)
 
 /*ARGSUSED*/
 ptsopen(dev, flag)
-dev_t dev;
-{                                       /* Open for PTY Slave */
+       dev_t dev;
+{
        register struct tty *tp;
 
        register struct tty *tp;
 
-       if(minor(dev) >= NPTY) {
+       if (minor(dev) >= NPTY) {
                u.u_error = ENXIO;
                return;
        }
        tp = &pt_tty[minor(dev)];
                u.u_error = ENXIO;
                return;
        }
        tp = &pt_tty[minor(dev)];
-       if((tp->t_state & ISOPEN) == 0) {
-               ttychars(tp);           /* Set up default chars */
-               tp->t_flags = 0;        /* No features (nor raw mode) */
-       } else if(tp->t_state&XCLUDE && u.u_uid != 0) {
+       if ((tp->t_state & ISOPEN) == 0) {
+               ttychars(tp);           /* Set up default chars */
+               tp->t_flags = 0;        /* No features (nor raw mode) */
+       } else if (tp->t_state&XCLUDE && u.u_uid != 0) {
                u.u_error = EBUSY;
                return;
        }
                u.u_error = EBUSY;
                return;
        }
-       if(tp->t_oproc)                 /* Ctrlr still around. */
+       if (tp->t_oproc)                        /* Ctrlr still around. */
                tp->t_state |= CARR_ON;
                tp->t_state |= CARR_ON;
-       while((tp->t_state & CARR_ON) == 0) {
+       while ((tp->t_state & CARR_ON) == 0) {
                tp->t_state |= WOPEN;
                sleep((caddr_t)&tp->t_rawq, TTIPRI);
        }
                tp->t_state |= WOPEN;
                sleep((caddr_t)&tp->t_rawq, TTIPRI);
        }
@@ -65,8 +65,8 @@ dev_t dev;
 }
 
 ptsclose(dev)
 }
 
 ptsclose(dev)
-dev_t dev;
-{                                       /* Close slave part of PTY */
+       dev_t dev;
+{                                      /* Close slave part of PTY */
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
@@ -74,157 +74,157 @@ dev_t dev;
 }
 
 ptsread(dev)
 }
 
 ptsread(dev)
-dev_t dev;
-{       /* Read from PTY, i.e. from data written by controlling device */
-       register struct tty    *tp;
+       dev_t dev;
+{
+       register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
 
        tp = &pt_tty[minor(dev)];
-       if(tp->t_oproc) {
+       if (tp->t_oproc) {
                (*linesw[tp->t_line].l_read)(tp);
                (*linesw[tp->t_line].l_read)(tp);
-                               /* Wakeup other half if sleeping */
                wakeup((caddr_t)&tp->t_rawq.c_cf);
        }
 }
 
 ptswrite(dev)
                wakeup((caddr_t)&tp->t_rawq.c_cf);
        }
 }
 
 ptswrite(dev)
-dev_t dev;
-{                       /* Write on PTY, i.e. to be read from
-                          controlling device */
+       dev_t dev;
+{
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
-                       /* Wait for controlling device to be opened */
-       if(tp->t_oproc)
+       if (tp->t_oproc)
                (*linesw[tp->t_line].l_write)(tp);
 }
 
 ptsstart(tp)
                (*linesw[tp->t_line].l_write)(tp);
 }
 
 ptsstart(tp)
-struct tty *tp;
-{                       /* Called by 'ttstart' to output a character.
-                          Merely wakes up controlling half, which
-                          does actual work */
-       if(tp->t_state & TTSTOP)
+       struct tty *tp;
+{
+       struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
+
+       if (tp->t_state & TTSTOP)
                return;
                return;
+       if (pti->pti_selr) {
+               selwakeup(pti->pti_selr, pti->pti_flags & PTCRCOLL);
+               pti->pti_selr = 0;
+               pti->pti_flags &= ~PTCRCOLL;
+       }
        wakeup((caddr_t)&tp->t_outq.c_cf);
 }
 
 /*ARGSUSED*/
 ptcopen(dev, flag)
        wakeup((caddr_t)&tp->t_outq.c_cf);
 }
 
 /*ARGSUSED*/
 ptcopen(dev, flag)
-dev_t dev;
-{                               /* Open for PTY Controller */
+       dev_t dev;
+       int flag;
+{
        register struct tty *tp;
 
        register struct tty *tp;
 
-       if(minor(dev) >= NPTY) {
+       if (minor(dev) >= NPTY) {
                u.u_error = ENXIO;
                return;
        }
        tp = &pt_tty[minor(dev)];
                u.u_error = ENXIO;
                return;
        }
        tp = &pt_tty[minor(dev)];
-       if(tp->t_oproc) {
+       if (tp->t_oproc) {
                u.u_error = EIO;
                return;
        }
                u.u_error = EIO;
                return;
        }
-       tp->t_oproc = ptsstart;         /* Set address of start routine */
-       tp->t_iproc = 0;
-       if(tp->t_state & WOPEN)
+       tp->t_oproc = ptsstart;
+       if (tp->t_state & WOPEN)
                wakeup((caddr_t)&tp->t_rawq);
        tp->t_state |= CARR_ON;
 }
 
 ptcclose(dev)
                wakeup((caddr_t)&tp->t_rawq);
        tp->t_state |= CARR_ON;
 }
 
 ptcclose(dev)
-dev_t dev;
-{                                       /* Close controlling part of PTY */
+       dev_t dev;
+{
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
-       if(tp->t_state & ISOPEN)
+       if (tp->t_state & ISOPEN)
                gsignal(tp->t_pgrp, SIGHUP);
                gsignal(tp->t_pgrp, SIGHUP);
-       tp->t_state &= ~CARR_ON;        /* Virtual carrier is gone */
-       flushtty(tp);                   /* Clean things up */
-       tp->t_oproc = 0;                /* Mark as closed */
+       tp->t_state &= ~CARR_ON;        /* virtual carrier gone */
+       flushtty(tp, FREAD|FWRITE);
+       tp->t_oproc = 0;                /* mark closed */
 }
 
 ptcread(dev)
 dev_t dev;
 }
 
 ptcread(dev)
 dev_t dev;
-{                                       /* Read from PTY's output buffer */
+{
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
-       if((tp->t_state&(CARR_ON|ISOPEN)) == 0)
+       if ((tp->t_state&(CARR_ON|ISOPEN)) == 0)
                return;
                return;
-       while(tp->t_outq.c_cc == 0 ||   /* Wait for something to arrive */
-             (tp->t_state&TTSTOP))     /* (Woken by ptsstart) */
+       while (tp->t_outq.c_cc == 0 || (tp->t_state&TTSTOP))
                sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI);
                sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI);
-       while(tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0);
-       if(tp->t_outq.c_cc <= TTLOWAT(tp)  && (tp->t_state&ASLEEP)) {
+       while (tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0);
+       if (tp->t_outq.c_cc <= TTLOWAT(tp)  && (tp->t_state&ASLEEP)) {
                tp->t_state &= ~ASLEEP;
                tp->t_state &= ~ASLEEP;
-               if(tp->t_chan)
-                       mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
-               else
-                       wakeup((caddr_t)&tp->t_outq);
+               wakeup((caddr_t)&tp->t_outq);
        }
 }
 
        }
 }
 
+ptcselect(dev)
+       dev_t dev;
+{
+       register struct tty *tp = &pt_tty[minor(dev)];
+       struct pt_ioctl *pti;
+       struct proc *p;
+
+       if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) {
+               return (1);
+}
+       if (tp->t_outq.c_cc) {
+               return (1);
+}
+       pti = &pt_ioctl[minor(dev)];
+       if ((p = pti->pti_selr) && p->p_wchan == (caddr_t)&selwait)
+               pti->pti_flags |= PTCRCOLL;
+       else
+               pti->pti_selr = u.u_procp;
+       return (0);
+}
+
 ptcwrite(dev)
 dev_t dev;
 ptcwrite(dev)
 dev_t dev;
-{                       /* Stuff characters into PTY's input buffer */
+{
        register struct tty *tp;
        register char *cp, *ce;
        register int cc;
        char locbuf[BUFSIZ];
 
        tp = &pt_tty[minor(dev)];
        register struct tty *tp;
        register char *cp, *ce;
        register int cc;
        char locbuf[BUFSIZ];
 
        tp = &pt_tty[minor(dev)];
-       if((tp->t_state&(CARR_ON|ISOPEN)) == 0)
+       if ((tp->t_state&(CARR_ON|ISOPEN)) == 0)
                return;
                return;
-       while(u.u_count) {
+       while (u.u_count) {
                cc = MIN(u.u_count, BUFSIZ);
                cp = locbuf;
                iomove(cp, (unsigned)cc, B_WRITE);
                cc = MIN(u.u_count, BUFSIZ);
                cp = locbuf;
                iomove(cp, (unsigned)cc, B_WRITE);
-               if(u.u_error)
+               if (u.u_error)
                        break;
                ce = cp + cc;
                        break;
                ce = cp + cc;
-               while(cp < ce) {
-                       while(tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) {
+               while (cp < ce) {
+                       while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) {
                                wakeup((caddr_t)&tp->t_rawq);
                                /* Better than just flushing it! */
                                /* Wait for something to be read */
                                sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI);
                        }
                                wakeup((caddr_t)&tp->t_rawq);
                                /* Better than just flushing it! */
                                /* Wait for something to be read */
                                sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI);
                        }
-                       ttyinput(*cp++, tp);
+                       (*linesw[tp->t_line].l_rint)(*cp++, tp);
                }
        }
 }
 
                }
        }
 }
 
-/* Note: Both slave and controlling device have the same routine for */
-/* 'ioctl' (but note check for controller - 4/12/78:mob)*/
 /*ARGSUSED*/
 ptyioctl(dev, cmd, addr, flag)
 /*ARGSUSED*/
 ptyioctl(dev, cmd, addr, flag)
-caddr_t addr;
-dev_t dev;
-{                                      /* Read and write status bits */
+       caddr_t addr;
+       dev_t dev;
+{
        register struct tty *tp;
        register struct tty *tp;
-       register int tbd;
-#ifdef BLAND
-       register int nld;
-#endif
 
        tp = &pt_tty[minor(dev)];
 
        tp = &pt_tty[minor(dev)];
-               /* if controller stty then must flush to prevent a hang */
-       if(cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP)
-               while(getc(&tp->t_outq) >= 0);
-       if(ttioctl(tp, cmd, addr, dev)) {
-               if(cmd == TIOCSETP || cmd == TIOCSETN) {
-#ifdef BLAND
-                       nld = tp->t_flags & NLDELAY;
-#endif
-                       tbd = tp->t_flags & TBDELAY;
-                       tp->t_flags &= ~ALLDELAYS;
-                       if(tbd == TBDELAY)      /* Wants tab expansion */
-                               tp->t_flags |= tbd;
-#ifdef BLAND
-                       if(nld == NLDELAY)      /* Allow ANN ARBOR mode. */
-                               tp->t_flags |= nld;
-#endif
-               }
-       } else
+       /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */
+       if (cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP)
+               while (getc(&tp->t_outq) >= 0);
+       if (ttioctl(tp, cmd, addr, dev) == 0)
                u.u_error = ENOTTY;
 }
                u.u_error = ENOTTY;
 }
+#endif