major reorganization; t_lstate & t_lflags purged
authorSam Leffler <sam@ucbvax.Berkeley.EDU>
Wed, 8 Dec 1982 08:44:28 +0000 (00:44 -0800)
committerSam Leffler <sam@ucbvax.Berkeley.EDU>
Wed, 8 Dec 1982 08:44:28 +0000 (00:44 -0800)
SCCS-vsn: sys/kern/tty.c 4.35

usr/src/sys/kern/tty.c

index 15cab4f..9c62c5e 100644 (file)
@@ -1,12 +1,10 @@
-/*     tty.c   4.35    82/12/05        */
+/*     tty.c   4.35    82/12/07        */
 
 
-/*
- * TTY subroutines common to more than one line discipline
- */
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/dir.h"
 #include "../h/user.h"
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/dir.h"
 #include "../h/user.h"
+#include "../h/ioctl.h"
 #include "../h/tty.h"
 #include "../h/proc.h"
 #include "../h/inode.h"
 #include "../h/tty.h"
 #include "../h/proc.h"
 #include "../h/inode.h"
@@ -74,7 +72,6 @@ char partab[] = {
  * sequence is replaced by the table value.  Mostly used for
  * upper-case only terminals.
  */
  * sequence is replaced by the table value.  Mostly used for
  * upper-case only terminals.
  */
-
 char   maptab[] ={
        000,000,000,000,000,000,000,000,
        000,000,000,000,000,000,000,000,
 char   maptab[] ={
        000,000,000,000,000,000,000,000,
        000,000,000,000,000,000,000,000,
@@ -99,33 +96,16 @@ short       tthiwat[16] =
 short  ttlowat[16] =
    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
 
 short  ttlowat[16] =
    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
 
-#define        OBUFSIZ 100
+struct ttychars ttydefaults = {
+       CERASE, CKILL,  CINTR,  CQUIT,  CSTART, CSTOP,  CEOF,
+       CBRK,   CSUSP,  CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT
+};
 
 
-/*
- * set default control characters.
- */
 ttychars(tp)
 ttychars(tp)
-       register struct tty *tp;
+       struct tty *tp;
 {
 
 {
 
-       tun.t_intrc = CINTR;
-       tun.t_quitc = CQUIT;
-       tun.t_startc = CSTART;
-       tun.t_stopc = CSTOP;
-       tun.t_eofc = CEOT;
-       tun.t_brkc = CBRK;
-       tp->t_erase = CERASE;
-       tp->t_kill = CKILL;
-/* begin local */
-       tlun.t_suspc = CTRL(z);
-       tlun.t_dsuspc = CTRL(y);
-       tlun.t_rprntc = CTRL(r);
-       tlun.t_flushc = CTRL(o);
-       tlun.t_werasc = CTRL(w);
-       tlun.t_lnextc = CTRL(v);
-       tp->t_local = 0;
-       tp->t_lstate = 0;
-/* end local */
+       tp->t_chars = ttydefaults;
 }
 
 /*
 }
 
 /*
@@ -147,7 +127,7 @@ wflushtty(tp)
 }
 
 /*
 }
 
 /*
- * flush all TTY queues
+ * Flush all TTY queues
  */
 flushtty(tp, rw)
        register struct tty *tp;
  */
 flushtty(tp, rw)
        register struct tty *tp;
@@ -171,9 +151,9 @@ flushtty(tp, rw)
                while (getc(&tp->t_rawq) >= 0)
                        ;
                tp->t_delct = 0;
                while (getc(&tp->t_rawq) >= 0)
                        ;
                tp->t_delct = 0;
-               tp->t_rocount = 0;              /* local */
+               tp->t_rocount = 0;
                tp->t_rocol = 0;
                tp->t_rocol = 0;
-               tp->t_lstate = 0;
+               tp->t_state &= ~TS_LOCAL;
        }
        splx(s);
 }
        }
        splx(s);
 }
@@ -185,17 +165,16 @@ ttyblock(tp)
        register struct tty *tp;
 {
        register x;
        register struct tty *tp;
 {
        register x;
+
        x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
        if (tp->t_rawq.c_cc > TTYHOG) {
                flushtty(tp, FREAD|FWRITE);
                tp->t_state &= ~TS_TBLOCK;
        }
        x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
        if (tp->t_rawq.c_cc > TTYHOG) {
                flushtty(tp, FREAD|FWRITE);
                tp->t_state &= ~TS_TBLOCK;
        }
-       if (x >= TTYHOG/2) {
-               if (putc(tun.t_stopc, &tp->t_outq)==0) {
-                       tp->t_state |= TS_TBLOCK;
-                       tp->t_char++;
-                       ttstart(tp);
-               }
+       if (x >= TTYHOG/2 && putc(tp->t_stopc, &tp->t_outq) == 0) {
+               tp->t_state |= TS_TBLOCK;
+               tp->t_char++;
+               ttstart(tp);
        }
 }
 
        }
 }
 
@@ -209,10 +188,8 @@ ttrstrt(tp)
        register struct tty *tp;
 {
 
        register struct tty *tp;
 {
 
-       if (tp == 0) {
-               printf("ttrstrt: arg was 0!\n");
-               return;
-       }
+       if (tp == 0)
+               panic("ttrstrt");
        tp->t_state &= ~TS_TIMEOUT;
        ttstart(tp);
 }
        tp->t_state &= ~TS_TIMEOUT;
        ttstart(tp);
 }
@@ -229,7 +206,7 @@ ttstart(tp)
        register s;
 
        s = spl5();
        register s;
 
        s = spl5();
-       if ((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
+       if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
            tp->t_oproc)                /* kludge for pty */
                (*tp->t_oproc)(tp);
        splx(s);
            tp->t_oproc)                /* kludge for pty */
                (*tp->t_oproc)(tp);
        splx(s);
@@ -276,6 +253,9 @@ ttioctl(tp, com, data, flag)
                break;
        }
 
                break;
        }
 
+       /*
+        * Process the ioctl.
+        */
        switch (com) {
 
        /* get discipline number */
        switch (com) {
 
        /* get discipline number */
@@ -286,10 +266,12 @@ ttioctl(tp, com, data, flag)
        /* set line discipline */
        case TIOCSETD: {
                register int t = *(int *)data;
        /* set line discipline */
        case TIOCSETD: {
                register int t = *(int *)data;
-               int error;
+               int error = 0;
 
 
-               if (t >= nldisp)
-                       return (ENXIO);
+               if (t >= nldisp) {
+                       u.u_error = ENXIO;
+                       break;
+               }
                s = spl5();
                if (tp->t_line)
                        (*linesw[tp->t_line].l_close)(tp);
                s = spl5();
                if (tp->t_line)
                        (*linesw[tp->t_line].l_close)(tp);
@@ -321,13 +303,13 @@ ttioctl(tp, com, data, flag)
                if (tp->t_flags&RAW || sg->sg_flags&RAW || com == TIOCSETP)
                        wflushtty(tp);
                else if ((tp->t_flags&CBREAK) != (sg->sg_flags&CBREAK)) {
                if (tp->t_flags&RAW || sg->sg_flags&RAW || com == TIOCSETP)
                        wflushtty(tp);
                else if ((tp->t_flags&CBREAK) != (sg->sg_flags&CBREAK)) {
-                       if (sg->sg_flags & CBREAK) {
+                       if (sg->sg_flags&CBREAK) {
                                catq(&tp->t_rawq, &tp->t_canq);
                                tq = tp->t_rawq;
                                tp->t_rawq = tp->t_canq;
                                tp->t_canq = tq;
                        } else {
                                catq(&tp->t_rawq, &tp->t_canq);
                                tq = tp->t_rawq;
                                tp->t_rawq = tp->t_canq;
                                tp->t_canq = tq;
                        } else {
-                               tp->t_local |= LPENDIN;
+                               tp->t_flags |= PENDIN;
                                ttwakeup(tp);
                        }
                }
                                ttwakeup(tp);
                        }
                }
@@ -335,8 +317,9 @@ ttioctl(tp, com, data, flag)
                tp->t_ospeed = sg->sg_ospeed;
                tp->t_erase = sg->sg_erase;
                tp->t_kill = sg->sg_kill;
                tp->t_ospeed = sg->sg_ospeed;
                tp->t_erase = sg->sg_erase;
                tp->t_kill = sg->sg_kill;
-               tp->t_flags = sg->sg_flags;
-               if (tp->t_flags & RAW) {
+               tp->t_flags &= ~0xffff;
+               tp->t_flags |= sg->sg_flags;
+               if (tp->t_flags&RAW) {
                        tp->t_state &= ~TS_TTSTOP;
                        ttstart(tp);
                }
                        tp->t_state &= ~TS_TTSTOP;
                        ttstart(tp);
                }
@@ -372,6 +355,17 @@ ttioctl(tp, com, data, flag)
                break;
        }
 
                break;
        }
 
+       /* set and fetch special characters */
+       /* THIS SHOULD USE struct ttychars */
+       case TIOCSETC:
+               bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars));
+               break;
+
+       case TIOCGETC:
+               bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars));
+               break;
+
+/* BEGIN DEFUNCT */
        case FIONBIO:
                if (*(int *)data)
                        tp->t_state |= TS_NBIO;
        case FIONBIO:
                if (*(int *)data)
                        tp->t_state |= TS_NBIO;
@@ -379,31 +373,36 @@ ttioctl(tp, com, data, flag)
                        tp->t_state &= ~TS_NBIO;
                break;
 
                        tp->t_state &= ~TS_NBIO;
                break;
 
-       case FIOASYNC:
-               if (*(int *)data)
-                       tp->t_state |= TS_ASYNC;
-               else
-                       tp->t_state &= ~TS_ASYNC;
+       /* set/get local special characters */
+       case TIOCSLTC:
+               bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars));
                break;
 
                break;
 
-       /* set and fetch special characters */
-       case TIOCSETC:
-               bcopy(data, (caddr_t)&tun, sizeof (struct tchars));
+       case TIOCGLTC:
+               bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars));
                break;
 
                break;
 
-       case TIOCGETC:
-               bcopy((caddr_t)&tun, data, sizeof (struct tchars));
+       /*
+        * Modify local mode word.
+        */
+       case TIOCLBIS:
+               tp->t_flags |= *(int *)data << 16;
                break;
 
                break;
 
-       /* set/get local special characters */
-       case TIOCSLTC:
-               bcopy(data, (caddr_t)&tlun, sizeof (struct ltchars));
+       case TIOCLBIC:
+               tp->t_flags &= ~(*(int *)data << 16);
                break;
 
                break;
 
-       case TIOCGLTC:
-               bcopy((caddr_t)&tlun, data, sizeof (struct ltchars));
+       case TIOCLSET:
+               tp->t_flags &= 0xffff;
+               tp->t_flags |= *(int *)data << 16;
                break;
 
                break;
 
+       case TIOCLGET:
+               *(int *)data = tp->t_flags >> 16;
+               break;
+/* END DEFUNCT */
+
        /* return number of characters immediately available */
        case FIONREAD:
                *(off_t *)data = ttnread(tp);
        /* return number of characters immediately available */
        case FIONREAD:
                *(off_t *)data = ttnread(tp);
@@ -418,26 +417,9 @@ ttioctl(tp, com, data, flag)
                *(int *)data = tp->t_pgrp;
                break;
 
                *(int *)data = tp->t_pgrp;
                break;
 
-       /* Modify local mode word */
-       case TIOCLBIS:
-               tp->t_local |= *(int *)data;
-               break;
-
-       case TIOCLBIC:
-               tp->t_local &= ~(*(int *)data);
-               break;
-
-       case TIOCLSET:
-               tp->t_local = *(int *)data;
-               break;
-
-       case TIOCLGET:
-               *(int *)data = tp->t_local;
-               break;
-
        case TIOCSTOP:
                s = spl5();
        case TIOCSTOP:
                s = spl5();
-               if ((tp->t_state & TS_TTSTOP) == 0) {
+               if ((tp->t_state&TS_TTSTOP) == 0) {
                        tp->t_state |= TS_TTSTOP;
                        (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
                }
                        tp->t_state |= TS_TTSTOP;
                        (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
                }
@@ -446,9 +428,9 @@ ttioctl(tp, com, data, flag)
 
        case TIOCSTART:
                s = spl5();
 
        case TIOCSTART:
                s = spl5();
-               if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) {
+               if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) {
                        tp->t_state &= ~TS_TTSTOP;
                        tp->t_state &= ~TS_TTSTOP;
-                       tp->t_local &= ~LFLUSHO;
+                       tp->t_flags &= ~FLUSHO;
                        ttstart(tp);
                }
                splx(s);
                        ttstart(tp);
                }
                splx(s);
@@ -460,8 +442,7 @@ ttioctl(tp, com, data, flag)
        case TIOCSTI:
                if (u.u_uid && u.u_ttyp != tp)
                        return (EACCES);
        case TIOCSTI:
                if (u.u_uid && u.u_ttyp != tp)
                        return (EACCES);
-               else
-                       (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
+               (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
                break;
 
        default:
                break;
 
        default:
@@ -475,7 +456,7 @@ ttnread(tp)
 {
        int nread = 0;
 
 {
        int nread = 0;
 
-       if (tp->t_local & LPENDIN)
+       if (tp->t_flags & PENDIN)
                ttypend(tp);
        nread = tp->t_canq.c_cc;
        if (tp->t_flags & (RAW|CBREAK))
                ttypend(tp);
        nread = tp->t_canq.c_cc;
        if (tp->t_flags & (RAW|CBREAK))
@@ -519,14 +500,9 @@ win:
        return (1);
 }
 
        return (1);
 }
 
-#define        OBUFSIZ 100
-
 /*
 /*
- * routine called on opens while tp->t_line == NTTYDISC
- * establishes a process group for distribution of
+ * Establish a process group for distribution of
  * quits and interrupts from the tty.
  * quits and interrupts from the tty.
- * (actually, pp->p_pgrp can't be 0 when this routine
- * is called since NTTYDISC is not the default discipline)
  */
 ttyopen(dev, tp)
        dev_t dev;
  */
 ttyopen(dev, tp)
        dev_t dev;
@@ -577,163 +553,141 @@ ttypend(tp)
        struct clist tq;
        register c;
 
        struct clist tq;
        register c;
 
-       tp->t_local &= ~LPENDIN;
-       tp->t_lstate |= LSTYPEN;
+       tp->t_flags &= ~PENDIN;
+       tp->t_state |= TS_TYPEN;
        tq = tp->t_rawq;
        tp->t_rawq.c_cc = 0;
        tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
        while ((c = getc(&tq)) >= 0)
                ttyinput(c, tp);
        tq = tp->t_rawq;
        tp->t_rawq.c_cc = 0;
        tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
        while ((c = getc(&tq)) >= 0)
                ttyinput(c, tp);
-       tp->t_lstate &= ~LSTYPEN;
+       tp->t_state &= ~TS_TYPEN;
 }
 
 /*
 }
 
 /*
- * Place a character on raw TTY input queue, putting in delimiters
- * and waking up top half as needed.
- * Also echo if required.
- * The arguments are the character and the appropriate
- * tty structure.
+ * Place a character on raw TTY input queue,
+ * putting in delimiters and waking up top
+ * half as needed.  Also echo if required.
+ * The arguments are the character and the
+ * appropriate tty structure.
  */
 ttyinput(c, tp)
        register c;
        register struct tty *tp;
 {
  */
 ttyinput(c, tp)
        register c;
        register struct tty *tp;
 {
-       register int t_flags;
+       register int t_flags = tp->t_flags;
        int i;
 
        int i;
 
-       if (tp->t_local&LPENDIN)
+       /*
+        * If input is pending take it first.
+        */
+       if (t_flags&PENDIN)
                ttypend(tp);
        tk_nin++;
        c &= 0377;
                ttypend(tp);
        tk_nin++;
        c &= 0377;
-       t_flags = tp->t_flags;
+
+       /*
+        * In tandem mode, check high water mark.
+        */
        if (t_flags&TANDEM)
                ttyblock(tp);
        if (t_flags&TANDEM)
                ttyblock(tp);
-       if ((t_flags&RAW)==0) {
-               if ((tp->t_lstate&LSTYPEN) == 0)
-                       c &= 0177;
-       /* check for literal nexting very first */
-               if (tp->t_lstate&LSLNCH) {
-                       c |= 0200;
-                       tp->t_lstate &= ~LSLNCH;
+
+       if (t_flags&RAW) {
+               /*
+                * Raw mode, just put character
+                * in input q w/o interpretation.
+                */
+               if (tp->t_rawq.c_cc > TTYHOG) 
+                       flushtty(tp, FREAD|FWRITE);
+               else {
+                       if (putc(c, &tp->t_rawq) >= 0)
+                               ttwakeup(tp);
+                       ttyecho(c, tp);
                }
                }
-               if (tp->t_line == NTTYDISC && c==tlun.t_lnextc) {
+               goto endcase;
+       }
+
+       /*
+        * Ignore any high bit added during
+        * previous ttyinput processing.
+        */
+       if ((tp->t_state&TS_TYPEN) == 0)
+               c &= 0177;
+       /*
+        * Check for literal nexting very first
+        */
+       if (tp->t_state&TS_LNCH) {
+               c |= 0200;
+               tp->t_state &= ~TS_LNCH;
+       }
+
+       /*
+        * Scan for special characters.  This code
+        * is really just a big case statement with
+        * non-constant cases.  The bottom of the
+        * case statement is labeled ``endcase'', so goto
+        * it after a case match, or similar.
+        */
+       if (tp->t_line == NTTYDISC) {
+               if (c == tp->t_lnextc) {
                        if (tp->t_flags&ECHO)
                                ttyout("^\b", tp);
                        if (tp->t_flags&ECHO)
                                ttyout("^\b", tp);
-                       tp->t_lstate |= LSLNCH;
-       /* check for output control functions */
-               } else if (c==tun.t_stopc) {
-                       if ((tp->t_state&TS_TTSTOP)==0) {
-                               tp->t_state |= TS_TTSTOP;
-                               (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
-                               return;
-                       }
-                       if (c!=tun.t_startc)
-                               return;
-               } else if (c==tun.t_startc) {
-                       tp->t_state &= ~TS_TTSTOP;
-                       tp->t_local &= ~LFLUSHO;
-                       ttstart(tp);
-                       return;
-               } else if (tp->t_line == NTTYDISC && c==tlun.t_flushc) {
-                       if (tp->t_local & LFLUSHO)
-                               tp->t_local &= ~LFLUSHO;
+                       tp->t_state |= TS_LNCH;
+                       goto endcase;
+               }
+               if (c == tp->t_flushc) {
+                       if (tp->t_flags&FLUSHO)
+                               tp->t_flags &= ~FLUSHO;
                        else {
                                flushtty(tp, FWRITE);
                                ttyecho(c, tp);
                        else {
                                flushtty(tp, FWRITE);
                                ttyecho(c, tp);
-                               if (tp->t_rawq.c_cc+tp->t_canq.c_cc)
+                               if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
                                        ttyretype(tp);
                                        ttyretype(tp);
-                               tp->t_local |= LFLUSHO;
+                               tp->t_flags |= FLUSHO;
                        }
                        }
-                       ttstart(tp);
-                       return;
-               } else if (c==tun.t_intrc || c==tun.t_quitc ||
-                   (tp->t_line == NTTYDISC && c==tlun.t_suspc)) {
-                       if ((tp->t_local & LNOFLSH) == 0)
-                               flushtty(tp,
-                                   c==tlun.t_suspc ? FREAD : FREAD|FWRITE);
+                       goto startoutput;
+               }
+               if (c == tp->t_suspc) {
+                       if ((tp->t_flags&NOFLSH) == 0)
+                               flushtty(tp, FREAD);
                        ttyecho(c, tp);
                        ttyecho(c, tp);
-                       c = c==tun.t_intrc ? SIGINT :
-                               ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP);
-                       ttsignal(tp, c);
-       /* check for buffer editing functions - cooked mode */
-               } else if ((t_flags&CBREAK) == 0) {
-                       if ((tp->t_lstate&LSQUOT) &&
-                           (c==tp->t_erase||c==tp->t_kill)) {
-                               ttyrub(unputc(&tp->t_rawq), tp);
-                               c |= 0200;
-                       }
-                       if (c==tp->t_erase) {
-                               if (tp->t_rawq.c_cc)
-                                       ttyrub(unputc(&tp->t_rawq), tp);
-                       } else if (c==tp->t_kill) {
-                               if (tp->t_local&LCRTKIL &&
-                                   tp->t_rawq.c_cc == tp->t_rocount) {
-                                       while (tp->t_rawq.c_cc)
-                                               ttyrub(unputc(&tp->t_rawq), tp);
-                               } else {
-                                       ttyecho(c, tp);
-                                       ttyecho('\n', tp);
-                                       while (getc(&tp->t_rawq) > 0)
-                                               ;
-                                       tp->t_rocount = 0;
-                               }
-                               tp->t_lstate = 0;
-                       } else if (tp->t_line == NTTYDISC && c==tlun.t_werasc) {
-                               if (tp->t_rawq.c_cc == 0)
-                                       goto out;
-                               do {
-                                       c = unputc(&tp->t_rawq);
-                                       if (c != ' ' && c != '\t')
-                                               goto erasenb;
-                                       ttyrub(c, tp);
-                               } while (tp->t_rawq.c_cc);
-                               goto out;
-                           erasenb:
-                               do {
-                                       ttyrub(c, tp);
-                                       if (tp->t_rawq.c_cc == 0)
-                                               goto out;
-                                       c = unputc(&tp->t_rawq);
-                               } while (c != ' ' && c != '\t');
-                               (void) putc(c, &tp->t_rawq);
-                       } else if (tp->t_line == NTTYDISC && c==tlun.t_rprntc) {
-                               ttyretype(tp);
-       /* check for cooked mode input buffer overflow */
-                       } else if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
-                               ;
-       /* put data char in q for user and wakeup if a break char */
-                       } else if (putc(c, &tp->t_rawq) >= 0) {
-                               if (tp->t_rawq.c_cc+tp->t_canq.c_cc==TTYHOG
-                                   && tp->t_line == NTTYDISC)
-                                       (void) ttyoutput(CTRL(g), tp);
-                               if (!ttbreakc(c, tp)) {
-                                       if (tp->t_rocount++ == 0)
-                                               tp->t_rocol = tp->t_col;
-                               } else {
-                                       tp->t_rocount = 0;
-                                       catq(&tp->t_rawq, &tp->t_canq);
-                                       /* IF (TP->T_CHAN) (VOID) SDATA(TP->T_CHAN); */
-                                       ttwakeup(tp);
-                               }
-                               tp->t_lstate &= ~LSQUOT;
-                               if (c == '\\')
-                                       tp->t_lstate |= LSQUOT;
-                               if (tp->t_lstate&LSERASE) {
-                                       tp->t_lstate &= ~LSERASE;
-                                       (void) ttyoutput('/', tp);
-                               }
-                               i = tp->t_col;
-                               ttyecho(c, tp);
-                               if (c==tun.t_eofc && tp->t_flags&ECHO) {
-                                       i = MIN(2, tp->t_col - i);
-                                       while (i > 0) {
-                                               (void) ttyoutput('\b', tp);
-                                               i--;
-                                       }
-                               }
-                       }
-       /* CBREAK mode */
-               } else if (tp->t_rawq.c_cc > TTYHOG) {
+                       gsignal(tp->t_pgrp, SIGTSTP);
+                       goto endcase;
+               }
+       }
+
+       /*
+        * Handle start/stop characters.
+        */
+       if (c == tp->t_stopc) {
+               if ((tp->t_state&TS_TTSTOP) == 0) {
+                       tp->t_state |= TS_TTSTOP;
+                       (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
+                       return;
+               }
+               if (c != tp->t_startc)
+                       return;
+               goto endcase;
+       }
+       if (c == tp->t_startc)
+               goto restartoutput;
+
+       /*
+        * Look for interrupt/quit chars.
+        */
+       if (c == tp->t_intrc || c == tp->t_quitc) {
+               if ((tp->t_flags&NOFLSH) == 0)
+                       flushtty(tp, FREAD|FWRITE);
+               ttyecho(c, tp);
+               gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
+               goto endcase;
+       }
+
+       /*
+        * Cbreak mode, don't process line editing
+        * characters; check high water mark for wakeup.
+        */
+       if (t_flags&CBREAK) {
+               if (tp->t_rawq.c_cc > TTYHOG) {
                        if (tp->t_outq.c_cc < TTHIWAT(tp) &&
                            tp->t_line == NTTYDISC)
                                (void) ttyoutput(CTRL(g), tp);
                        if (tp->t_outq.c_cc < TTHIWAT(tp) &&
                            tp->t_line == NTTYDISC)
                                (void) ttyoutput(CTRL(g), tp);
@@ -741,28 +695,130 @@ ttyinput(c, tp)
                        ttwakeup(tp);
                        ttyecho(c, tp);
                }
                        ttwakeup(tp);
                        ttyecho(c, tp);
                }
-       /* RAW mode */
-       } else if (tp->t_rawq.c_cc > TTYHOG) 
-               flushtty(tp, FREAD|FWRITE);
-       else {
-               if (putc(c, &tp->t_rawq) >= 0)
+               goto endcase;
+       }
+
+       /*
+        * From here on down cooked mode character
+        * processing takes place.
+        */
+       if ((tp->t_state&TS_QUOT) &&
+           (c == tp->t_erase || c == tp->t_kill)) {
+               ttyrub(unputc(&tp->t_rawq), tp);
+               c |= 0200;
+       }
+       if (c == tp->t_erase) {
+               if (tp->t_rawq.c_cc)
+                       ttyrub(unputc(&tp->t_rawq), tp);
+               goto endcase;
+       }
+       if (c == tp->t_kill) {
+               if (tp->t_flags&CRTKIL &&
+                   tp->t_rawq.c_cc == tp->t_rocount) {
+                       while (tp->t_rawq.c_cc)
+                               ttyrub(unputc(&tp->t_rawq), tp);
+               } else {
+                       ttyecho(c, tp);
+                       ttyecho('\n', tp);
+                       while (getc(&tp->t_rawq) > 0)
+                               ;
+                       tp->t_rocount = 0;
+               }
+               tp->t_state &= ~TS_LOCAL;
+               goto endcase;
+       }
+
+       /*
+        * New line discipline,
+        * check word erase/reprint line.
+        */
+       if (tp->t_line == NTTYDISC) {
+               if (c == tp->t_werasc) {
+                       if (tp->t_rawq.c_cc == 0)
+                               goto endcase;
+                       do {
+                               c = unputc(&tp->t_rawq);
+                               if (c != ' ' && c != '\t')
+                                       goto erasenb;
+                               ttyrub(c, tp);
+                       } while (tp->t_rawq.c_cc);
+                       goto endcase;
+       erasenb:
+                       do {
+                               ttyrub(c, tp);
+                               if (tp->t_rawq.c_cc == 0)
+                                       goto endcase;
+                               c = unputc(&tp->t_rawq);
+                       } while (c != ' ' && c != '\t');
+                       (void) putc(c, &tp->t_rawq);
+                       goto endcase;
+               }
+               if (c == tp->t_rprntc) {
+                       ttyretype(tp);
+                       goto endcase;
+               }
+       }
+
+       /*
+        * Check for input buffer overflow
+        */
+       if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG)
+               goto endcase;
+
+       /*
+        * Put data char in q for user and
+        * wakeup on seeing a line delimiter.
+        */
+       if (putc(c, &tp->t_rawq) >= 0) {
+               if (tp->t_rawq.c_cc + tp->t_canq.c_cc == TTYHOG
+                   && tp->t_line == NTTYDISC)
+                       (void) ttyoutput(CTRL(g), tp);
+               if (ttbreakc(c, tp)) {
+                       tp->t_rocount = 0;
+                       catq(&tp->t_rawq, &tp->t_canq);
                        ttwakeup(tp);
                        ttwakeup(tp);
+               } else if (tp->t_rocount++ == 0)
+                       tp->t_rocol = tp->t_col;
+               tp->t_state &= ~TS_QUOT;
+               if (c == '\\')
+                       tp->t_state |= TS_QUOT;
+               if (tp->t_state&TS_ERASE) {
+                       tp->t_state &= ~TS_ERASE;
+                       (void) ttyoutput('/', tp);
+               }
+               i = tp->t_col;
                ttyecho(c, tp);
                ttyecho(c, tp);
+               if (c == tp->t_eofc && tp->t_flags&ECHO) {
+                       i = MIN(2, tp->t_col - i);
+                       while (i > 0) {
+                               (void) ttyoutput('\b', tp);
+                               i--;
+                       }
+               }
        }
        }
-out:
-       if (tp->t_local & LDECCTQ && tp->t_state & TS_TTSTOP &&
-           tun.t_startc != tun.t_stopc)
+
+endcase:
+       /*
+        * If DEC-style start/stop is enabled don't restart
+        * output until seeing the start character.
+        */
+       if (tp->t_flags&DECCTQ && tp->t_state&TS_TTSTOP &&
+           tp->t_startc != tp->t_stopc)
                return;
                return;
+
+restartoutput:
        tp->t_state &= ~TS_TTSTOP;
        tp->t_state &= ~TS_TTSTOP;
-       tp->t_local &= ~LFLUSHO;
+       tp->t_flags &= ~FLUSHO;
+
+startoutput:
        ttstart(tp);
 }
 
 /*
        ttstart(tp);
 }
 
 /*
- * put character on TTY output queue, adding delays,
+ * Put character on TTY output queue, adding delays,
  * expanding tabs, and handling the CR/NL bit.
  * expanding tabs, and handling the CR/NL bit.
- * It is called both from the top half for output, and from
- * interrupt level for echoing.
+ * This is called both from the top half for output,
+ * and from interrupt level for echoing.
  * The arguments are the character and the tty structure.
  * Returns < 0 if putc succeeds, otherwise returns char to resend
  * Must be recursive.
  * The arguments are the character and the tty structure.
  * Returns < 0 if putc succeeds, otherwise returns char to resend
  * Must be recursive.
@@ -774,29 +830,30 @@ ttyoutput(c, tp)
        register char *colp;
        register ctype;
 
        register char *colp;
        register ctype;
 
-       if (tp->t_flags&RAW || tp->t_local&LLITOUT) {
-               if (tp->t_local&LFLUSHO)
+       if (tp->t_flags & (RAW|LITOUT)) {
+               if (tp->t_flags&FLUSHO)
                        return (-1);
                if (putc(c, &tp->t_outq))
                        return (c);
                tk_nout++;
                return (-1);
        }
                        return (-1);
                if (putc(c, &tp->t_outq))
                        return (c);
                tk_nout++;
                return (-1);
        }
+
        /*
        /*
-        * Ignore EOT in normal mode to avoid hanging up
-        * certain terminals.
+        * Ignore EOT in normal mode to avoid
+        * hanging up certain terminals.
         */
        c &= 0177;
         */
        c &= 0177;
-       if (c==CEOT && (tp->t_flags&CBREAK)==0)
+       if (c == CEOT && (tp->t_flags&CBREAK) == 0)
                return (-1);
        /*
         * Turn tabs to spaces as required
         */
                return (-1);
        /*
         * Turn tabs to spaces as required
         */
-       if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
+       if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
                register int s;
 
                c = 8 - (tp->t_col&7);
                register int s;
 
                c = 8 - (tp->t_col&7);
-               if ((tp->t_local&LFLUSHO) == 0) {
+               if ((tp->t_flags&FLUSHO) == 0) {
                        s = spl5();             /* don't interrupt tabs */
                        c -= b_to_q("        ", c, &tp->t_outq);
                        tk_nout += c;
                        s = spl5();             /* don't interrupt tabs */
                        c -= b_to_q("        ", c, &tp->t_outq);
                        tk_nout += c;
@@ -819,21 +876,22 @@ ttyoutput(c, tp)
                                c = colp[-2];
                                break;
                        }
                                c = colp[-2];
                                break;
                        }
-               if ('A'<=c && c<='Z') {
+               if ('A' <= c && c <= 'Z') {
                        if (ttyoutput('\\', tp) >= 0)
                                return (c);
                        if (ttyoutput('\\', tp) >= 0)
                                return (c);
-               } else if ('a'<=c && c<='z')
+               } else if ('a' <= c && c <= 'z')
                        c += 'A' - 'a';
        }
                        c += 'A' - 'a';
        }
+
        /*
         * turn <nl> to <cr><lf> if desired.
         */
        /*
         * turn <nl> to <cr><lf> if desired.
         */
-       if (c=='\n' && tp->t_flags&CRMOD)
+       if (c == '\n' && tp->t_flags&CRMOD)
                if (ttyoutput('\r', tp) >= 0)
                        return (c);
                if (ttyoutput('\r', tp) >= 0)
                        return (c);
-       if (c=='~' && tp->t_local&LTILDE)
+       if (c == '~' && tp->t_flags&TILDE)
                c = '`';
                c = '`';
-       if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq))
+       if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
                return (c);
        /*
         * Calculate delays.
                return (c);
        /*
         * Calculate delays.
@@ -842,6 +900,8 @@ ttyoutput(c, tp)
         * The delays are indicated by characters above 0200.
         * In raw mode there are no delays and the
         * transmission path is 8 bits wide.
         * The delays are indicated by characters above 0200.
         * In raw mode there are no delays and the
         * transmission path is 8 bits wide.
+        *
+        * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
         */
        colp = &tp->t_col;
        ctype = partab[c];
         */
        colp = &tp->t_col;
        ctype = partab[c];
@@ -864,10 +924,8 @@ ttyoutput(c, tp)
                if (ctype == 1) { /* tty 37 */
                        if (*colp)
                                c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
                if (ctype == 1) { /* tty 37 */
                        if (*colp)
                                c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
-               } else
-               if (ctype == 2) { /* vt05 */
+               } else if (ctype == 2) /* vt05 */
                        c = 6;
                        c = 6;
-               }
                *colp = 0;
                break;
 
                *colp = 0;
                break;
 
@@ -883,25 +941,26 @@ ttyoutput(c, tp)
                break;
 
        case VTAB:
                break;
 
        case VTAB:
-               if (tp->t_flags & VTDELAY) /* tty 37 */
+               if (tp->t_flags&VTDELAY) /* tty 37 */
                        c = 0177;
                break;
 
        case RETURN:
                ctype = (tp->t_flags >> 12) & 03;
                        c = 0177;
                break;
 
        case RETURN:
                ctype = (tp->t_flags >> 12) & 03;
-               if (ctype == 1) /* tn 300 */
+               if (ctype == 1) /* tn 300 */
                        c = 5;
                        c = 5;
-               } else if (ctype == 2) { /* ti 700 */
+               else if (ctype == 2) /* ti 700 */
                        c = 10;
                        c = 10;
-               else if (ctype == 3) { /* concept 100 */
+               else if (ctype == 3) { /* concept 100 */
                        int i;
                        int i;
+
                        if ((i = *colp) >= 0)
                        if ((i = *colp) >= 0)
-                               for (; i<9; i++)
+                               for (; i < 9; i++)
                                        (void) putc(0177, &tp->t_outq);
                }
                *colp = 0;
        }
                                        (void) putc(0177, &tp->t_outq);
                }
                *colp = 0;
        }
-       if (c && (tp->t_local&LFLUSHO) == 0)
+       if (c && (tp->t_flags&FLUSHO) == 0)
                (void) putc(c|0200, &tp->t_outq);
        return (-1);
 }
                (void) putc(c|0200, &tp->t_outq);
        return (-1);
 }
@@ -915,16 +974,23 @@ ttread(tp, uio)
        struct uio *uio;
 {
        register struct clist *qp;
        struct uio *uio;
 {
        register struct clist *qp;
-       register c, first;
-       int error = 0;
+       register c, t_flags;
+       int first, error = 0;
 
        if ((tp->t_state&TS_CARR_ON)==0)
                return (EIO);
 loop:
 
        if ((tp->t_state&TS_CARR_ON)==0)
                return (EIO);
 loop:
+       /*
+        * Take any pending input first.
+        */
        (void) spl5();
        (void) spl5();
-       if (tp->t_local&LPENDIN)
+       if (tp->t_flags&PENDIN)
                ttypend(tp);
        (void) spl0();
                ttypend(tp);
        (void) spl0();
+
+       /*
+        * Hang process if it's in the background.
+        */
        while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
                if (u.u_signal[SIGTTIN] == SIG_IGN ||
                    u.u_signal[SIGTTIN] == SIG_HOLD ||
        while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
                if (u.u_signal[SIGTTIN] == SIG_IGN ||
                    u.u_signal[SIGTTIN] == SIG_HOLD ||
@@ -936,13 +1002,20 @@ loop:
                gsignal(u.u_procp->p_pgrp, SIGTTIN);
                sleep((caddr_t)&lbolt, TTIPRI);
        }
                gsignal(u.u_procp->p_pgrp, SIGTTIN);
                sleep((caddr_t)&lbolt, TTIPRI);
        }
-       if (tp->t_flags&RAW) {
+       t_flags = tp->t_flags;
+
+       /*
+        * In raw mode take characters directly from the
+        * raw queue w/o processing.  Interlock against
+        * device interrupts when interrogating rawq.
+        */
+       if (t_flags&RAW) {
                (void) spl5();
                if (tp->t_rawq.c_cc <= 0) {
                (void) spl5();
                if (tp->t_rawq.c_cc <= 0) {
-                       if ((tp->t_state&TS_CARR_ON)==0 ||
+                       if ((tp->t_state&TS_CARR_ON) == 0 ||
                            (tp->t_state&TS_NBIO)) {
                                (void) spl0();
                            (tp->t_state&TS_NBIO)) {
                                (void) spl0();
-                               return (EWOULDBLOCK);
+                               return (0);
                        }
                        sleep((caddr_t)&tp->t_rawq, TTIPRI);
                        (void) spl0();
                        }
                        sleep((caddr_t)&tp->t_rawq, TTIPRI);
                        (void) spl0();
@@ -955,58 +1028,94 @@ loop:
                                break;
                }
                return (error);
                                break;
                }
                return (error);
-       } else {
-               qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq;
-               (void) spl5();
-               if (qp->c_cc <= 0) {
-                       if ((tp->t_state&TS_CARR_ON)==0 ||
-                           (tp->t_state&TS_NBIO)) {
-                               (void) spl0();
-                               return (EWOULDBLOCK);
-                       }
-                       sleep((caddr_t)&tp->t_rawq, TTIPRI);
+       }
+
+       /*
+        * In cbreak mode use the rawq, otherwise
+        * take characters from the canonicalized q.
+        */
+       qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq;
+
+       /*
+        * No input, sleep on rawq awaiting hardware
+        * receipt and notification.
+        */
+       (void) spl5();
+       if (qp->c_cc <= 0) {
+               if ((tp->t_state&TS_CARR_ON) == 0 ||
+                   (tp->t_state&TS_NBIO)) {
                        (void) spl0();
                        (void) spl0();
-                       goto loop;
+                       return (EWOULDBLOCK);
                }
                }
+               sleep((caddr_t)&tp->t_rawq, TTIPRI);
                (void) spl0();
                (void) spl0();
-               first = 1;
-               while ((c = getc(qp)) >= 0) {
-                       if (tp->t_flags&CRMOD && c == '\r')
-                               c = '\n';
-                       if (tp->t_flags&LCASE && c <= 0177)
-                               if (tp->t_lstate&LSBKSL) {
-                                       if (maptab[c])
-                                               c = maptab[c];
-                                       tp->t_lstate &= ~LSBKSL;
-                               } else if (c >= 'A' && c <= 'Z')
-                                       c += 'a' - 'A';
-                               else if (c == '\\') {
-                                       tp->t_lstate |= LSBKSL;
-                                       continue;
-                               }
-                       if (tp->t_line == NTTYDISC && c == tlun.t_dsuspc) {
-                               ttsignal(tp, SIGTSTP);
-                               if (first) {
-                                       sleep((caddr_t)&lbolt, TTIPRI);
-                                       goto loop;
-                               }
-                               break;
+               goto loop;
+       }
+       (void) spl0();
+
+       /*
+        * Input present, perform input mapping
+        * and processing (we're not in raw mode).
+        */
+       first = 1;
+       while ((c = getc(qp)) >= 0) {
+               if (t_flags&CRMOD && c == '\r')
+                       c = '\n';
+               /*
+                * Hack lower case simulation on
+                * upper case only terminals.
+                */
+               if (t_flags&LCASE && c <= 0177)
+                       if (tp->t_state&TS_BKSL) {
+                               if (maptab[c])
+                                       c = maptab[c];
+                               tp->t_state &= ~TS_BKSL;
+                       } else if (c >= 'A' && c <= 'Z')
+                               c += 'a' - 'A';
+                       else if (c == '\\') {
+                               tp->t_state |= TS_BKSL;
+                               continue;
                        }
                        }
-                       if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
-                               break;
-                       error = passuc(c & 0177, uio);
-                       if (error)
-                               break;
-                       if (uio->uio_iovcnt == 0)
-                               break;
-                       if ((tp->t_flags&CBREAK)==0 && ttbreakc(c, tp))
-                               break;
-                       first = 0;
+               /*
+                * Check for delayed suspend character.
+                */
+               if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
+                       gsignal(tp->t_pgrp, SIGTSTP);
+                       if (first) {
+                               sleep((caddr_t)&lbolt, TTIPRI);
+                               goto loop;
+                       }
+                       break;
                }
                }
-               tp->t_lstate &= ~LSBKSL;
+               /*
+                * Interpret EOF only in cooked mode.
+                */
+               if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
+                       break;
+               /*
+                * Give user character.
+                */
+               error = passuc(c & 0177, uio);
+               if (error)
+                       break;
+               if (uio->uio_iovcnt == 0)
+                       break;
+               /*
+                * In cooked mode check for a "break character"
+                * marking the end of a "line of input".
+                */
+               if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp))
+                       break;
+               first = 0;
        }
        }
+       tp->t_state &= ~TS_BKSL;
+
+       /*
+        * Look to unblock output now that (presumably)
+        * the input queue has gone down.
+        */
        if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
        if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
-               if (putc(tun.t_startc, &tp->t_outq)==0) {
+               if (putc(tp->t_startc, &tp->t_outq) == 0) {
                        tp->t_state &= ~TS_TBLOCK;
                        ttstart(tp);
                }
                        tp->t_state &= ~TS_TBLOCK;
                        ttstart(tp);
                }
@@ -1021,29 +1130,24 @@ loop:
  */
 ttwrite(tp, uio)
        register struct tty *tp;
  */
 ttwrite(tp, uio)
        register struct tty *tp;
-       struct uio *uio;
+       register struct uio *uio;
 {
 {
-#ifdef vax
-       /*
-        * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
-        * AND MUST NOT BE CHANGED WITHOUT PATCHING
-        * THE 'ASM' INLINES BELOW.  WATCH OUT.
-        */
-#endif
        register char *cp;
        register char *cp;
-       register int cc, ce;
-       register i;
+       register int cc, ce, c;
+       int i, hiwat, cnt, error, s;
        char obuf[OBUFSIZ];
        char obuf[OBUFSIZ];
-       register c;
-       int hiwat = TTHIWAT(tp);
-       int cnt = uio->uio_resid;
-       int error = 0;
 
 
-       if ((tp->t_state&TS_CARR_ON)==0)
+       if ((tp->t_state&TS_CARR_ON) == 0)
                return (EIO);
                return (EIO);
+       hiwat = TTHIWAT(tp);
+       cnt = uio->uio_resid;
+       error = 0;
 loop:
 loop:
+       /*
+        * Hang the process if it's in the background.
+        */
        while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
        while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
-           (tp->t_local&LTOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
+           (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
            u.u_signal[SIGTTOU] != SIG_IGN &&
            u.u_signal[SIGTTOU] != SIG_HOLD
 /*
            u.u_signal[SIGTTOU] != SIG_IGN &&
            u.u_signal[SIGTTOU] != SIG_HOLD
 /*
@@ -1054,7 +1158,18 @@ loop:
                gsignal(u.u_procp->p_pgrp, SIGTTOU);
                sleep((caddr_t)&lbolt, TTIPRI);
        }
                gsignal(u.u_procp->p_pgrp, SIGTTOU);
                sleep((caddr_t)&lbolt, TTIPRI);
        }
+
+       /*
+        * Process the user's data in at most OBUFSIZ
+        * chunks.  Perform lower case simulation and
+        * similar hacks.  Keep track of high water
+        * mark, sleep on overflow awaiting device aid
+        * in acquiring new space.
+        */
        while (uio->uio_resid > 0) {
        while (uio->uio_resid > 0) {
+               /*
+                * Grab a hunk of data from the user.
+                */
                cc = uio->uio_iov->iov_len;
                if (cc == 0) {
                        uio->uio_iovcnt--;
                cc = uio->uio_iov->iov_len;
                if (cc == 0) {
                        uio->uio_iovcnt--;
@@ -1066,15 +1181,20 @@ loop:
                if (cc > OBUFSIZ)
                        cc = OBUFSIZ;
                cp = obuf;
                if (cc > OBUFSIZ)
                        cc = OBUFSIZ;
                cp = obuf;
-               error = uiomove(cp, cc, UIO_WRITE, uio);
+               error = uiomove(cp, (unsigned)cc, UIO_WRITE, uio);
                if (error)
                        break;
                if (tp->t_outq.c_cc > hiwat)
                        goto ovhiwat;
                if (error)
                        break;
                if (tp->t_outq.c_cc > hiwat)
                        goto ovhiwat;
-               if (tp->t_local&LFLUSHO)
+               if (tp->t_flags&FLUSHO)
                        continue;
                        continue;
-               if (tp->t_flags&LCASE || tp->t_local&LTILDE) {
-                       while (cc) {
+               /*
+                * If we're mapping lower case or kludging tildes,
+                * then we've got to look at each character, so
+                * just feed the stuff to ttyoutput...
+                */
+               if (tp->t_flags & (LCASE|TILDE)) {
+                       while (cc > 0) {
                                c = *cp++;
                                tp->t_rocount = 0;
                                while ((c = ttyoutput(c, tp)) >= 0) {
                                c = *cp++;
                                tp->t_rocount = 0;
                                while ((c = ttyoutput(c, tp)) >= 0) {
@@ -1089,43 +1209,58 @@ loop:
                        }
                        continue;
                }
                        }
                        continue;
                }
-               while (cc) {
-                       if (tp->t_flags&RAW || tp->t_local&LLITOUT)
+               /*
+                * If nothing fancy need be done, grab those characters we
+                * can handle without any of ttyoutput's processing and
+                * just transfer them to the output q.  For those chars
+                * which require special processing (as indicated by the
+                * bits in partab), call ttyoutput.  After processing
+                * a hunk of data, look for FLUSHO so ^O's will take effect
+                * immediately.
+                */
+               while (cc > 0) {
+                       if (tp->t_flags & (RAW|LITOUT))
                                ce = cc;
                        else {
                                ce = cc;
                        else {
-#ifdef vax
-                               asm("   scanc   r9,(r10),_partab,$077");
-                               asm("   subl3   r0,r9,r8");
-#else
-                               ce=0;
-                               while (((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
-                                       ce++;
-#endif
-                               if (ce==0) {
+                               ce = cc - scanc(cc, cp, partab, 077);
+                               /*
+                                * If ce is zero, then we're processing
+                                * a special character through ttyoutput.
+                                */
+                               if (ce == 0) {
                                        tp->t_rocount = 0;
                                        if (ttyoutput(*cp, tp) >= 0) {
                                        tp->t_rocount = 0;
                                        if (ttyoutput(*cp, tp) >= 0) {
+                                               /* no c-lists, wait a bit */
                                                ttstart(tp);
                                                sleep((caddr_t)&lbolt, TTOPRI);
                                                continue;
                                        }
                                                ttstart(tp);
                                                sleep((caddr_t)&lbolt, TTOPRI);
                                                continue;
                                        }
-                                       cp++;
-                                       cc--;
-                                       if (tp->t_outq.c_cc > hiwat)
+                                       cp++, cc--;
+                                       if (tp->t_flags&FLUSHO ||
+                                           tp->t_outq.c_cc > hiwat)
                                                goto ovhiwat;
                                                goto ovhiwat;
+                                       continue;
                                }
                        }
                                }
                        }
+                       /*
+                        * A bunch of normal characters have been found,
+                        * transfer them en masse to the output queue and
+                        * continue processing at the top of the loop.
+                        * If there are any further characters in this
+                        * <= OBUFSIZ chunk, the first should be a character
+                        * requiring special handling by ttyoutput.
+                        */
                        tp->t_rocount = 0;
                        tp->t_rocount = 0;
-                       i=b_to_q(cp,ce,&tp->t_outq);
-                       ce-=i;
-                       tk_nout+=ce;
-                       tp->t_col+=ce;
-                       cp+=ce;
-                       cc-=ce;
-                       if (i) {
+                       i = b_to_q(cp, ce, &tp->t_outq);
+                       ce -= i;
+                       tp->t_col += ce;
+                       cp += ce, cc -= ce, tk_nout += ce;
+                       if (i > 0) {
+                               /* out of c-lists, wait a bit */
                                ttstart(tp);
                                sleep((caddr_t)&lbolt, TTOPRI);
                        }
                                ttstart(tp);
                                sleep((caddr_t)&lbolt, TTOPRI);
                        }
-                       if (ce || tp->t_outq.c_cc > hiwat)
+                       if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
                                goto ovhiwat;
                }
        }
                                goto ovhiwat;
                }
        }
@@ -1133,24 +1268,30 @@ loop:
        return (error);
 
 ovhiwat:
        return (error);
 
 ovhiwat:
-       (void) spl5();
-       uio->uio_iov->iov_base -= cc;
-       uio->uio_iov->iov_len += cc;
-       uio->uio_resid += cc;
-       uio->uio_offset -= cc;
+       s = spl5();
+       if (cc != 0) {
+               uio->uio_iov->iov_base -= cc;
+               uio->uio_iov->iov_len += cc;
+               uio->uio_resid += cc;
+               uio->uio_offset -= cc;
+       }
+       /*
+        * This can only occur if FLUSHO
+        * is also set in t_flags.
+        */
        if (tp->t_outq.c_cc <= hiwat) {
        if (tp->t_outq.c_cc <= hiwat) {
-               (void) spl0();
+               splx(s);
                goto loop;
        }
        ttstart(tp);
                goto loop;
        }
        ttstart(tp);
-       if (tp->t_state & TS_NBIO) {
+       if (tp->t_state&TS_NBIO) {
                if (uio->uio_resid == cnt)
                        return (EWOULDBLOCK);
                return (0);
        }
        tp->t_state |= TS_ASLEEP;
        sleep((caddr_t)&tp->t_outq, TTOPRI);
                if (uio->uio_resid == cnt)
                        return (EWOULDBLOCK);
                return (0);
        }
        tp->t_state |= TS_ASLEEP;
        sleep((caddr_t)&tp->t_outq, TTOPRI);
-       (void) spl0();
+       splx(s);
        goto loop;
 }
 
        goto loop;
 }
 
@@ -1167,11 +1308,11 @@ ttyrub(c, tp)
        int s;
        char *nextc();
 
        int s;
        char *nextc();
 
-       if ((tp->t_flags&ECHO)==0)
+       if ((tp->t_flags&ECHO) == 0)
                return;
                return;
-       tp->t_local &= ~LFLUSHO;
+       tp->t_flags &= ~FLUSHO;
        c &= 0377;
        c &= 0377;
-       if (tp->t_local&LCRTBS) {
+       if (tp->t_flags&CRTBS) {
                if (tp->t_rocount == 0) {
                        /*
                         * Screwed by ttwrite; retype
                if (tp->t_rocount == 0) {
                        /*
                         * Screwed by ttwrite; retype
@@ -1179,9 +1320,9 @@ ttyrub(c, tp)
                        ttyretype(tp);
                        return;
                }
                        ttyretype(tp);
                        return;
                }
-               if (c==('\t'|0200) || c==('\n'|0200))
+               if (c == ('\t'|0200) || c == ('\n'|0200))
                        ttyrubo(tp, 2);
                        ttyrubo(tp, 2);
-               else switch (partab[c&=0177] & 0177) {
+               else switch (partab[c&=0177]&0177) {
 
                case ORDINARY:
                        if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
 
                case ORDINARY:
                        if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
@@ -1194,7 +1335,7 @@ ttyrub(c, tp)
                case BACKSPACE:
                case CONTROL:
                case RETURN:
                case BACKSPACE:
                case CONTROL:
                case RETURN:
-                       if (tp->t_local & LCTLECH)
+                       if (tp->t_flags&CTLECH)
                                ttyrubo(tp, 2);
                        break;
 
                                ttyrubo(tp, 2);
                        break;
 
@@ -1205,13 +1346,14 @@ ttyrub(c, tp)
                        }
                        s = spl5();
                        savecol = tp->t_col;
                        }
                        s = spl5();
                        savecol = tp->t_col;
-                       tp->t_lstate |= LSCNTTB;
-                       tp->t_local |= LFLUSHO;
+                       tp->t_state |= TS_CNTTB;
+                       tp->t_flags |= FLUSHO;
                        tp->t_col = tp->t_rocol;
                        tp->t_col = tp->t_rocol;
-                       for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
+                       cp = tp->t_rawq.c_cf;
+                       for (; cp; cp = nextc(&tp->t_rawq, cp))
                                ttyecho(*cp, tp);
                                ttyecho(*cp, tp);
-                       tp->t_local &= ~LFLUSHO;
-                       tp->t_lstate &= ~LSCNTTB;
+                       tp->t_flags &= ~FLUSHO;
+                       tp->t_state &= ~TS_CNTTB;
                        splx(s);
                        /*
                         * savecol will now be length of the tab
                        splx(s);
                        /*
                         * savecol will now be length of the tab
@@ -1227,10 +1369,10 @@ ttyrub(c, tp)
                default:
                        panic("ttyrub");
                }
                default:
                        panic("ttyrub");
                }
-       } else if (tp->t_local&LPRTERA) {
-               if ((tp->t_lstate&LSERASE) == 0) {
+       } else if (tp->t_flags&PRTERA) {
+               if ((tp->t_state&TS_ERASE) == 0) {
                        (void) ttyoutput('\\', tp);
                        (void) ttyoutput('\\', tp);
-                       tp->t_lstate |= LSERASE;
+                       tp->t_state |= TS_ERASE;
                }
                ttyecho(c, tp);
        } else
                }
                ttyecho(c, tp);
        } else
@@ -1246,9 +1388,10 @@ ttyrubo(tp, cnt)
        register struct tty *tp;
        int cnt;
 {
        register struct tty *tp;
        int cnt;
 {
+       register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
 
        while (--cnt >= 0)
 
        while (--cnt >= 0)
-               ttyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
+               ttyout(rubostring, tp);
 }
 
 /*
 }
 
 /*
@@ -1262,15 +1405,15 @@ ttyretype(tp)
        char *nextc();
        int s;
 
        char *nextc();
        int s;
 
-       if (tlun.t_rprntc != 0377)
-               ttyecho(tlun.t_rprntc, tp);
+       if (tp->t_rprntc != 0377)
+               ttyecho(tp->t_rprntc, tp);
        (void) ttyoutput('\n', tp);
        s = spl5();
        for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
                ttyecho(*cp, tp);
        for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
                ttyecho(*cp, tp);
        (void) ttyoutput('\n', tp);
        s = spl5();
        for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
                ttyecho(*cp, tp);
        for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
                ttyecho(*cp, tp);
-       tp->t_lstate &= ~LSERASE;
+       tp->t_state &= ~TS_ERASE;
        splx(s);
        tp->t_rocount = tp->t_rawq.c_cc;
        tp->t_rocol = 0;
        splx(s);
        tp->t_rocount = tp->t_rawq.c_cc;
        tp->t_rocol = 0;
@@ -1284,8 +1427,8 @@ ttyecho(c, tp)
        register struct tty *tp;
 {
 
        register struct tty *tp;
 {
 
-       if ((tp->t_lstate & LSCNTTB) == 0)
-               tp->t_local &= ~LFLUSHO;
+       if ((tp->t_state&TS_CNTTB) == 0)
+               tp->t_flags &= ~FLUSHO;
        if ((tp->t_flags&ECHO) == 0)
                return;
        c &= 0377;
        if ((tp->t_flags&ECHO) == 0)
                return;
        c &= 0377;
@@ -1295,7 +1438,7 @@ ttyecho(c, tp)
        }
        if (c == '\r' && tp->t_flags&CRMOD)
                c = '\n';
        }
        if (c == '\r' && tp->t_flags&CRMOD)
                c = '\n';
-       if (tp->t_local&LCTLECH) {
+       if (tp->t_flags&CTLECH) {
                if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
                        (void) ttyoutput('^', tp);
                        c &= 0177;
                if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
                        (void) ttyoutput('^', tp);
                        c &= 0177;
@@ -1309,7 +1452,7 @@ ttyecho(c, tp)
        }
        if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
                c += 'a' - 'A';
        }
        if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
                c += 'a' - 'A';
-       (void) ttyoutput(c & 0177, tp);
+       (void) ttyoutput(c&0177, tp);
 }
 
 /*
 }
 
 /*
@@ -1319,7 +1462,7 @@ ttbreakc(c, tp)
        register c;
        register struct tty *tp;
 {
        register c;
        register struct tty *tp;
 {
-       return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
+       return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
                c == '\r' && (tp->t_flags&CRMOD));
 }
 
                c == '\r' && (tp->t_flags&CRMOD));
 }
 
@@ -1348,10 +1491,16 @@ ttwakeup(tp)
        wakeup((caddr_t)&tp->t_rawq);
 }
 
        wakeup((caddr_t)&tp->t_rawq);
 }
 
-ttsignal(tp, signo)
-       struct tty *tp;
-       int signo;
+#ifndef vax
+scanc(size, cp, table, mask)
+       register int size;
+       register char *cp, table[];
+       register int mask;
 {
 {
+       register int i = 0;
 
 
-       gsignal(tp->t_pgrp, signo);
+       while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size)
+               i++;
+       return (i);
 }
 }
+#endif