SRI-NOSC/dmr/misc/tty2.c

Compare this file to the similar file:
Show the results in this format:

#

/*
 * general TTY subroutines
 */
#include "/usr/sys/h/param.h"
#include "/usr/sys/h/systm.h"
#include "/usr/sys/h/user.h"
#include "/usr/sys/h/tty1.h"
#include "/usr/sys/h/proc.h"
#include "/usr/sys/h/inode.h"
#include "/usr/sys/h/file.h"
#include "/usr/sys/h/reg.h"
#include "/usr/sys/h/conf.h"

/*
 * 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[];

/*
 * character mapping tables for ibm 2741
 */
char	uc[],lc[];
/*
 * The actual structure of a clist block manipulated by
 * getc and putc (mch.s)
 */
struct cblock {
	struct cblock *c_next;
	char info[6];
};

/* The character lists-- space for 6*NCLIST characters */
struct cblock cfree[NCLIST];
/* List head for unused character blocks. */
struct cblock *cfreelist;

/*
 * structure of device registers for KL, DL, and DC
 * interfaces-- more particularly, those for which the
 * SSTART bit is off and can be treated by general routines
 * (that is, not DH).
 */
struct {
	int ttrcsr;
	int ttrbuf;
	int tttcsr;
	int tttbuf;
};
/*
 * transfer raw input list to canonical list,
 * doing erase-kill processing and handling escapes.
 * It waits until a full line has been typed in cooked mode,
 * or until any character has been typed in raw mode.
 */
canon(atp)
struct tty *atp;
{
	register char *bp;
	char *bp1;
	register struct tty *tp;
	register int c;
	int cnt;

	tp = atp;
	spl5();
	while (tp->t_delct==0) {
		if ((tp->t_state&CARR_ON)==0)
			return(0);
		sleep(&tp->t_rawq, TTIPRI);
	}
	spl0();
loop:
	bp = &canonb[2];
	while ((c=getc(&tp->t_rawq)) >= 0) {
		if (c==0377) {
			tp->t_delct--;
			/* so may receive more than one char in raw mode */
			if (tp->t_flags&RAW)
				continue;
			break;
		}
		if (c==0376) {
			if (tp->t_speeds&LOOP) {
				tp->t_delct--;
				continue;
			}
		}
		/*
		 * handle escape and single char erase processing.
		 * 2741 has the erase character hard-coded to the
		 * default CERASE.  The backspace key on the 2741
		 * is always translated to CERASE which is defined
		 * in tty.h.  Normal devices have a programmable
		 * erase char in this version of unix.
		 */
		if (!(tp->t_flags&RAW)) {
			if (bp[-1]!='\\') {
#ifdef	IBM
				if ((tp->t_speeds&017)==IBM && c==CERASE) {
					if (bp> &canonb[2])
						bp--;
					continue;
				}
#endif	IBM
				if (c==tp->t_erase
#ifdef	IBM
				&& (tp->t_speeds&017) != IBM
#endif	IBM
				) {
					if (bp > &canonb[2])
						bp--;
					continue;
				}
				if (c==tp->t_kill)
					goto loop;
				if (c==CEOT)
					continue;
			} else 
			if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) {
				if (bp[-2] != '\\') {
					c = maptab[c];
				}
				bp--;
			}
		}
		*bp++ = c;
		if (bp>=canonb+CANBSIZ)
			break;
	}
	bp1 = bp;
	bp = &canonb[2];
	cnt = bp1 - bp;			/* calc num chars processed */
	c = &tp->t_canq;
	while (bp<bp1) {
		putc(*bp++, c);
	}
	return(cnt);
}

/*
 * 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(ac, atp)
struct tty *atp;
{
	register int t_flags, c;
	register struct tty *tp;
	int conv;

	tp = atp;
	c = ac & 0177;
	/*
	 * Input processing for 2741's is done here
	 * separately from normal devices.  Thus only one compare
	 * is done to get here, and normal processing is not affected.
	 * The following implements the 2741 synchronization strategy
	 * with the output side and the necessary
	 * character translations.
	 */
#ifdef	IBM
	if ((tp->t_speeds&017) == IBM) {
		/*
		 * the only way (c==0177) is if a break
		 * is detected by the driver.  To be consistent with
		 * standard unix this is translated to a zero for getty
		 * so that speed-shifting on login can be done.
		 * it must be done this way because zero is a
		 * legal 2741 character.
		 */
		if (c==0177) {
		   if (tp->t_flags&RAW) {
			if (!putc(0,&tp->t_rawq)) {
				tp->t_delct++;
			}
			wakeup(&tp->t_rawq);
			return;
		   }
		}
		c =& 077;		/* mask to 6-bits in case of 0177 */
		/*
		 * record upper/lower case changes
		 */
		if (c==LC) {
			tp->ibm =& ~0200;
			tp->ibm =| 0100;
			return;
		}
		if (c==UC) {
			tp->ibm =& ~0100;
			tp->ibm =| 0200;
			return;
		}
		/*
		 * CRD char is not unique.  It is treated as such only if
		 * expected; i.e. when CHANGE bit has been set by the
		 * output side.
		 */
		if (c==CRD) {
			if (tp->ibm & CHANGE) {
				tp->ibm =& ~  (CHANGE+LOCK+EOL);
				tp->ibm =| ULOCK;
				wakeup(&tp->ibm);
				return;
			}
		}
		/*
		 * CRC is unique indicating end of tty message and
		 * transition to locked keyboard.
		 */
		if (c==CRC) {
			if (tp->ibm&WANT) {
				tp->ibm =| LOCK;
				wakeup(&tp->ibm);
				return;
			}
			if (tp->ibm&CHANGE) {
				printf(" urk ");
			}
			tp->ibm=| CHANGE;
			putc(CRC,&tp->t_outq);
			putc(0214,&tp->t_outq);
			ttstart(tp);
			/*
			 * if EOL not set, we have a null
			 * input line.  this can be got only
			 * by pressing the ATTN key.  so c gets
			 * converted to 077 which translates
			 * to 0177 (rubout) below
			 */
			if (!(tp->ibm&EOL)) {
				c = 077;
			}
			else return;
		}
		/*
		 * translate 6-bit chars to ascii
		 * first pick a char out of translate table.
		 * then do escape processing.  CMAP bit is high
		 * if previous char was the escape char.
		 */
		if ((tp->ibm&CASE)&0100)
			c = lc[c];
		else	c = uc[c];
		if (tp->ibm&CMAP) {
			tp->ibm =& ~  CMAP;
			switch(c) {
			   case 'D': c=CEOT;	break;
			   case 'E': c= 033;	break;	/* ESC for tenex */
			   case 'Q': c=CQUIT;	break;
			   case 'L': c= '<';	break;
			   case 'G': c= '>';	break;
			   case '!': c= '|';	break;
			   case '(': c= '{';	break;
			   case ')': c= '}';	break;
			   case 047: c= '`';	break;
			   case 'T': c= '~';	break;
			   case 'U': c= '^';	break;
			   case 'r':
			   case 't':
			   case 'n':
			   case '\\': putc('\\',&tp->t_rawq);
						break;
			   default:
				/* 
				 * convert alphabetics not trapped
				 * by the case statement to 
				 * ASCII control characters.
				 */
				conv = 0;
				if (c>='A' && c<='Z') {
					conv = 0100;
				}
				if (c>='a' && c<='z') {
					conv = 0140;
				}
				if (conv) c=- conv;
				else putc('\\',&tp->t_rawq);
			}
		} else if (c == '\\') {
			tp->ibm =| CMAP;
			return;
		}
		/*
		 * notice end-of-line in order to detect
		 * null lines from ibm terminal
		 */
		if (c=='\n') tp->ibm =| EOL;
		else tp->ibm =& ~ EOL;
	}
#endif	IBM
	t_flags = tp->t_flags;
	/*
	 * block output side if user hasn't finished typing
	 * an input line as long as we're not in raw mode.
	 */
	if (!(t_flags&RAW) && c!= '\n') {
		tp->t_speeds =| BLOCK;
		/*
		 * CSTOP character toggles output blocking.
		 * CDUMP is used to throw characters away.
		 * this is used to (1) remove CSTOP chars from
		 * the input stream, (2) to throw away newline-
		 * after-line delete for 2741's.
		 */
		if (c==CSTOP) {
			if (tp->t_speeds&CDUMP) c = '\n';
			else {
				tp->t_speeds =| CDUMP;
				return;
			}
		} else tp->t_speeds =& ~  CDUMP;
	}
	if (( c =& 0177 ) == '\r' && t_flags&CRMOD )
		c = '\n';
	/*
	 * Handle process-interrupting characters,
	 * re-enable output,
	 * turn line around for 2741's.
	 */
	if (!(t_flags&RAW) && (c==CQUIT || c==CINTR)) {
		signal(tp->t_pgrp, c==CINTR? SIGINT:SIGQIT);
		flushtty(tp);
		tp->t_speeds=& ~ (BLOCK+CDUMP);
		wakeup(&tp->t_speeds);
#ifdef	IBM
		if ((tp->t_speeds&017)==IBM) {
			tp->ibm=LOCK;
			ttstop(tp);
		}
#endif	IBM
		return;
	}
	if (tp->t_rawq.c_cc >= TTYHOG) {
		flushtty(tp);
		return;
	}
	if (t_flags&LCASE && c>='A' && c<='Z')
		c =+ 'a'-'A';
	if (c!='\n' || !(tp->t_speeds&CDUMP))
		putc(c, &tp->t_rawq);
	if (t_flags&RAW || c=='\n' || c==004) {
		wakeup(&tp->t_speeds);
		tp->t_speeds=& ~BLOCK;
		if (c=='\n' && tp->t_speeds&CDUMP) {
			tp->t_speeds=& ~ CDUMP;
			return;
		}
		wakeup(&tp->t_rawq);
		if (putc(0377, &tp->t_rawq)==0)
			tp->t_delct++;
	}
	/*
	 * Some unix software twiddles the ECHO bit.
	 * This must be ignored on 2741's.
	 */
	if (t_flags & ECHO
#ifdef	IBM
	&& !((tp->t_speeds&017)==IBM)
#endif	IBM
	) {
		ttyoutput(c,tp);
		ttstart(tp);
	}
	/*
	 * Line kill processing done here.
	 * echo newline and enable output
	 * (except for 2741's)
	 */
	if (c==tp->t_kill && !(t_flags&RAW)) {
#ifdef	IBM
		if ((tp->t_speeds&017)==IBM) {
			tp->t_speeds=| CDUMP;
			return;
		}
#endif	IBM
		ttyoutput('\n',tp);
		tp->t_speeds =& ~  (BLOCK+CDUMP);
		ttstart(tp);
		wakeup(&tp->t_speeds);
	}
}