patchable olducode varable
[unix-history] / usr / src / sys / kern / tty.c
index faf34aa..2b2318e 100644 (file)
@@ -1,4 +1,4 @@
-/*     tty.c   3.1     %H%     */
+/*     tty.c   3.9     %G%     */
 
 /*
  * general TTY subroutines
 
 /*
  * general TTY subroutines
 #include "../h/reg.h"
 #include "../h/conf.h"
 #include "../h/buf.h"
 #include "../h/reg.h"
 #include "../h/conf.h"
 #include "../h/buf.h"
+#include "../h/dk.h"
 
 char   partab[];
 
 
 char   partab[];
 
+/*
+ * When running dz's using only SAE (silo alarm) on input
+ * it is necessary to call dzrint() at clock interrupt time.
+ * This is unsafe unless spl5()s in tty code are changed to
+ * spl6()s to block clock interrupts.  Note that the dh driver
+ * currently in use works the same way as the dz, even though
+ * we could try to more intelligently manage its silo.
+ * Thus don't take this out if you have no dz's unless you
+ * change clock.c and dhtimer().
+ */
+#define        spl5    spl6
 
 /*
  * Input mapping table-- if an entry is non-zero, when the
 
 /*
  * Input mapping table-- if an entry is non-zero, when the
@@ -72,21 +84,22 @@ register struct tty *tp;
        if(pp->p_pgrp == 0) {
                u.u_ttyp = tp;
                u.u_ttyd = dev;
        if(pp->p_pgrp == 0) {
                u.u_ttyp = tp;
                u.u_ttyd = dev;
-               if (tp->t_pgrp==0)
+               if (tp->t_pgrp == 0)
                        tp->t_pgrp = pp->p_pid;
                pp->p_pgrp = tp->t_pgrp;
        }
        tp->t_state &= ~WOPEN;
        tp->t_state |= ISOPEN;
                        tp->t_pgrp = pp->p_pid;
                pp->p_pgrp = tp->t_pgrp;
        }
        tp->t_state &= ~WOPEN;
        tp->t_state |= ISOPEN;
+       tp->t_line = 0;         /* conservative */
 }
 
 }
 
-
 /*
  * set default control characters.
  */
 ttychars(tp)
 register struct tty *tp;
 {
 /*
  * set default control characters.
  */
 ttychars(tp)
 register struct tty *tp;
 {
+
        tun.t_intrc = CINTR;
        tun.t_quitc = CQUIT;
        tun.t_startc = CSTART;
        tun.t_intrc = CINTR;
        tun.t_quitc = CQUIT;
        tun.t_startc = CSTART;
@@ -95,6 +108,19 @@ register struct tty *tp;
        tun.t_brkc = CBRK;
        tp->t_erase = CERASE;
        tp->t_kill = CKILL;
        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);
+       tlun.t_lintr = CTRL(c);
+       tlun.t_lerase = CTRL(h);
+       tlun.t_lkill = CTRL(u);
+       tp->t_local = 0;
+       tp->t_lstate = 0;
+/* end local */
 }
 
 /*
 }
 
 /*
@@ -107,6 +133,7 @@ register struct tty *tp;
        tp->t_pgrp = 0;
        wflushtty(tp);
        tp->t_state = 0;
        tp->t_pgrp = 0;
        wflushtty(tp);
        tp->t_state = 0;
+       tp->t_line = 0;
 }
 
 /*
 }
 
 /*
@@ -126,6 +153,19 @@ gtty()
        ioctl();
 }
 
        ioctl();
 }
 
+/*
+ * Do nothing specific version of line
+ * discipline specific ioctl command.
+ */
+/*ARGSUSED*/
+nullioctl(tp, cmd, addr)
+register struct tty *tp;
+caddr_t addr;
+{
+
+       return (cmd);
+}
+
 /*
  * ioctl system call
  * Check legality, execute common code, and switch out to individual
 /*
  * ioctl system call
  * Check legality, execute common code, and switch out to individual
@@ -157,7 +197,15 @@ ioctl()
        ip = fp->f_inode;
        fmt = ip->i_mode & IFMT;
        if (fmt != IFCHR && fmt != IFMPC) {
        ip = fp->f_inode;
        fmt = ip->i_mode & IFMT;
        if (fmt != IFCHR && fmt != IFMPC) {
-               u.u_error = ENOTTY;
+/* begin local */
+               if (uap->cmd==FIONREAD && (fmt == IFREG || fmt == IFDIR)) {
+                       off_t nread = ip->i_size - fp->f_un.f_offset;
+
+                       if (copyout((caddr_t)&nread, uap->cmarg, sizeof(off_t)))
+                               u.u_error = EFAULT;
+               } else
+/* end local */
+                       u.u_error = ENOTTY;
                return;
        }
        dev = ip->i_un.i_rdev;
                return;
        }
        dev = ip->i_un.i_rdev;
@@ -173,7 +221,8 @@ register struct tty *tp;
 caddr_t addr;
 {
        unsigned t;
 caddr_t addr;
 {
        unsigned t;
-       struct ttiocb iocb;
+       struct sgttyb iocb;
+       struct clist tq;
        extern int nldisp;
 
        switch(com) {
        extern int nldisp;
 
        switch(com) {
@@ -199,12 +248,14 @@ caddr_t addr;
                        u.u_error = ENXIO;
                        break;
                }
                        u.u_error = ENXIO;
                        break;
                }
+               (void) spl5();
                if (tp->t_line)
                        (*linesw[tp->t_line].l_close)(tp);
                if (t)
                        (*linesw[t].l_open)(dev, tp, addr);
                if (u.u_error==0)
                        tp->t_line = t;
                if (tp->t_line)
                        (*linesw[tp->t_line].l_close)(tp);
                if (t)
                        (*linesw[t].l_open)(dev, tp, addr);
                if (u.u_error==0)
                        tp->t_line = t;
+               (void) spl0();
                break;
 
        /*
                break;
 
        /*
@@ -222,34 +273,57 @@ caddr_t addr;
         * Set new parameters
         */
        case TIOCSETP:
         * Set new parameters
         */
        case TIOCSETP:
-               wflushtty(tp);
        case TIOCSETN:
                if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
                        u.u_error = EFAULT;
                        return(1);
                }
        case TIOCSETN:
                if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
                        u.u_error = EFAULT;
                        return(1);
                }
-               VOID spl5();
-               while (canon(tp)>=0) 
-                       ;
+               (void) spl5();
+               if (tp->t_line == 0) {
+                       if (com == TIOCSETP)
+                               wflushtty(tp);
+                       while (canon(tp)>=0) 
+                               ;
+               } else if (tp->t_line == NTTYDISC) {
+                       if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
+                           com == TIOCSETP)
+                               wflushtty(tp);
+                       else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
+                               if (iocb.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 {
+                                       tp->t_local |= LPENDIN;
+                                       if (tp->t_canq.c_cc)
+                                               panic("ioccom canq");
+                                       if (tp->t_chan)
+                                               (void) sdata(tp->t_chan);
+                                       else
+                                               wakeup((caddr_t)&tp->t_rawq);
+                               }
+                       }
+               }
                if ((tp->t_state&SPEEDS)==0) {
                if ((tp->t_state&SPEEDS)==0) {
-                       tp->t_ispeed = iocb.ioc_ispeed;
-                       tp->t_ospeed = iocb.ioc_ospeed;
+                       tp->t_ispeed = iocb.sg_ispeed;
+                       tp->t_ospeed = iocb.sg_ospeed;
                }
                }
-               tp->t_erase = iocb.ioc_erase;
-               tp->t_kill = iocb.ioc_kill;
-               tp->t_flags = iocb.ioc_flags;
-               VOID spl0();
+               tp->t_erase = iocb.sg_erase;
+               tp->t_kill = iocb.sg_kill;
+               tp->t_flags = iocb.sg_flags;
+               (void) spl0();
                break;
 
        /*
         * send current parameters to user
         */
        case TIOCGETP:
                break;
 
        /*
         * send current parameters to user
         */
        case TIOCGETP:
-               iocb.ioc_ispeed = tp->t_ispeed;
-               iocb.ioc_ospeed = tp->t_ospeed;
-               iocb.ioc_erase = tp->t_erase;
-               iocb.ioc_kill = tp->t_kill;
-               iocb.ioc_flags = tp->t_flags;
+               iocb.sg_ispeed = tp->t_ispeed;
+               iocb.sg_ospeed = tp->t_ospeed;
+               iocb.sg_erase = tp->t_erase;
+               iocb.sg_kill = tp->t_kill;
+               iocb.sg_flags = tp->t_flags;
                if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
                        u.u_error = EFAULT;
                break;
                if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
                        u.u_error = EFAULT;
                break;
@@ -271,22 +345,96 @@ caddr_t addr;
         */
        case DIOCSETP:
        case DIOCGETP:
         */
        case DIOCSETP:
        case DIOCGETP:
-               (*linesw[tp->t_line].l_ioctl)(com, tp, addr);
+               if ((*linesw[tp->t_line].l_ioctl)(com, tp, addr))
+                       u.u_error = ENOTTY;
                break;
 
        /*
         * set and fetch special characters
         */
        case TIOCSETC:
                break;
 
        /*
         * set and fetch special characters
         */
        case TIOCSETC:
-               if (copyin(addr, (caddr_t)&tun, sizeof(struct tc)))
+               if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
                        u.u_error = EFAULT;
                break;
 
        case TIOCGETC:
                        u.u_error = EFAULT;
                break;
 
        case TIOCGETC:
-               if (copyout((caddr_t)&tun, addr, sizeof(struct tc)))
+               if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
+                       u.u_error = EFAULT;
+               break;
+
+/* local ioctls */
+       case TIOCSLTC:
+               if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
+                       u.u_error = EFAULT;
+               break;
+
+       case TIOCGLTC:
+               if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
+                       u.u_error = EFAULT;
+               break;
+
+       case FIONREAD: {
+               off_t nread;
+
+               switch (tp->t_line) {
+
+               case NETLDISC:
+                       nread = tp->t_rec ? tp->t_inbuf : 0;
+                       break;
+
+               case NTTYDISC:
+                       nread = tp->t_canq.c_cc;
+                       if (tp->t_flags & (RAW|CBREAK))
+                               nread += tp->t_rawq.c_cc;
+                       break;
+
+               case 0:
+                       /* do something here ... */
+                       ;
+               }
+               if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
+                       u.u_error = EFAULT;
+               break;
+               }
+
+       /*
+        * Should allow SPGRP and GPGRP only if tty open for reading.
+        */
+       case TIOCSPGRP:
+               tp->t_pgrp = (int)addr;
+               break;
+
+       case TIOCGPGRP:
+               if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
+                       u.u_error = EFAULT;
+               break;
+
+       /*
+        * Modify local mode word.
+        */
+       case TIOCLBIS:
+               tp->t_local |= (int)addr;
+               break;
+
+       case TIOCLBIC:
+               tp->t_local &= ~(int)addr;
+               break;
+
+       case TIOCLSET:
+               tp->t_local = (int)addr;
+               break;
+
+       case TIOCLGET:
+               if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
+                       u.u_error = EFAULT;
+               break;
+
+       case TIOCOUTQ:
+               if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc)))
                        u.u_error = EFAULT;
                break;
 
                        u.u_error = EFAULT;
                break;
 
+/* end of locals */
        default:
                return(0);
        }
        default:
                return(0);
        }
@@ -300,14 +448,14 @@ wflushtty(tp)
 register struct tty *tp;
 {
 
 register struct tty *tp;
 {
 
-       VOID spl5();
+       (void) spl5();
        while (tp->t_outq.c_cc && tp->t_state&CARR_ON) {
                (*tp->t_oproc)(tp);
                tp->t_state |= ASLEEP;
                sleep((caddr_t)&tp->t_outq, TTOPRI);
        }
        flushtty(tp);
        while (tp->t_outq.c_cc && tp->t_state&CARR_ON) {
                (*tp->t_oproc)(tp);
                tp->t_state |= ASLEEP;
                sleep((caddr_t)&tp->t_outq, TTOPRI);
        }
        flushtty(tp);
-       VOID spl0();
+       (void) spl0();
 }
 
 /*
 }
 
 /*
@@ -318,11 +466,13 @@ register struct tty *tp;
 {
        register s;
 
 {
        register s;
 
+       if (tp->t_line == NETLDISC)
+               return;
+       s = spl6();
        while (getc(&tp->t_canq) >= 0)
                ;
        wakeup((caddr_t)&tp->t_rawq);
        wakeup((caddr_t)&tp->t_outq);
        while (getc(&tp->t_canq) >= 0)
                ;
        wakeup((caddr_t)&tp->t_rawq);
        wakeup((caddr_t)&tp->t_outq);
-       s = spl6();
        tp->t_state &= ~TTSTOP;
        (*cdevsw[major(tp->t_dev)].d_stop)(tp);
        while (getc(&tp->t_outq) >= 0)
        tp->t_state &= ~TTSTOP;
        (*cdevsw[major(tp->t_dev)].d_stop)(tp);
        while (getc(&tp->t_outq) >= 0)
@@ -330,6 +480,8 @@ register struct tty *tp;
        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_lstate = 0;
        splx(s);
 }
 
        splx(s);
 }
 
@@ -389,7 +541,7 @@ loop:
                        break;
        }
        bp1 = &canonb[2];
                        break;
        }
        bp1 = &canonb[2];
-       VOID b_to_q(bp1, bp-bp1, &tp->t_canq);
+       (void) b_to_q(bp1, bp-bp1, &tp->t_canq);
 
        if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
                if (putc(tun.t_startc, &tp->t_outq)==0) {
 
        if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
                if (putc(tun.t_startc, &tp->t_outq)==0) {
@@ -415,9 +567,9 @@ register char *pb, *pe;
 
        tandem = tp->t_flags&TANDEM;
        if (tp->t_flags&RAW) {
 
        tandem = tp->t_flags&TANDEM;
        if (tp->t_flags&RAW) {
-               VOID b_to_q(pb, pe-pb, &tp->t_rawq);
+               (void) b_to_q(pb, pe-pb, &tp->t_rawq);
                if (tp->t_chan)
                if (tp->t_chan)
-                       VOID sdata(tp->t_chan); else
+                       (void) sdata(tp->t_chan); else
                        wakeup((caddr_t)&tp->t_rawq);
        } else {
                tp->t_flags &= ~TANDEM;
                        wakeup((caddr_t)&tp->t_rawq);
        } else {
                tp->t_flags &= ~TANDEM;
@@ -475,7 +627,7 @@ register struct tty *tp;
                        if (tp->t_chan)
                                scontrol(tp->t_chan, M_SIG, c);
                        else
                        if (tp->t_chan)
                                scontrol(tp->t_chan, M_SIG, c);
                        else
-                               signal(tp->t_pgrp, c);
+                               gsignal(tp->t_pgrp, c);
                        return;
                }
                if (c=='\r' && t_flags&CRMOD)
                        return;
                }
                if (c=='\r' && t_flags&CRMOD)
@@ -487,12 +639,12 @@ register struct tty *tp;
        }
        if (t_flags&LCASE && c>='A' && c<='Z')
                c += 'a'-'A';
        }
        if (t_flags&LCASE && c>='A' && c<='Z')
                c += 'a'-'A';
-       VOID putc(c, &tp->t_rawq);
+       (void) putc(c, &tp->t_rawq);
        if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) {
                if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0)
                        tp->t_delct++;
                if ((cp=tp->t_chan)!=NULL)
        if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) {
                if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0)
                        tp->t_delct++;
                if ((cp=tp->t_chan)!=NULL)
-                       VOID sdata(cp); else
+                       (void) sdata(cp); else
                        wakeup((caddr_t)&tp->t_rawq);
        }
        if (t_flags&ECHO) {
                        wakeup((caddr_t)&tp->t_rawq);
        }
        if (t_flags&ECHO) {
@@ -539,19 +691,18 @@ register struct tty *tp;
        register char *colp;
        register ctype;
 
        register char *colp;
        register ctype;
 
-       tk_nout++;
        /*
         * Ignore EOT in normal mode to avoid hanging up
         * certain terminals.
         * In raw mode dump the char unchanged.
         */
        /*
         * Ignore EOT in normal mode to avoid hanging up
         * certain terminals.
         * In raw mode dump the char unchanged.
         */
-
        if ((tp->t_flags&RAW)==0) {
                c &= 0177;
                if ((tp->t_flags&CBREAK)==0 && c==CEOT)
                        return;
        } else {
        if ((tp->t_flags&RAW)==0) {
                c &= 0177;
                if ((tp->t_flags&CBREAK)==0 && c==CEOT)
                        return;
        } else {
-               VOID putc(c, &tp->t_outq);
+               tk_nout++;
+               (void) putc(c, &tp->t_outq);
                return;
        }
 
                return;
        }
 
@@ -559,12 +710,13 @@ register struct tty *tp;
         * Turn tabs to spaces as required
         */
        if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
         * Turn tabs to spaces as required
         */
        if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
-               c = 8;
-               do
-                       ttyoutput(' ', tp);
-               while (--c >= 0 && tp->t_col&07);
+               c = 8 - (tp->t_col & 7);
+               (void) b_to_q("        ", c, &tp->t_outq);
+               tp->t_col += c;
+               tk_nout += c;
                return;
        }
                return;
        }
+       tk_nout++;
        /*
         * for upper-case-only terminals,
         * generate escapes.
        /*
         * for upper-case-only terminals,
         * generate escapes.
@@ -585,7 +737,7 @@ register struct tty *tp;
         */
        if (c=='\n' && tp->t_flags&CRMOD)
                ttyoutput('\r', tp);
         */
        if (c=='\n' && tp->t_flags&CRMOD)
                ttyoutput('\r', tp);
-       VOID putc(c, &tp->t_outq);
+       (void) putc(c, &tp->t_outq);
        /*
         * Calculate delays.
         * The numbers here represent clock ticks
        /*
         * Calculate delays.
         * The numbers here represent clock ticks
@@ -654,12 +806,12 @@ register struct tty *tp;
                } else if(ctype == 3) { /* concept 100 */
                        int i;
                        for (i= *colp; i<9; i++)
                } else if(ctype == 3) { /* concept 100 */
                        int i;
                        for (i= *colp; i<9; i++)
-                               VOID putc(0177, &tp->t_outq);
+                               (void) putc(0177, &tp->t_outq);
                }
                *colp = 0;
        }
        if(c)
                }
                *colp = 0;
        }
        if(c)
-               VOID putc(c|0200, &tp->t_outq);
+               (void) putc(c|0200, &tp->t_outq);
 }
 
 /*
 }
 
 /*
@@ -745,7 +897,7 @@ register struct tty *tp;
                iomove(cp, (unsigned)cc, B_WRITE);
                if (u.u_error)
                        break;
                iomove(cp, (unsigned)cc, B_WRITE);
                if (u.u_error)
                        break;
-               VOID spl5();
+               (void) spl5();
                while (tp->t_outq.c_cc > TTHIWAT) {
                        ttstart(tp);
                        tp->t_state |= ASLEEP;
                while (tp->t_outq.c_cc > TTHIWAT) {
                        ttstart(tp);
                        tp->t_state |= ASLEEP;
@@ -753,12 +905,12 @@ register struct tty *tp;
                                u.u_base -= cc;
                                u.u_offset -= cc;
                                u.u_count += cc;
                                u.u_base -= cc;
                                u.u_offset -= cc;
                                u.u_count += cc;
-                               VOID spl0();
+                               (void) spl0();
                                return((caddr_t)&tp->t_outq);
                        }
                        sleep((caddr_t)&tp->t_outq, TTOPRI);
                }
                                return((caddr_t)&tp->t_outq);
                        }
                        sleep((caddr_t)&tp->t_outq, TTOPRI);
                }
-               VOID spl0();
+               (void) spl0();
                if (tp->t_flags&LCASE) {
                        while (cc--)
                                ttyoutput(*cp++,tp);
                if (tp->t_flags&LCASE) {
                        while (cc--)
                                ttyoutput(*cp++,tp);
@@ -779,7 +931,7 @@ register struct tty *tp;
                                if (ce==0) {
                                        ttyoutput(*cp++,tp);
                                        cc--;
                                if (ce==0) {
                                        ttyoutput(*cp++,tp);
                                        cc--;
-                                       continue;
+                                       goto check;
                                }
                        }
                        i=b_to_q(cp,ce,&tp->t_outq);
                                }
                        }
                        i=b_to_q(cp,ce,&tp->t_outq);
@@ -788,14 +940,15 @@ register struct tty *tp;
                        tp->t_col+=ce;
                        cp+=ce;
                        cc-=ce;
                        tp->t_col+=ce;
                        cp+=ce;
                        cc-=ce;
-                       if (i) {
-                               VOID spl5();
+check:
+                       if (tp->t_outq.c_cc > TTHIWAT) {
+                               (void) spl5();
                                while (tp->t_outq.c_cc > TTHIWAT) {
                                        ttstart(tp);
                                        tp->t_state |= ASLEEP;
                                        sleep((caddr_t)&tp->t_outq, TTOPRI);
                                }
                                while (tp->t_outq.c_cc > TTHIWAT) {
                                        ttstart(tp);
                                        tp->t_state |= ASLEEP;
                                        sleep((caddr_t)&tp->t_outq, TTOPRI);
                                }
-                               VOID spl0();
+                               (void) spl0();
                        }
                }
        }
                        }
                }
        }