⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tty.c

📁 UNIX v6源代码 这几乎是最经典的unix版本 unix操作系统设计和莱昂氏unix源代码分析都是用的该版
💻 C
字号:
#/* *//* * general TTY subroutines */#include "../param.h"#include "../systm.h"#include "../user.h"#include "../tty.h"#include "../proc.h"#include "../inode.h"#include "../file.h"#include "../reg.h"#include "../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[]{	000,000,000,000,004,000,000,000,	000,000,000,000,000,000,000,000,	000,000,000,000,000,000,000,000,	000,000,000,000,000,000,000,000,	000,'|',000,'#',000,000,000,'`',	'{','}',000,000,000,000,000,000,	000,000,000,000,000,000,000,000,	000,000,000,000,000,000,000,000,	'@',000,000,000,000,000,000,000,	000,000,000,000,000,000,000,000,	000,000,000,000,000,000,000,000,	000,000,000,000,000,000,'~',000,	000,'A','B','C','D','E','F','G',	'H','I','J','K','L','M','N','O',	'P','Q','R','S','T','U','V','W',	'X','Y','Z',000,000,000,000,000,};/* * 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;};/* * The routine implementing the gtty system call. * Just call lower level routine and pass back values. */gtty(){	int v[3];	register *up, *vp;	vp = v;	sgtty(vp);	if (u.u_error)		return;	up = u.u_arg[0];	suword(up, *vp++);	suword(++up, *vp++);	suword(++up, *vp++);}/* * The routine implementing the stty system call. * Read in values and call lower level. */stty(){	register int *up;	up = u.u_arg[0];	u.u_arg[0] = fuword(up);	u.u_arg[1] = fuword(++up);	u.u_arg[2] = fuword(++up);	sgtty(0);}/* * Stuff common to stty and gtty. * Check legality and switch out to individual * device routine. * v  is 0 for stty; the parameters are taken from u.u_arg[]. * c  is non-zero for gtty and is the place in which the device * routines place their information. */sgtty(v)int *v;{	register struct file *fp;	register struct inode *ip;	if ((fp = getf(u.u_ar0[R0])) == NULL)		return;	ip = fp->f_inode;	if ((ip->i_mode&IFMT) != IFCHR) {		u.u_error = ENOTTY;		return;	}	(*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v);}/* * Wait for output to drain, then flush input waiting. */wflushtty(atp)struct tty *atp;{	register struct tty *tp;	tp = atp;	spl5();	while (tp->t_outq.c_cc) {		tp->t_state =| ASLEEP;		sleep(&tp->t_outq, TTOPRI);	}	flushtty(tp);	spl0();}/* * Initialize clist by freeing all character blocks, then count * number of character devices. (Once-only routine) */cinit(){	register int ccp;	register struct cblock *cp;	register struct cdevsw *cdp;	ccp = cfree;	for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) {		cp->c_next = cfreelist;		cfreelist = cp;	}	ccp = 0;	for(cdp = cdevsw; cdp->d_open; cdp++)		ccp++;	nchrdev = ccp;}/* * flush all TTY queues */flushtty(atp)struct tty *atp;{	register struct tty *tp;	register int sps;	tp = atp;	while (getc(&tp->t_canq) >= 0);	while (getc(&tp->t_outq) >= 0);	wakeup(&tp->t_rawq);	wakeup(&tp->t_outq);	sps = PS->integ;	spl5();	while (getc(&tp->t_rawq) >= 0);	tp->t_delct = 0;	PS->integ = sps;}/* * 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;	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--;			break;		}		if ((tp->t_flags&RAW)==0) {			if (bp[-1]!='\\') {				if (c==tp->t_erase) {					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];	c = &tp->t_canq;	while (bp<bp1)		putc(*bp++, c);	return(1);}/* * 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;	tp = atp;	c = ac;	t_flags = tp->t_flags;	if ((c =& 0177) == '\r' && t_flags&CRMOD)		c = '\n';	if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) {		signal(tp, c==CINTR? SIGINT:SIGQIT);		flushtty(tp);		return;	}	if (tp->t_rawq.c_cc>=TTYHOG) {		flushtty(tp);		return;	}	if (t_flags&LCASE && c>='A' && c<='Z')		c =+ 'a'-'A';	putc(c, &tp->t_rawq);	if (t_flags&RAW || c=='\n' || c==004) {		wakeup(&tp->t_rawq);		if (putc(0377, &tp->t_rawq)==0)			tp->t_delct++;	}	if (t_flags&ECHO) {		ttyoutput(c, tp);		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. */ttyoutput(ac, tp)struct tty *tp;{	register int c;	register struct tty *rtp;	register char *colp;	int ctype;	rtp = tp;	c = ac&0177;	/*	 * Ignore EOT in normal mode to avoid hanging up	 * certain terminals.	 */	if (c==004 && (rtp->t_flags&RAW)==0)		return;	/*	 * Turn tabs to spaces as required	 */	if (c=='\t' && rtp->t_flags&XTABS) {		do			ttyoutput(' ', rtp);		while (rtp->t_col&07);		return;	}	/*	 * for upper-case-only terminals,	 * generate escapes.	 */	if (rtp->t_flags&LCASE) {		colp = "({)}!|^~'`";		while(*colp++)			if(c == *colp++) {				ttyoutput('\\', rtp);				c = colp[-2];				break;			}		if ('a'<=c && c<='z')			c =+ 'A' - 'a';	}	/*	 * turn <nl> to <cr><lf> if desired.	 */	if (c=='\n' && rtp->t_flags&CRMOD)		ttyoutput('\r', rtp);	if (putc(c, &rtp->t_outq))		return;	/*	 * Calculate delays.	 * The numbers here represent clock ticks	 * and are not necessarily optimal for all terminals.	 * The delays are indicated by characters above 0200,	 * thus (unfortunately) restricting the transmission	 * path to 7 bits.	 */	colp = &rtp->t_col;	ctype = partab[c];	c = 0;	switch (ctype&077) {	/* ordinary */	case 0:		(*colp)++;	/* non-printing */	case 1:		break;	/* backspace */	case 2:		if (*colp)			(*colp)--;		break;	/* newline */	case 3:		ctype = (rtp->t_flags >> 8) & 03;		if(ctype == 1) { /* tty 37 */			if (*colp)				c = max((*colp>>4) + 3, 6);		} else		if(ctype == 2) { /* vt05 */			c = 6;		}		*colp = 0;		break;	/* tab */	case 4:		ctype = (rtp->t_flags >> 10) & 03;		if(ctype == 1) { /* tty 37 */			c = 1 - (*colp | ~07);			if(c < 5)				c = 0;		}		*colp =| 07;		(*colp)++;		break;	/* vertical motion */	case 5:		if(rtp->t_flags & VTDELAY) /* tty 37 */			c = 0177;		break;	/* carriage return */	case 6:		ctype = (rtp->t_flags >> 12) & 03;		if(ctype == 1) { /* tn 300 */			c = 5;		} else		if(ctype == 2) { /* ti 700 */			c = 10;		}		*colp = 0;	}	if(c)		putc(c|0200, &rtp->t_outq);}/* * Restart typewriter output following a delay * timeout. * The name of the routine is passed to the timeout * subroutine and it is called during a clock interrupt. */ttrstrt(atp){	register struct tty *tp;	tp = atp;	tp->t_state =& ~TIMEOUT;	ttstart(tp);}/* * Start output on the typewriter. It is used from the top half * after some characters have been put on the output queue, * from the interrupt routine to transmit the next * character, and after a timeout has finished. * If the SSTART bit is off for the tty the work is done here, * using the protocol of the single-line interfaces (KL, DL, DC); * otherwise the address word of the tty structure is * taken to be the name of the device-dependent startup routine. */ttstart(atp)struct tty *atp;{	register int *addr, c;	register struct tty *tp;	struct { int (*func)(); };	tp = atp;	addr = tp->t_addr;	if (tp->t_state&SSTART) {		(*addr.func)(tp);		return;	}	if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT)		return;	if ((c=getc(&tp->t_outq)) >= 0) {		if (c<=0177)			addr->tttbuf = c | (partab[c]&0200);		else {			timeout(ttrstrt, tp, c&0177);			tp->t_state =| TIMEOUT;		}	}}/* * Called from device's read routine after it has * calculated the tty-structure given as argument. * The pc is backed up for the duration of this call. * In case of a caught interrupt, an RTI will re-execute. */ttread(atp)struct tty *atp;{	register struct tty *tp;	tp = atp;	if ((tp->t_state&CARR_ON)==0)		return;	if (tp->t_canq.c_cc || canon(tp))		while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0);}/* * Called from the device's write routine after it has * calculated the tty-structure given as argument. */ttwrite(atp)struct tty *atp;{	register struct tty *tp;	register int c;	tp = atp;	if ((tp->t_state&CARR_ON)==0)		return;	while ((c=cpass())>=0) {		spl5();		while (tp->t_outq.c_cc > TTHIWAT) {			ttstart(tp);			tp->t_state =| ASLEEP;			sleep(&tp->t_outq, TTOPRI);		}		spl0();		ttyoutput(c, tp);	}	ttstart(tp);}/* * Common code for gtty and stty functions on typewriters. * If v is non-zero then gtty is being done and information is * passed back therein; * if it is zero stty is being done and the input information is in the * u_arg array. */ttystty(atp, av)int *atp, *av;{	register  *tp, *v;	tp = atp;	if(v = av) {		*v++ = tp->t_speeds;		v->lobyte = tp->t_erase;		v->hibyte = tp->t_kill;		v[1] = tp->t_flags;		return(1);	}	wflushtty(tp);	v = u.u_arg;	tp->t_speeds = *v++;	tp->t_erase = v->lobyte;	tp->t_kill = v->hibyte;	tp->t_flags = v[1];	return(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -