+ case BACKSPACE:
+ if (*colp)
+ (*colp)--;
+ break;
+
+ case NEWLINE:
+ ctype = (tp->t_flags >> 8) & 03;
+ if (ctype == 1) { /* tty 37 */
+ if (*colp)
+ c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
+ } else
+ if (ctype == 2) { /* vt05 */
+ c = 6;
+ }
+ *colp = 0;
+ break;
+
+ case TAB:
+ ctype = (tp->t_flags >> 10) & 03;
+ if (ctype == 1) { /* tty 37 */
+ c = 1 - (*colp | ~07);
+ if (c < 5)
+ c = 0;
+ }
+ *colp |= 07;
+ (*colp)++;
+ break;
+
+ case VTAB:
+ if (tp->t_flags & VTDELAY) /* tty 37 */
+ c = 0177;
+ break;
+
+ case RETURN:
+ ctype = (tp->t_flags >> 12) & 03;
+ if (ctype == 1) { /* tn 300 */
+ c = 5;
+ } else if (ctype == 2) { /* ti 700 */
+ c = 10;
+ } else if (ctype == 3) { /* concept 100 */
+ int i;
+ if ((i = *colp) >= 0)
+ for (; i<9; i++)
+ (void) putc(0177, &tp->t_outq);
+ }
+ *colp = 0;
+ }
+ if (c && (tp->t_local&LFLUSHO) == 0)
+ (void) putc(c|0200, &tp->t_outq);
+ return (-1);
+}
+
+/*
+ * Called from device's read routine after it has
+ * calculated the tty-structure given as argument.
+ */
+ttread(tp, uio)
+ register struct tty *tp;
+ struct uio *uio;
+{
+ register struct clist *qp;
+ register c, first;
+
+ if ((tp->t_state&TS_CARR_ON)==0)
+ return (0);
+loop:
+ (void) spl5();
+ if (tp->t_local&LPENDIN)
+ ttypend(tp);
+ (void) spl0();
+ 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) ||
+*/
+ u.u_procp->p_flag&SVFORK)
+ return (0);
+ gsignal(u.u_procp->p_pgrp, SIGTTIN);
+ sleep((caddr_t)&lbolt, TTIPRI);
+ }
+ if (tp->t_flags&RAW) {
+ (void) spl5();
+ if (tp->t_rawq.c_cc <= 0) {
+ if ((tp->t_state&TS_CARR_ON)==0 ||
+ (tp->t_state&TS_NBIO)) {
+ (void) spl0();
+ return (0);
+ }
+ sleep((caddr_t)&tp->t_rawq, TTIPRI);
+ (void) spl0();
+ goto loop;
+ }
+ (void) spl0();
+ while (tp->t_rawq.c_cc && uio->uio_iovcnt) {
+ u.u_error = passuc(getc(&tp->t_rawq), uio);
+ if (u.u_error)
+ break;
+ }
+ return (0);
+ } 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 (0);
+ }
+ sleep((caddr_t)&tp->t_rawq, TTIPRI);
+ (void) spl0();
+ goto loop;
+ }
+ (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;
+ }
+ if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
+ break;
+ u.u_error = passuc(c & 0177, uio);
+ if (u.u_error)
+ break;
+ if (uio->uio_iovcnt == 0)
+ break;
+ if ((tp->t_flags&CBREAK)==0 && ttbreakc(c, tp))
+ break;
+ first = 0;
+ }
+ tp->t_lstate &= ~LSBKSL;
+ }
+
+ if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
+ if (putc(tun.t_startc, &tp->t_outq)==0) {
+ tp->t_state &= ~TS_TBLOCK;
+ ttstart(tp);
+ }
+ tp->t_char = 0;
+ }
+
+ return (tp->t_rawq.c_cc + tp->t_canq.c_cc);
+}
+
+/*
+ * Called from the device's write routine after it has
+ * calculated the tty-structure given as argument.
+ */
+caddr_t
+ttwrite(tp, uio)
+ register struct tty *tp;
+ 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 int cc, ce;
+ register i;
+ char obuf[OBUFSIZ];
+ register c;
+ int hiwat = TTHIWAT(tp);
+ int cnt = uio->uio_resid;
+
+ if ((tp->t_state&TS_CARR_ON)==0)
+ return (NULL);
+loop:
+ while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
+ (tp->t_local<OSTOP) && (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) {
+*/
+ ) {
+ gsignal(u.u_procp->p_pgrp, SIGTTOU);
+ sleep((caddr_t)&lbolt, TTIPRI);
+ }
+ while (uio->uio_resid > 0) {
+ cc = uio->uio_iov->iov_len;
+ if (cc == 0) {
+ uio->uio_iovcnt--;
+ uio->uio_iov++;
+ if (uio->uio_iovcnt < 0)
+ panic("ttwrite");
+ continue;
+ }
+ if (cc > OBUFSIZ)
+ cc = OBUFSIZ;
+ cp = obuf;
+ u.u_error = uiomove(cp, cc, UIO_WRITE, uio);
+ if (u.u_error)
+ break;
+ if (tp->t_outq.c_cc > hiwat)
+ goto ovhiwat;
+ if (tp->t_local&LFLUSHO)
+ continue;
+ if (tp->t_flags&LCASE || tp->t_local<ILDE) {
+ while (cc) {
+ c = *cp++;
+ tp->t_rocount = 0;
+ while ((c = ttyoutput(c, tp)) >= 0) {
+ /* out of clists, wait a bit */
+ ttstart(tp);
+ sleep((caddr_t)&lbolt, TTOPRI);
+ tp->t_rocount = 0;
+ }
+ --cc;
+ if (tp->t_outq.c_cc > hiwat)
+ goto ovhiwat;
+ }
+ continue;
+ }
+ while (cc) {
+ if (tp->t_flags&RAW || tp->t_local&LLITOUT)
+ 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) {
+ tp->t_rocount = 0;
+ if (ttyoutput(*cp, tp) >= 0) {
+ ttstart(tp);
+ sleep((caddr_t)&lbolt, TTOPRI);
+ continue;
+ }
+ cp++;
+ cc--;
+ if (tp->t_outq.c_cc > hiwat)
+ goto ovhiwat;
+ }
+ }
+ 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) {
+ ttstart(tp);
+ sleep((caddr_t)&lbolt, TTOPRI);
+ }
+ if (ce || tp->t_outq.c_cc > hiwat)
+ goto ovhiwat;
+ }
+ }
+ ttstart(tp);
+ return (NULL);
+
+ovhiwat:
+ (void) spl5();
+ uio->uio_iov->iov_base -= cc;
+ uio->uio_iov->iov_len += cc;
+ uio->uio_resid += cc;
+ uio->uio_offset -= cc;
+ if (tp->t_outq.c_cc <= hiwat) {
+ (void) spl0();
+ goto loop;
+ }
+ ttstart(tp);
+ if (tp->t_state & TS_NBIO) {
+ if (uio->uio_resid == cnt)
+ u.u_error = EWOULDBLOCK;
+ return (NULL);
+ }
+ tp->t_state |= TS_ASLEEP;
+ sleep((caddr_t)&tp->t_outq, TTOPRI);
+ (void) spl0();
+ goto loop;
+}
+
+/*
+ * Rubout one character from the rawq of tp
+ * as cleanly as possible.
+ */
+ttyrub(c, tp)
+ register c;
+ register struct tty *tp;
+{
+ register char *cp;
+ register int savecol;
+ int s;
+ char *nextc();
+
+ if ((tp->t_flags&ECHO)==0)
+ return;
+ tp->t_local &= ~LFLUSHO;
+ c &= 0377;
+ if (tp->t_local&LCRTBS) {
+ if (tp->t_rocount == 0) {
+ /*
+ * Screwed by ttwrite; retype
+ */
+ ttyretype(tp);
+ return;
+ }
+ if (c==('\t'|0200) || c==('\n'|0200))
+ ttyrubo(tp, 2);
+ else switch (partab[c&=0177] & 0177) {
+
+ case ORDINARY:
+ if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
+ ttyrubo(tp, 2);
+ else
+ ttyrubo(tp, 1);
+ break;
+
+ case VTAB:
+ case BACKSPACE:
+ case CONTROL:
+ case RETURN:
+ if (tp->t_local & LCTLECH)
+ ttyrubo(tp, 2);
+ break;
+
+ case TAB:
+ if (tp->t_rocount < tp->t_rawq.c_cc) {
+ ttyretype(tp);
+ return;
+ }
+ s = spl5();
+ savecol = tp->t_col;
+ tp->t_lstate |= LSCNTTB;
+ tp->t_local |= LFLUSHO;
+ tp->t_col = tp->t_rocol;
+ for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
+ ttyecho(*cp, tp);
+ tp->t_local &= ~LFLUSHO;
+ tp->t_lstate &= ~LSCNTTB;
+ splx(s);
+ /*
+ * savecol will now be length of the tab
+ */
+ savecol -= tp->t_col;
+ tp->t_col += savecol;
+ if (savecol > 8)
+ savecol = 8; /* overflow screw */
+ while (--savecol >= 0)
+ (void) ttyoutput('\b', tp);
+ break;
+
+ default:
+ panic("ttyrub");
+ }
+ } else if (tp->t_local&LPRTERA) {
+ if ((tp->t_lstate&LSERASE) == 0) {
+ (void) ttyoutput('\\', tp);
+ tp->t_lstate |= LSERASE;
+ }
+ ttyecho(c, tp);
+ } else
+ ttyecho(tp->t_erase, tp);
+ tp->t_rocount--;
+}
+
+/*
+ * Crt back over cnt chars perhaps
+ * erasing them.
+ */
+ttyrubo(tp, cnt)
+ register struct tty *tp;
+ int cnt;
+{
+
+ while (--cnt >= 0)
+ ttyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
+}
+
+/*
+ * Reprint the rawq line.
+ * We assume c_cc has already been checked.
+ */
+ttyretype(tp)
+ register struct tty *tp;
+{
+ register char *cp;
+ char *nextc();
+ int s;
+
+ if (tlun.t_rprntc != 0377)
+ ttyecho(tlun.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);
+ tp->t_lstate &= ~LSERASE;
+ splx(s);
+ tp->t_rocount = tp->t_rawq.c_cc;
+ tp->t_rocol = 0;
+}
+
+/*
+ * Echo a typed character to the terminal
+ */
+ttyecho(c, tp)
+ register c;
+ register struct tty *tp;
+{
+
+ if ((tp->t_lstate & LSCNTTB) == 0)
+ tp->t_local &= ~LFLUSHO;
+ if ((tp->t_flags&ECHO) == 0)
+ return;
+ c &= 0377;
+ if (tp->t_flags&RAW) {
+ (void) ttyoutput(c, tp);
+ return;
+ }
+ if (c == '\r' && tp->t_flags&CRMOD)
+ c = '\n';
+ if (tp->t_local&LCTLECH) {
+ if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
+ (void) ttyoutput('^', tp);
+ c &= 0177;
+ if (c == 0177)
+ c = '?';
+ else if (tp->t_flags&LCASE)
+ c += 'a' - 1;
+ else
+ c += 'A' - 1;
+ }
+ }
+ if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
+ c += 'a' - 'A';
+ (void) ttyoutput(c & 0177, tp);
+}
+
+/*
+ * Is c a break char for tp?
+ */
+ttbreakc(c, tp)
+ register c;
+ register struct tty *tp;
+{
+ return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
+ c == '\r' && (tp->t_flags&CRMOD));
+}
+
+/*
+ * send string cp to tp
+ */
+ttyout(cp, tp)
+ register char *cp;
+ register struct tty *tp;
+{
+ register char c;
+
+ while (c = *cp++)
+ (void) ttyoutput(c, tp);
+}
+
+ttwakeup(tp)
+ struct tty *tp;
+{
+
+ if (tp->t_rsel) {
+ selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
+ tp->t_state &= ~TS_RCOLL;
+ tp->t_rsel = 0;