From 94c91d405400aea8db724eef5b8efaddc25180b8 Mon Sep 17 00:00:00 2001 From: Jim Kulp Date: Sun, 9 Nov 1980 08:37:25 -0800 Subject: [PATCH] BSD 4 development Work on file usr/src/sys/dev/ttynew.c Synthesized-from: CSRG//cd1/4.0 --- usr/src/sys/dev/ttynew.c | 872 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 872 insertions(+) create mode 100644 usr/src/sys/dev/ttynew.c diff --git a/usr/src/sys/dev/ttynew.c b/usr/src/sys/dev/ttynew.c new file mode 100644 index 0000000000..bb668f49a0 --- /dev/null +++ b/usr/src/sys/dev/ttynew.c @@ -0,0 +1,872 @@ +/* ttynew.c 4.3 11/9/80 */ + +/* + * New version of tty driver, supported + * as NTTYDISC. Adapted from a tty.c written + * by J.E.Kulp of IIASA, Austria (jekulp@mc) + */ +#include "../h/param.h" +#include "../h/systm.h" +#include "../h/dir.h" +#include "../h/user.h" +#include "../h/tty.h" +#include "../h/proc.h" +#include "../h/mx.h" +#include "../h/inode.h" +#include "../h/file.h" +#include "../h/reg.h" +#include "../h/conf.h" +#include "../h/buf.h" +#include "../h/dk.h" + +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 + * corresponding character is typed preceded by "\" the escape + * sequence is replaced by the table value. Mostly used for + * upper-case only terminals. + */ + +char maptab[]; /* see tty.c */ + +/* + * shorthand + */ +#define q1 tp->t_rawq +#define q2 tp->t_canq +#define q3 tp->t_outq +#define q4 tp->t_un.t_ctlq + +#define OBUFSIZ 100 + +/* + * routine called on opens while tp->t_line == NTTYDISC + * establishes a process group for distribution of + * 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) + */ +ntyopen(dev, tp) +dev_t dev; +register struct tty *tp; +{ + register struct proc *pp; + + pp = u.u_procp; + tp->t_dev = dev; + if(pp->p_pgrp == 0) { + u.u_ttyp = tp; + u.u_ttyd = dev; + 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; + if (tp->t_line != NTTYDISC) + wflushtty(tp); +} + +/* + * clean tp on last close + */ +ntyclose(tp) +register struct tty *tp; +{ + + wflushtty(tp); + /* let ttyclose do the work if we are really closing */ +} + +/* + * block transfer input handler. + */ +ntyrend(tp, pb, pe) +register struct tty *tp; +register char *pb, *pe; +{ + int tandem; + + tandem = tp->t_flags&TANDEM; + if (tp->t_flags&RAW) { + (void) b_to_q(pb, pe-pb, &tp->t_rawq); + if (tp->t_chan) + (void) sdata(tp->t_chan); + else + wakeup((caddr_t)&tp->t_rawq); + } else { + tp->t_flags &= ~TANDEM; + while (pb < pe) + ntyinput(*pb++, tp); + tp->t_flags |= tandem; + } + if (tandem) + ttyblock(tp); +} + +/* + * reinput pending characters after state switch + * call at spl5(). + */ +ntypend(tp) +register struct tty *tp; +{ + struct clist tq; + register c; + + tp->t_local &= ~LPENDIN; + tp->t_lstate |= LSTYPEN; + 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) + ntyinput(c, tp); + tp->t_lstate &= ~LSTYPEN; +} + +/* + * 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. + */ +ntyinput(c, tp) +register c; +register struct tty *tp; +{ + register int t_flags; + int i; + + if (tp->t_local&LPENDIN) + ntypend(tp); + tk_nin++; + c &= 0377; + t_flags = tp->t_flags; + 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 (c==tlun.t_lnextc) { + if (tp->t_flags&ECHO) + ntyout("^\b", tp); + tp->t_lstate |= LSLNCH; + /* check for output control functions */ + } else if (c==tun.t_stopc) { + if ((tp->t_state&TTSTOP)==0) { + tp->t_state |= TTSTOP; + (*cdevsw[major(tp->t_dev)].d_stop)(tp); + return; + } + if (c!=tun.t_startc) + return; + } else if (c==tun.t_startc) + ; + /* check for input interrupts (and flushed output) */ + else if (c==tlun.t_flushc) { + if (tp->t_local & LFLUSHO) + tp->t_local &= ~LFLUSHO; + else { + flushtty(tp, FWRITE); + ntyecho(c, tp); + if (tp->t_rawq.c_cc+tp->t_canq.c_cc) + ntyretype(tp); + tp->t_local |= LFLUSHO; + } + ttstart(tp); + return; + } else if (c==tlun.t_suspc || c==tun.t_intrc || + c==tun.t_quitc) { + flushtty(tp, c==tlun.t_suspc ? FREAD : FREAD|FWRITE); + ntyecho(c, tp); + c = c==tun.t_intrc ? SIGINT : + ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP); + if (tp->t_chan) + scontrol(tp->t_chan, M_SIG, c); + else + gsignal(tp->t_pgrp, 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)) { + ntyrub(unputc(&tp->t_rawq), tp); + c |= 0200; + } + if (c==tp->t_erase) { + if (tp->t_rawq.c_cc) + ntyrub(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) + ntyrub(unputc(&tp->t_rawq), tp); + } else { + ntyecho(c, tp); + ntyecho('\n', tp); + while (getc(&tp->t_rawq) > 0) + ; + tp->t_rocount = 0; + } + tp->t_lstate = 0; + } else if (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; + ntyrub(c, tp); + } while (tp->t_rawq.c_cc); + goto out; + erasenb: + do { + ntyrub(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 (c==tlun.t_rprntc) { + ntyretype(tp); + /* check for cooked mode input buffer overflow */ + } else if (tp->t_rawq.c_cc + tp->t_canq.c_cc > TTYHOG) { + /* we should start a timeout that flushes the + buffer if it stays full - same in CBREAK */ + if (tp->t_outq.c_cc < TTHIWAT(tp)) + (void) ntyoutput(CTRL(g), tp); + /* put data char in q for user and wakeup if a break char */ + } else if (putc(c, &tp->t_rawq) >= 0) { + if (!ntbreakc(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); + else + wakeup((caddr_t)&tp->t_rawq); + if (tp->t_local&LINTRUP) + gsignal(tp->t_pgrp, SIGTINT); + } + tp->t_lstate &= ~LSQUOT; + if (c == '\\') + tp->t_lstate |= LSQUOT; + if (tp->t_lstate&LSERASE) { + tp->t_lstate &= ~LSERASE; + (void) ntyoutput('/', tp); + } + i = tp->t_col; + ntyecho(c, tp); + if (c==tun.t_eofc && tp->t_flags&ECHO) { + i = MIN(2, tp->t_col - i); + while (i > 0) { + (void) ntyoutput('\b', tp); + i--; + } + } + } + /* CBREAK mode */ + } else if (tp->t_rawq.c_cc > TTYHOG) { + if (tp->t_outq.c_cc < TTHIWAT(tp)) + (void) ntyoutput(CTRL(g), tp); + } else if (putc(c, &tp->t_rawq) >= 0) { + if (tp->t_local&LINTRUP) + gsignal(tp->t_pgrp, SIGTINT); + if (tp->t_chan) + (void) sdata(tp->t_chan); + else + wakeup((caddr_t)&tp->t_rawq); + ntyecho(c, tp); + } + /* RAW mode */ + } else if (tp->t_rawq.c_cc > TTYHOG) + flushtty(tp, FREAD|FWRITE); + else if (putc(c, &tp->t_rawq) >= 0) { + if (tp->t_local&LINTRUP) + gsignal(tp->t_pgrp, SIGTINT); + if (tp->t_chan) + (void) sdata(tp->t_chan); + else + wakeup((caddr_t)&tp->t_rawq); + } +out: + tp->t_state &= ~TTSTOP; + tp->t_local &= ~LFLUSHO; + ttstart(tp); +} + +/* + * put character on TTY output queue, adding delays, + * expanding tabs, and handling the CR/NL bit. + * It 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. + */ +ntyoutput(c, tp) +register c; +register struct tty *tp; +{ + register char *colp; + register ctype; + + if (tp->t_flags&RAW || tp->t_local&LLITOUT) { + if (tp->t_local&LFLUSHO) + 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. + */ + c &= 0177; + if (c==CEOT && (tp->t_flags&CBREAK)==0) + return (-1); + /* + * Turn tabs to spaces as required + */ + if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { + register int s; + + c = 8 - (tp->t_col&7); + if ((tp->t_local&LFLUSHO) == 0) { + s = spl5(); /* don't interrupt tabs */ + c -= b_to_q(" ", c, &tp->t_outq); + tk_nout += c; + splx(s); + } + tp->t_col += c; + return (c ? -1 : '\t'); + } + tk_nout++; + /* + * for upper-case-only terminals, + * generate escapes. + */ + if (tp->t_flags&LCASE) { + colp = "({)}!|^~'`"; + while(*colp++) + if(c == *colp++) { + if (ntyoutput('\\', tp) >= 0) + return (c); + c = colp[-2]; + break; + } + if ('A'<=c && c<='Z') { + if (ntyoutput('\\', tp) >= 0) + return (c); + } else if ('a'<=c && c<='z') + c += 'A' - 'a'; + } + /* + * turn to if desired. + */ + if (c=='\n' && tp->t_flags&CRMOD) + if (ntyoutput('\r', tp) >= 0) + return (c); + if (c=='~' && tp->t_local<ILDE) + c = '`'; + if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq)) + return (c); + /* + * Calculate delays. + * The numbers here represent clock ticks + * and are not necessarily optimal for all terminals. + * The delays are indicated by characters above 0200. + * In raw mode there are no delays and the + * transmission path is 8 bits wide. + */ + colp = &tp->t_col; + ctype = partab[c]; + c = 0; + switch (ctype&077) { + + case ORDINARY: + (*colp)++; + + case CONTROL: + break; + + 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. + */ +ntread(tp) +register struct tty *tp; +{ + register struct clist *qp; + register c, first; + + if ((tp->t_state&CARR_ON)==0) + return(0); +loop: + (void) spl5(); + if (tp->t_local&LPENDIN) + ntypend(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&CARR_ON)==0 || tp->t_chan!=NULL) { + (void) spl0(); + return (0); + } + if (tp->t_local&LINTRUP && + u.u_signal[SIGTINT] != SIG_DFL) { + u.u_error = EIO; + (void) spl0(); + return (0); + } + sleep((caddr_t)&tp->t_rawq, TTIPRI); + (void) spl0(); + goto loop; + } + (void) spl0(); + while (tp->t_rawq.c_cc && passc(getc(&tp->t_rawq))>=0) + ; + 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&CARR_ON)==0 || tp->t_chan!=NULL) { + (void) spl0(); + return (0); + } + if (tp->t_local&LINTRUP && + u.u_signal[SIGTINT] != SIG_DFL) { + u.u_error = EIO; + (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 (c == tlun.t_dsuspc) { + gsignal(tp->t_pgrp, SIGTSTP); + if (first) { + sleep((caddr_t)&lbolt, TTIPRI); + goto loop; + } + break; + } + if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0) + break; + if (passc(c & 0177) < 0) + break; + if ((tp->t_flags&CBREAK)==0 && ntbreakc(c, tp)) + break; + first = 0; + } + tp->t_lstate &= ~LSBKSL; + } + + if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { + if (putc(tun.t_startc, &tp->t_outq)==0) { + tp->t_state &= ~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 +ntwrite(tp) +register struct tty *tp; +{ +#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); + + if ((tp->t_state&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 (u.u_count) { + cc = MIN(u.u_count, OBUFSIZ); + cp = obuf; + iomove(cp, (unsigned)cc, B_WRITE); + 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 = ntyoutput(c, tp)) >= 0) { + /* out of clists, wait a bit */ + ttstart(tp); + sleep((caddr_t)&lbolt, TTOPRI); + tp->t_rocount = 0; + } + 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)&&(cet_rocount = 0; + if (ntyoutput(*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(); + u.u_base -= cc; + u.u_offset -= cc; + u.u_count += cc; + if (tp->t_outq.c_cc <= hiwat) { + (void) spl0(); + goto loop; + } + ttstart(tp); + tp->t_state |= ASLEEP; + if (tp->t_chan) { + (void) spl0(); + return ((caddr_t)&tp->t_outq); + } + sleep((caddr_t)&tp->t_outq, TTOPRI); + (void) spl0(); + goto loop; +} + +/* + * Rubout one character from the rawq of tp + * as cleanly as possible. + */ +ntyrub(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 + */ + ntyretype(tp); + return; + } + if (c==('\t'|0200) || c==('\n'|0200)) + ntyrubo(tp, 2); + else switch(partab[c&=0177] & 0177) { + + case ORDINARY: + if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z') + ntyrubo(tp, 2); + else + ntyrubo(tp, 1); + break; + + case VTAB: + case BACKSPACE: + case CONTROL: + case RETURN: + if (tp->t_local & LCTLECH) + ntyrubo(tp, 2); + break; + + case TAB: + if (tp->t_rocount < tp->t_rawq.c_cc) { + ntyretype(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)) + ntyecho(*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) ntyoutput('\b', tp); + break; + + default: + panic("ttyrub"); + } + } else if (tp->t_local&LPRTERA) { + if ((tp->t_lstate&LSERASE) == 0) { + (void) ntyoutput('\\', tp); + tp->t_lstate |= LSERASE; + } + ntyecho(c, tp); + } else + ntyecho(tp->t_erase, tp); + tp->t_rocount--; +} + +/* + * Crt back over cnt chars perhaps + * erasing them. + */ +ntyrubo(tp, cnt) +register struct tty *tp; +int cnt; +{ + + while (--cnt >= 0) + ntyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp); +} + +/* + * Reprint the rawq line. + * We assume c_cc has already been checked. + */ +ntyretype(tp) +register struct tty *tp; +{ + register char *cp; + char *nextc(); + int s; + + if (tlun.t_rprntc != 0377) + ntyecho(tlun.t_rprntc, tp); + (void) ntyoutput('\n', tp); + s = spl5(); + for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) + ntyecho(*cp, tp); + for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) + ntyecho(*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 + */ +ntyecho(c, tp) +register c; +register struct tty *tp; +{ + + if ((tp->t_lstate & LSCNTTB) == 0) + tp->t_local &= ~LFLUSHO; + c &= 0377; + if (tp->t_flags&ECHO) { + 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) ntyoutput('^', tp); + c &= 0177; + if (c == 0177) + c = '?'; + else if (tp->t_flags&LCASE) + c += 'a' - 1; + else + c += 'A' - 1; + } + } + (void) ntyoutput(c & 0177, tp); + } +} + +/* + * Is c a break char for tp? + */ +ntbreakc(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 + */ +ntyout(cp, tp) +register char *cp; +register struct tty *tp; +{ + register char c; + + while (c = *cp++) + (void) ntyoutput(c, tp); +} -- 2.20.1