use modem entry in linesw to signal carrier change; split line-disc close
[unix-history] / usr / src / sys / kern / tty.c
index 458c46d..08baeb4 100644 (file)
@@ -1,21 +1,27 @@
-/*     tty.c   6.2     83/09/09        */
+/*
+ * Copyright (c) 1982 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ *     @(#)tty.c       6.22 (Berkeley) %G%
+ */
 
 #include "../machine/reg.h"
 
 
 #include "../machine/reg.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/file.h"
-#include "../h/conf.h"
-#include "../h/buf.h"
-#include "../h/dk.h"
-#include "../h/uio.h"
-#include "../h/kernel.h"
+#include "param.h"
+#include "systm.h"
+#include "dir.h"
+#include "user.h"
+#include "ioctl.h"
+#include "tty.h"
+#include "proc.h"
+#include "inode.h"
+#include "file.h"
+#include "conf.h"
+#include "buf.h"
+#include "dk.h"
+#include "uio.h"
+#include "kernel.h"
 
 /*
  * Table giving parity for characters and indicating
 
 /*
  * Table giving parity for characters and indicating
@@ -123,10 +129,10 @@ ttywflush(tp)
 ttywait(tp)
        register struct tty *tp;
 {
 ttywait(tp)
        register struct tty *tp;
 {
-       register int s = spl5();
+       register int s = spltty();
 
        while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
 
        while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
-           tp->t_state&TS_CARR_ON && tp->t_oproc) {    /* kludge for pty */
+           tp->t_state&TS_CARR_ON) {
                (*tp->t_oproc)(tp);
                tp->t_state |= TS_ASLEEP;
                sleep((caddr_t)&tp->t_outq, TTOPRI);
                (*tp->t_oproc)(tp);
                tp->t_state |= TS_ASLEEP;
                sleep((caddr_t)&tp->t_outq, TTOPRI);
@@ -142,7 +148,7 @@ ttyflush(tp, rw)
 {
        register s;
 
 {
        register s;
 
-       s = spl6();
+       s = spltty();
        if (rw & FREAD) {
                while (getc(&tp->t_canq) >= 0)
                        ;
        if (rw & FREAD) {
                while (getc(&tp->t_canq) >= 0)
                        ;
@@ -158,7 +164,6 @@ ttyflush(tp, rw)
        if (rw & FREAD) {
                while (getc(&tp->t_rawq) >= 0)
                        ;
        if (rw & FREAD) {
                while (getc(&tp->t_rawq) >= 0)
                        ;
-               tp->t_delct = 0;
                tp->t_rocount = 0;
                tp->t_rocol = 0;
                tp->t_state &= ~TS_LOCAL;
                tp->t_rocount = 0;
                tp->t_rocol = 0;
                tp->t_state &= ~TS_LOCAL;
@@ -179,9 +184,16 @@ ttyblock(tp)
                ttyflush(tp, FREAD|FWRITE);
                tp->t_state &= ~TS_TBLOCK;
        }
                ttyflush(tp, FREAD|FWRITE);
                tp->t_state &= ~TS_TBLOCK;
        }
-       if (x >= TTYHOG/2 && putc(tp->t_stopc, &tp->t_outq) == 0) {
-               tp->t_state |= TS_TBLOCK;
-               ttstart(tp);
+       /*
+        * Block further input iff:
+        * Current input > threshold AND input is available to user program
+        */
+       if (x >= TTYHOG/2 && 
+           ((tp->t_flags & (RAW|CBREAK)) || (tp->t_canq.c_cc > 0))) {
+               if (putc(tp->t_stopc, &tp->t_outq)==0) {
+                       tp->t_state |= TS_TBLOCK;
+                       ttstart(tp);
+               }
        }
 }
 
        }
 }
 
@@ -212,7 +224,7 @@ ttstart(tp)
 {
        register s;
 
 {
        register s;
 
-       s = spl5();
+       s = spltty();
        if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
            tp->t_oproc)                /* kludge for pty */
                (*tp->t_oproc)(tp);
        if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
            tp->t_oproc)                /* kludge for pty */
                (*tp->t_oproc)(tp);
@@ -234,8 +246,7 @@ ttioctl(tp, com, data, flag)
 
        /*
         * If the ioctl involves modification,
 
        /*
         * If the ioctl involves modification,
-        * insist on being able to write the device,
-        * and hang if in the background.
+        * hang if in the background.
         */
        switch (com) {
 
         */
        switch (com) {
 
@@ -250,11 +261,12 @@ ttioctl(tp, com, data, flag)
        case TIOCLBIC:
        case TIOCLSET:
        case TIOCSTI:
        case TIOCLBIC:
        case TIOCLSET:
        case TIOCSTI:
+       case TIOCSWINSZ:
                while (tp->t_line == NTTYDISC &&
                   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
                   (u.u_procp->p_flag&SVFORK) == 0 &&
                while (tp->t_line == NTTYDISC &&
                   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
                   (u.u_procp->p_flag&SVFORK) == 0 &&
-                  u.u_signal[SIGTTOU] != SIG_IGN &&
-                  u.u_signal[SIGTTOU] != SIG_HOLD) {
+                  !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) &&
+                  !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) {
                        gsignal(u.u_procp->p_pgrp, SIGTTOU);
                        sleep((caddr_t)&lbolt, TTOPRI);
                }
                        gsignal(u.u_procp->p_pgrp, SIGTTOU);
                        sleep((caddr_t)&lbolt, TTOPRI);
                }
@@ -276,22 +288,18 @@ ttioctl(tp, com, data, flag)
                register int t = *(int *)data;
                int error = 0;
 
                register int t = *(int *)data;
                int error = 0;
 
-               if (t >= nldisp)
+               if ((unsigned) t >= nldisp)
                        return (ENXIO);
                        return (ENXIO);
-               s = spl5();
-               if (tp->t_line)
-                       (*linesw[tp->t_line].l_close)(tp);
-               if (t)
-                       error = (*linesw[t].l_open)(dev, tp);
-               splx(s);
+               s = spltty();
+               (*linesw[tp->t_line].l_close)(tp);
+               error = (*linesw[t].l_open)(dev, tp);
                if (error) {
                if (error) {
-                       s = spl5();
-                       if (tp->t_line)
-                               (void) (*linesw[tp->t_line].l_open)(dev, tp);
+                       (void) (*linesw[tp->t_line].l_open)(dev, tp);
                        splx(s);
                        return (error);
                }
                tp->t_line = t;
                        splx(s);
                        return (error);
                }
                tp->t_line = t;
+               splx(s);
                break;
        }
 
                break;
        }
 
@@ -330,7 +338,7 @@ ttioctl(tp, com, data, flag)
                break;
 
        case TIOCSTOP:
                break;
 
        case TIOCSTOP:
-               s = spl5();
+               s = spltty();
                if ((tp->t_state&TS_TTSTOP) == 0) {
                        tp->t_state |= TS_TTSTOP;
                        (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
                if ((tp->t_state&TS_TTSTOP) == 0) {
                        tp->t_state |= TS_TTSTOP;
                        (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
@@ -339,7 +347,7 @@ ttioctl(tp, com, data, flag)
                break;
 
        case TIOCSTART:
                break;
 
        case TIOCSTART:
-               s = spl5();
+               s = spltty();
                if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) {
                        tp->t_state &= ~TS_TTSTOP;
                        tp->t_flags &= ~FLUSHO;
                if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) {
                        tp->t_state &= ~TS_TTSTOP;
                        tp->t_flags &= ~FLUSHO;
@@ -352,6 +360,8 @@ ttioctl(tp, com, data, flag)
         * Simulate typing of a character at the terminal.
         */
        case TIOCSTI:
         * Simulate typing of a character at the terminal.
         */
        case TIOCSTI:
+               if (u.u_uid && (flag & FREAD) == 0)
+                       return (EPERM);
                if (u.u_uid && u.u_ttyp != tp)
                        return (EACCES);
                (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
                if (u.u_uid && u.u_ttyp != tp)
                        return (EACCES);
                (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
@@ -366,7 +376,7 @@ ttioctl(tp, com, data, flag)
                tp->t_ispeed = sg->sg_ispeed;
                tp->t_ospeed = sg->sg_ospeed;
                newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff);
                tp->t_ispeed = sg->sg_ispeed;
                tp->t_ospeed = sg->sg_ospeed;
                newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff);
-               s = spl5();
+               s = spltty();
                if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) {
                        ttywait(tp);
                        ttyflush(tp, FREAD);
                if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) {
                        ttywait(tp);
                        ttyflush(tp, FREAD);
@@ -453,18 +463,45 @@ ttioctl(tp, com, data, flag)
                break;
 
        case TIOCLGET:
                break;
 
        case TIOCLGET:
-               *(int *)data = tp->t_flags >> 16;
+               *(int *)data = ((unsigned) tp->t_flags) >> 16;
                break;
 
                break;
 
-       /* should allow SPGRP and GPGRP only if tty open for reading */
-       case TIOCSPGRP:
-               tp->t_pgrp = *(int *)data;
+       /*
+        * Allow SPGRP only if tty is open for reading.
+        * Quick check: if we can find a process in the new pgrp,
+        * this user must own that process.
+        * SHOULD VERIFY THAT PGRP IS IN USE AND IS THIS USER'S.
+        */
+       case TIOCSPGRP: {
+               struct proc *p;
+               int pgrp = *(int *)data;
+
+               if (u.u_uid && (flag & FREAD) == 0)
+                       return (EPERM);
+               p = pfind(pgrp);
+               if (p && p->p_pgrp == pgrp &&
+                   p->p_uid != u.u_uid && u.u_uid && !inferior(p))
+                       return (EPERM);
+               tp->t_pgrp = pgrp;
                break;
                break;
+       }
 
        case TIOCGPGRP:
                *(int *)data = tp->t_pgrp;
                break;
 
 
        case TIOCGPGRP:
                *(int *)data = tp->t_pgrp;
                break;
 
+       case TIOCSWINSZ:
+               if (bcmp((caddr_t)&tp->t_winsize, data,
+                   sizeof (struct winsize))) {
+                       tp->t_winsize = *(struct winsize *)data;
+                       gsignal(tp->t_pgrp, SIGWINCH);
+               }
+               break;
+
+       case TIOCGWINSZ:
+               *(struct winsize *)data = tp->t_winsize;
+               break;
+
        default:
                return (-1);
        }
        default:
                return (-1);
        }
@@ -490,13 +527,13 @@ ttselect(dev, rw)
 {
        register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
        int nread;
 {
        register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
        int nread;
-       int s = spl5();
+       int s = spltty();
 
        switch (rw) {
 
        case FREAD:
                nread = ttnread(tp);
 
        switch (rw) {
 
        case FREAD:
                nread = ttnread(tp);
-               if (nread > 0)
+               if ((nread > 0) || ((tp->t_state & TS_CARR_ON) == 0))
                        goto win;
                if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
                        tp->t_state |= TS_RCOLL;
                        goto win;
                if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
                        tp->t_state |= TS_RCOLL;
@@ -521,6 +558,7 @@ win:
 }
 
 /*
 }
 
 /*
+ * Initial open of tty, or (re)entry to line discipline.
  * Establish a process group for distribution of
  * quits and interrupts from the tty.
  */
  * Establish a process group for distribution of
  * quits and interrupts from the tty.
  */
@@ -540,12 +578,26 @@ ttyopen(dev, tp)
                pp->p_pgrp = tp->t_pgrp;
        }
        tp->t_state &= ~TS_WOPEN;
                pp->p_pgrp = tp->t_pgrp;
        }
        tp->t_state &= ~TS_WOPEN;
-       tp->t_state |= TS_ISOPEN;
-       if (tp->t_line != NTTYDISC)
-               ttywflush(tp);
+       if ((tp->t_state & TS_ISOPEN) == 0) {
+               tp->t_state |= TS_ISOPEN;
+               bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize));
+               if (tp->t_line != NTTYDISC)
+                       ttywflush(tp);
+       }
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * "close" a line discipline
+ */
+ttylclose(tp)
+       register struct tty *tp;
+{
+
+       ttywflush(tp);
+       tp->t_line = 0;
+}
+
 /*
  * clean tp on last close
  */
 /*
  * clean tp on last close
  */
@@ -553,19 +605,57 @@ ttyclose(tp)
        register struct tty *tp;
 {
 
        register struct tty *tp;
 {
 
-       if (tp->t_line) {
-               ttywflush(tp);
-               tp->t_line = 0;
-               return;
-       }
+       ttyflush(tp, FREAD|FWRITE);
        tp->t_pgrp = 0;
        tp->t_pgrp = 0;
-       ttywflush(tp);
        tp->t_state = 0;
 }
 
        tp->t_state = 0;
 }
 
+/*
+ * Handle modem control transition on a tty.
+ * Flag indicates new state of carrier.
+ * Returns 0 if the line should be turned off, otherwise 1.
+ */
+ttymodem(tp, flag)
+       register struct tty *tp;
+{
+
+       if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_flags & MDMBUF)) {
+               /*
+                * MDMBUF: do flow control according to carrier flag
+                */
+               if (flag) {
+                       tp->t_state &= ~TS_TTSTOP;
+                       ttstart(tp);
+               } else if ((tp->t_state&TS_TTSTOP) == 0) {
+                       tp->t_state |= TS_TTSTOP;
+                       (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
+               }
+       } else if (flag == 0) {
+               /*
+                * Lost carrier.
+                */
+               tp->t_state &= ~TS_CARR_ON;
+               if (tp->t_state & TS_ISOPEN) {
+                       if ((tp->t_flags & NOHANG) == 0) {
+                               gsignal(tp->t_pgrp, SIGHUP);
+                               gsignal(tp->t_pgrp, SIGCONT);
+                               ttyflush(tp, FREAD|FWRITE);
+                               return (0);
+                       }
+               }
+       } else {
+               /*
+                * Carrier now on.
+                */
+               tp->t_state |= TS_CARR_ON;
+               wakeup((caddr_t)&tp->t_rawq);
+       }
+       return (1);
+}
+
 /*
  * reinput pending characters after state switch
 /*
  * reinput pending characters after state switch
- * call at spl5().
+ * call at spltty().
  */
 ttypend(tp)
        register struct tty *tp;
  */
 ttypend(tp)
        register struct tty *tp;
@@ -630,7 +720,7 @@ ttyinput(c, tp)
         * Ignore any high bit added during
         * previous ttyinput processing.
         */
         * Ignore any high bit added during
         * previous ttyinput processing.
         */
-       if ((tp->t_state&TS_TYPEN) == 0)
+       if ((tp->t_state&TS_TYPEN) == 0 && (t_flags&PASS8) == 0)
                c &= 0177;
        /*
         * Check for literal nexting very first
                c &= 0177;
        /*
         * Check for literal nexting very first
@@ -649,13 +739,13 @@ ttyinput(c, tp)
         */
        if (tp->t_line == NTTYDISC) {
                if (c == tp->t_lnextc) {
         */
        if (tp->t_line == NTTYDISC) {
                if (c == tp->t_lnextc) {
-                       if (tp->t_flags&ECHO)
+                       if (t_flags&ECHO)
                                ttyout("^\b", tp);
                        tp->t_state |= TS_LNCH;
                        goto endcase;
                }
                if (c == tp->t_flushc) {
                                ttyout("^\b", tp);
                        tp->t_state |= TS_LNCH;
                        goto endcase;
                }
                if (c == tp->t_flushc) {
-                       if (tp->t_flags&FLUSHO)
+                       if (t_flags&FLUSHO)
                                tp->t_flags &= ~FLUSHO;
                        else {
                                ttyflush(tp, FWRITE);
                                tp->t_flags &= ~FLUSHO;
                        else {
                                ttyflush(tp, FWRITE);
@@ -667,7 +757,7 @@ ttyinput(c, tp)
                        goto startoutput;
                }
                if (c == tp->t_suspc) {
                        goto startoutput;
                }
                if (c == tp->t_suspc) {
-                       if ((tp->t_flags&NOFLSH) == 0)
+                       if ((t_flags&NOFLSH) == 0)
                                ttyflush(tp, FREAD);
                        ttyecho(c, tp);
                        gsignal(tp->t_pgrp, SIGTSTP);
                                ttyflush(tp, FREAD);
                        ttyecho(c, tp);
                        gsignal(tp->t_pgrp, SIGTSTP);
@@ -695,13 +785,26 @@ ttyinput(c, tp)
         * Look for interrupt/quit chars.
         */
        if (c == tp->t_intrc || c == tp->t_quitc) {
         * Look for interrupt/quit chars.
         */
        if (c == tp->t_intrc || c == tp->t_quitc) {
-               if ((tp->t_flags&NOFLSH) == 0)
+               if ((t_flags&NOFLSH) == 0)
                        ttyflush(tp, FREAD|FWRITE);
                ttyecho(c, tp);
                gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
                goto endcase;
        }
 
                        ttyflush(tp, FREAD|FWRITE);
                ttyecho(c, tp);
                gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
                goto endcase;
        }
 
+       if (tp->t_flags & LCASE && c <= 0177) {
+               if (tp->t_state&TS_BKSL) {
+                       ttyrub(unputc(&tp->t_rawq), tp);
+                       if (maptab[c])
+                               c = maptab[c];
+                       c |= 0200;
+                       tp->t_state &= ~(TS_BKSL|TS_QUOT);
+               } else if (c >= 'A' && c <= 'Z')
+                       c += 'a' - 'A';
+               else if (c == '\\')
+                       tp->t_state |= TS_BKSL;
+       }
+
        /*
         * Cbreak mode, don't process line editing
         * characters; check high water mark for wakeup.
        /*
         * Cbreak mode, don't process line editing
         * characters; check high water mark for wakeup.
@@ -733,7 +836,7 @@ ttyinput(c, tp)
                goto endcase;
        }
        if (c == tp->t_kill) {
                goto endcase;
        }
        if (c == tp->t_kill) {
-               if (tp->t_flags&CRTKIL &&
+               if (t_flags&CRTKIL &&
                    tp->t_rawq.c_cc == tp->t_rocount) {
                        while (tp->t_rawq.c_cc)
                                ttyrub(unputc(&tp->t_rawq), tp);
                    tp->t_rawq.c_cc == tp->t_rocount) {
                        while (tp->t_rawq.c_cc)
                                ttyrub(unputc(&tp->t_rawq), tp);
@@ -808,7 +911,7 @@ ttyinput(c, tp)
                }
                i = tp->t_col;
                ttyecho(c, tp);
                }
                i = tp->t_col;
                ttyecho(c, tp);
-               if (c == tp->t_eofc && tp->t_flags&ECHO) {
+               if (c == tp->t_eofc && t_flags&ECHO) {
                        i = MIN(2, tp->t_col - i);
                        while (i > 0) {
                                (void) ttyoutput('\b', tp);
                        i = MIN(2, tp->t_col - i);
                        while (i > 0) {
                                (void) ttyoutput('\b', tp);
@@ -816,20 +919,17 @@ ttyinput(c, tp)
                        }
                }
        }
                        }
                }
        }
-
 endcase:
        /*
         * If DEC-style start/stop is enabled don't restart
         * output until seeing the start character.
         */
 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 &&
+       if (t_flags&DECCTQ && tp->t_state&TS_TTSTOP &&
            tp->t_startc != tp->t_stopc)
                return;
            tp->t_startc != tp->t_stopc)
                return;
-
 restartoutput:
        tp->t_state &= ~TS_TTSTOP;
        tp->t_flags &= ~FLUSHO;
 restartoutput:
        tp->t_state &= ~TS_TTSTOP;
        tp->t_flags &= ~FLUSHO;
-
 startoutput:
        ttstart(tp);
 }
 startoutput:
        ttstart(tp);
 }
@@ -874,7 +974,7 @@ ttyoutput(c, tp)
 
                c = 8 - (tp->t_col&7);
                if ((tp->t_flags&FLUSHO) == 0) {
 
                c = 8 - (tp->t_col&7);
                if ((tp->t_flags&FLUSHO) == 0) {
-                       s = spl5();             /* don't interrupt tabs */
+                       s = spltty();           /* don't interrupt tabs */
                        c -= b_to_q("        ", c, &tp->t_outq);
                        tk_nout += c;
                        splx(s);
                        c -= b_to_q("        ", c, &tp->t_outq);
                        tk_nout += c;
                        splx(s);
@@ -1005,30 +1105,29 @@ ttread(tp, uio)
        register c, t_flags;
        int s, first, error = 0;
 
        register c, t_flags;
        int s, first, error = 0;
 
-       if ((tp->t_state&TS_CARR_ON)==0)
-               return (EIO);
 loop:
        /*
         * Take any pending input first.
         */
 loop:
        /*
         * Take any pending input first.
         */
-       s = spl5();
+       s = spltty();
        if (tp->t_flags&PENDIN)
                ttypend(tp);
        splx(s);
 
        if (tp->t_flags&PENDIN)
                ttypend(tp);
        splx(s);
 
+       if ((tp->t_state&TS_CARR_ON)==0)
+               return (EIO);
+
        /*
         * Hang process if it's in the background.
         */
        /*
         * 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 ||
-/*
-                   (u.u_procp->p_flag&SDETACH) ||
-*/
+       if (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
+               if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
+                  (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
                    u.u_procp->p_flag&SVFORK)
                        return (EIO);
                gsignal(u.u_procp->p_pgrp, SIGTTIN);
                sleep((caddr_t)&lbolt, TTIPRI);
                    u.u_procp->p_flag&SVFORK)
                        return (EIO);
                gsignal(u.u_procp->p_pgrp, SIGTTIN);
                sleep((caddr_t)&lbolt, TTIPRI);
+               goto loop;
        }
        t_flags = tp->t_flags;
 
        }
        t_flags = tp->t_flags;
 
@@ -1038,12 +1137,12 @@ loop:
         * device interrupts when interrogating rawq.
         */
        if (t_flags&RAW) {
         * device interrupts when interrogating rawq.
         */
        if (t_flags&RAW) {
-               s = spl5();
+               s = spltty();
                if (tp->t_rawq.c_cc <= 0) {
                        if ((tp->t_state&TS_CARR_ON) == 0 ||
                            (tp->t_state&TS_NBIO)) {
                                splx(s);
                if (tp->t_rawq.c_cc <= 0) {
                        if ((tp->t_state&TS_CARR_ON) == 0 ||
                            (tp->t_state&TS_NBIO)) {
                                splx(s);
-                               return (0);
+                               return (EWOULDBLOCK);
                        }
                        sleep((caddr_t)&tp->t_rawq, TTIPRI);
                        splx(s);
                        }
                        sleep((caddr_t)&tp->t_rawq, TTIPRI);
                        splx(s);
@@ -1065,7 +1164,7 @@ loop:
         * No input, sleep on rawq awaiting hardware
         * receipt and notification.
         */
         * No input, sleep on rawq awaiting hardware
         * receipt and notification.
         */
-       s = spl5();
+       s = spltty();
        if (qp->c_cc <= 0) {
                if ((tp->t_state&TS_CARR_ON) == 0 ||
                    (tp->t_state&TS_NBIO)) {
        if (qp->c_cc <= 0) {
                if ((tp->t_state&TS_CARR_ON) == 0 ||
                    (tp->t_state&TS_NBIO)) {
@@ -1086,21 +1185,6 @@ loop:
        while ((c = getc(qp)) >= 0) {
                if (t_flags&CRMOD && c == '\r')
                        c = '\n';
        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;
-                       }
                /*
                 * Check for delayed suspend character.
                 */
                /*
                 * Check for delayed suspend character.
                 */
@@ -1120,7 +1204,7 @@ loop:
                /*
                 * Give user character.
                 */
                /*
                 * Give user character.
                 */
-               error = ureadc(c & 0177, uio);
+               error = ureadc(t_flags&PASS8 ? c : c & 0177, uio);
                if (error)
                        break;
                if (uio->uio_resid == 0)
                if (error)
                        break;
                if (uio->uio_resid == 0)
@@ -1133,7 +1217,6 @@ loop:
                        break;
                first = 0;
        }
                        break;
                first = 0;
        }
-       tp->t_state &= ~TS_BKSL;
 
 checktandem:
        /*
 
 checktandem:
        /*
@@ -1148,6 +1231,34 @@ checktandem:
        return (error);
 }
 
        return (error);
 }
 
+/*
+ * Check the output queue on tp for space for a kernel message
+ * (from uprintf/tprintf).  Allow some space over the normal
+ * hiwater mark so we don't lose messages due to normal flow
+ * control, but don't let the tty run amok.
+ */
+ttycheckoutq(tp, wait)
+       register struct tty *tp;
+       int wait;
+{
+       int hiwat, s;
+
+       hiwat = TTHIWAT(tp);
+       s = spltty();
+       if (tp->t_outq.c_cc > hiwat + 200)
+           while (tp->t_outq.c_cc > hiwat) {
+               ttstart(tp);
+               if (wait == 0) {
+                       splx(s);
+                       return (0);
+               }
+               tp->t_state |= TS_ASLEEP;
+               sleep((caddr_t)&tp->t_outq, TTOPRI);
+       }
+       splx(s);
+       return (1);
+}
+
 /*
  * Called from the device's write routine after it has
  * calculated the tty-structure given as argument.
 /*
  * Called from the device's write routine after it has
  * calculated the tty-structure given as argument.
@@ -1161,26 +1272,22 @@ ttwrite(tp, uio)
        int i, hiwat, cnt, error, s;
        char obuf[OBUFSIZ];
 
        int i, hiwat, cnt, error, s;
        char obuf[OBUFSIZ];
 
-       if ((tp->t_state&TS_CARR_ON) == 0)
-               return (EIO);
        hiwat = TTHIWAT(tp);
        cnt = uio->uio_resid;
        error = 0;
 loop:
        hiwat = TTHIWAT(tp);
        cnt = uio->uio_resid;
        error = 0;
 loop:
+       if ((tp->t_state&TS_CARR_ON) == 0)
+               return (EIO);
        /*
         * Hang the process if it's in the background.
         */
        /*
         * Hang the process if it's in the background.
         */
-       while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
+       if (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
            (tp->t_flags&TOSTOP) && (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_procp->p_flag&SDETACH)==0) {
-*/
-           ) {
+           !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) &&
+           !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) {
                gsignal(u.u_procp->p_pgrp, SIGTTOU);
                sleep((caddr_t)&lbolt, TTIPRI);
                gsignal(u.u_procp->p_pgrp, SIGTTOU);
                sleep((caddr_t)&lbolt, TTIPRI);
+               goto loop;
        }
 
        /*
        }
 
        /*
@@ -1198,7 +1305,7 @@ loop:
                if (cc == 0) {
                        uio->uio_iovcnt--;
                        uio->uio_iov++;
                if (cc == 0) {
                        uio->uio_iovcnt--;
                        uio->uio_iov++;
-                       if (uio->uio_iovcnt < 0)
+                       if (uio->uio_iovcnt <= 0)
                                panic("ttwrite");
                        continue;
                }
                                panic("ttwrite");
                        continue;
                }
@@ -1226,6 +1333,13 @@ loop:
                                        ttstart(tp);
                                        sleep((caddr_t)&lbolt, TTOPRI);
                                        tp->t_rocount = 0;
                                        ttstart(tp);
                                        sleep((caddr_t)&lbolt, TTOPRI);
                                        tp->t_rocount = 0;
+                                       if (cc != 0) {
+                                               uio->uio_iov->iov_base -= cc;
+                                               uio->uio_iov->iov_len += cc;
+                                               uio->uio_resid += cc;
+                                               uio->uio_offset -= cc;
+                                       }
+                                       goto loop;
                                }
                                --cc;
                                if (tp->t_outq.c_cc > hiwat)
                                }
                                --cc;
                                if (tp->t_outq.c_cc > hiwat)
@@ -1255,10 +1369,16 @@ loop:
                                if (ce == 0) {
                                        tp->t_rocount = 0;
                                        if (ttyoutput(*cp, tp) >= 0) {
                                if (ce == 0) {
                                        tp->t_rocount = 0;
                                        if (ttyoutput(*cp, tp) >= 0) {
-                                               /* no c-lists, wait a bit */
-                                               ttstart(tp);
-                                               sleep((caddr_t)&lbolt, TTOPRI);
-                                               continue;
+                                           /* no c-lists, wait a bit */
+                                           ttstart(tp);
+                                           sleep((caddr_t)&lbolt, TTOPRI);
+                                           if (cc != 0) {
+                                               uio->uio_iov->iov_base -= cc;
+                                               uio->uio_iov->iov_len += cc;
+                                               uio->uio_resid += cc;
+                                               uio->uio_offset -= cc;
+                                           }
+                                           goto loop;
                                        }
                                        cp++, cc--;
                                        if (tp->t_flags&FLUSHO ||
                                        }
                                        cp++, cc--;
                                        if (tp->t_flags&FLUSHO ||
@@ -1284,6 +1404,11 @@ loop:
                                /* out of c-lists, wait a bit */
                                ttstart(tp);
                                sleep((caddr_t)&lbolt, TTOPRI);
                                /* out of c-lists, wait a bit */
                                ttstart(tp);
                                sleep((caddr_t)&lbolt, TTOPRI);
+                               uio->uio_iov->iov_base -= cc;
+                               uio->uio_iov->iov_len += cc;
+                               uio->uio_resid += cc;
+                               uio->uio_offset -= cc;
+                               goto loop;
                        }
                        if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
                                goto ovhiwat;
                        }
                        if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
                                goto ovhiwat;
@@ -1293,7 +1418,7 @@ loop:
        return (error);
 
 ovhiwat:
        return (error);
 
 ovhiwat:
-       s = spl5();
+       s = spltty();
        if (cc != 0) {
                uio->uio_iov->iov_base -= cc;
                uio->uio_iov->iov_len += cc;
        if (cc != 0) {
                uio->uio_iov->iov_base -= cc;
                uio->uio_iov->iov_len += cc;
@@ -1310,6 +1435,7 @@ ovhiwat:
        }
        ttstart(tp);
        if (tp->t_state&TS_NBIO) {
        }
        ttstart(tp);
        if (tp->t_state&TS_NBIO) {
+               splx(s);
                if (uio->uio_resid == cnt)
                        return (EWOULDBLOCK);
                return (0);
                if (uio->uio_resid == cnt)
                        return (EWOULDBLOCK);
                return (0);
@@ -1369,7 +1495,7 @@ ttyrub(c, tp)
                                ttyretype(tp);
                                return;
                        }
                                ttyretype(tp);
                                return;
                        }
-                       s = spl5();
+                       s = spltty();
                        savecol = tp->t_col;
                        tp->t_state |= TS_CNTTB;
                        tp->t_flags |= FLUSHO;
                        savecol = tp->t_col;
                        tp->t_state |= TS_CNTTB;
                        tp->t_flags |= FLUSHO;
@@ -1433,7 +1559,7 @@ ttyretype(tp)
        if (tp->t_rprntc != 0377)
                ttyecho(tp->t_rprntc, tp);
        (void) ttyoutput('\n', tp);
        if (tp->t_rprntc != 0377)
                ttyecho(tp->t_rprntc, tp);
        (void) ttyoutput('\n', tp);
-       s = spl5();
+       s = spltty();
        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))
        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))
@@ -1475,8 +1601,6 @@ ttyecho(c, tp)
                                c += 'A' - 1;
                }
        }
                                c += 'A' - 1;
                }
        }
-       if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
-               c += 'a' - 'A';
        (void) ttyoutput(c&0177, tp);
 }
 
        (void) ttyoutput(c&0177, tp);
 }
 
@@ -1517,17 +1641,3 @@ ttwakeup(tp)
                gsignal(tp->t_pgrp, SIGIO); 
        wakeup((caddr_t)&tp->t_rawq);
 }
                gsignal(tp->t_pgrp, SIGIO); 
        wakeup((caddr_t)&tp->t_rawq);
 }
-
-#if !defined(vax)
-scanc(size, cp, table, mask)
-       register int size;
-       register char *cp, table[];
-       register int mask;
-{
-       register int i = 0;
-
-       while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size)
-               i++;
-       return (i);
-}
-#endif