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

📄 tty.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 4 页
字号:
		/* Previous character was a character escape? */		if (tp->tty_escaped) {			tp->tty_escaped = NOT_ESCAPED;			ch |= IN_ESC;	/* protect character */		}		/* LNEXT (^V) to escape the next character? */		if (ch == tp->tty_termios.c_cc[VLNEXT]) {			tp->tty_escaped = ESCAPED;			rawecho(tp, '^');			rawecho(tp, '\b');			continue;	/* do not store the escape */		}		/* REPRINT (^R) to reprint echoed characters? */		if (ch == tp->tty_termios.c_cc[VREPRINT]) {			reprint(tp);			continue;		}	}	/* _POSIX_VDISABLE is a normal character value, so better escape it. */	if (ch == _POSIX_VDISABLE) ch |= IN_ESC;	/* Map CR to LF, ignore CR, or map LF to CR. */	if (ch == '\r') {		if (tp->tty_termios.c_iflag & IGNCR) continue;		if (tp->tty_termios.c_iflag & ICRNL) ch = '\n';	} else	if (ch == '\n') {		if (tp->tty_termios.c_iflag & INLCR) ch = '\r';	}	/* Canonical mode? */	if (tp->tty_termios.c_lflag & ICANON) {		/* Erase processing (rub out of last character). */		if (ch == tp->tty_termios.c_cc[VERASE]) {			(void) back_over(tp);			if (!(tp->tty_termios.c_lflag & ECHOE)) {				(void) tty_echo(tp, ch);			}			continue;		}		/* Kill processing (remove current line). */		if (ch == tp->tty_termios.c_cc[VKILL]) {			while (back_over(tp)) {}			if (!(tp->tty_termios.c_lflag & ECHOE)) {				(void) tty_echo(tp, ch);				if (tp->tty_termios.c_lflag & ECHOK)					rawecho(tp, '\n');			}			continue;		}		/* EOF (^D) means end-of-file, an invisible "line break". */		if (ch == tp->tty_termios.c_cc[VEOF]) ch |= IN_EOT | IN_EOF;		/* The line may be returned to the user after an LF. */		if (ch == '\n') ch |= IN_EOT;		/* Same thing with EOL, whatever it may be. */		if (ch == tp->tty_termios.c_cc[VEOL]) ch |= IN_EOT;	}	/* Start/stop input control? */	if (tp->tty_termios.c_iflag & IXON) {		/* Output stops on STOP (^S). */		if (ch == tp->tty_termios.c_cc[VSTOP]) {			tp->tty_inhibited = STOPPED;			tp->tty_events = 1;			continue;		}		/* Output restarts on START (^Q) or any character if IXANY. */		if (tp->tty_inhibited) {			if (ch == tp->tty_termios.c_cc[VSTART]					|| (tp->tty_termios.c_iflag & IXANY)) {				tp->tty_inhibited = RUNNING;				tp->tty_events = 1;				if (ch == tp->tty_termios.c_cc[VSTART])					continue;			}		}	}	if (tp->tty_termios.c_lflag & ISIG) {		/* Check for INTR (^?) and QUIT (^\) characters. */		if (ch == tp->tty_termios.c_cc[VINTR]					|| ch == tp->tty_termios.c_cc[VQUIT]) {			sig = SIGINT;			if (ch == tp->tty_termios.c_cc[VQUIT]) sig = SIGQUIT;			sigchar(tp, sig);			(void) tty_echo(tp, ch);			continue;		}	}	/* Is there space in the input buffer? */	if (tp->tty_incount == buflen(tp->tty_inbuf)) {		/* No space; discard in canonical mode, keep in raw mode. */		if (tp->tty_termios.c_lflag & ICANON) continue;		break;	}	if (!(tp->tty_termios.c_lflag & ICANON)) {		/* In raw mode all characters are "line breaks". */		ch |= IN_EOT;		/* Start an inter-byte timer? */		if (!timeset && tp->tty_termios.c_cc[VMIN] > 0				&& tp->tty_termios.c_cc[VTIME] > 0) {			settimer(tp, TRUE);			timeset = TRUE;		}	}	/* Perform the intricate function of echoing. */	if (tp->tty_termios.c_lflag & (ECHO|ECHONL)) ch = tty_echo(tp, ch);	/* Save the character in the input queue. */	*tp->tty_inhead++ = ch;	if (tp->tty_inhead == bufend(tp->tty_inbuf))		tp->tty_inhead = tp->tty_inbuf;	tp->tty_incount++;	if (ch & IN_EOT) tp->tty_eotct++;	/* Try to finish input if the queue threatens to overflow. */	if (tp->tty_incount == buflen(tp->tty_inbuf)) in_transfer(tp);  }  return ct;}/*===========================================================================* *				echo					     * *===========================================================================*/PRIVATE int tty_echo(tp, ch)register tty_t *tp;		/* terminal on which to echo */register int ch;		/* pointer to character to echo */{/* Echo the character if echoing is on.  Some control characters are echoed * with their normal effect, other control characters are echoed as "^X", * normal characters are echoed normally.  EOF (^D) is echoed, but immediately * backspaced over.  Return the character with the echoed length added to its * attributes. */  int len, rp;  ch &= ~IN_LEN;  if (!(tp->tty_termios.c_lflag & ECHO)) {	if (ch == ('\n' | IN_EOT) && (tp->tty_termios.c_lflag					& (ICANON|ECHONL)) == (ICANON|ECHONL))		(*tp->tty_echo)(tp, '\n');	return(ch);  }  /* "Reprint" tells if the echo output has been messed up by other output. */  rp = tp->tty_incount == 0 ? FALSE : tp->tty_reprint;  if ((ch & IN_CHAR) < ' ') {	switch (ch & (IN_ESC|IN_EOF|IN_EOT|IN_CHAR)) {	    case '\t':		len = 0;		do {			(*tp->tty_echo)(tp, ' ');			len++;		} while (len < TAB_SIZE && (tp->tty_position & TAB_MASK) != 0);		break;	    case '\r' | IN_EOT:	    case '\n' | IN_EOT:		(*tp->tty_echo)(tp, ch & IN_CHAR);		len = 0;		break;	    default:		(*tp->tty_echo)(tp, '^');		(*tp->tty_echo)(tp, '@' + (ch & IN_CHAR));		len = 2;	}  } else  if ((ch & IN_CHAR) == '\177') {	/* A DEL prints as "^?". */	(*tp->tty_echo)(tp, '^');	(*tp->tty_echo)(tp, '?');	len = 2;  } else {	(*tp->tty_echo)(tp, ch & IN_CHAR);	len = 1;  }  if (ch & IN_EOF) while (len > 0) { (*tp->tty_echo)(tp, '\b'); len--; }  tp->tty_reprint = rp;  return(ch | (len << IN_LSHIFT));}/*===========================================================================* *				rawecho					     * *===========================================================================*/PRIVATE void rawecho(tp, ch)register tty_t *tp;int ch;{/* Echo without interpretation if ECHO is set. */  int rp = tp->tty_reprint;  if (tp->tty_termios.c_lflag & ECHO) (*tp->tty_echo)(tp, ch);  tp->tty_reprint = rp;}/*===========================================================================* *				back_over				     * *===========================================================================*/PRIVATE int back_over(tp)register tty_t *tp;{/* Backspace to previous character on screen and erase it. */  u16_t *head;  int len;  if (tp->tty_incount == 0) return(0);	/* queue empty */  head = tp->tty_inhead;  if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);  if (*--head & IN_EOT) return(0);		/* can't erase "line breaks" */  if (tp->tty_reprint) reprint(tp);		/* reprint if messed up */  tp->tty_inhead = head;  tp->tty_incount--;  if (tp->tty_termios.c_lflag & ECHOE) {	len = (*head & IN_LEN) >> IN_LSHIFT;	while (len > 0) {		rawecho(tp, '\b');		rawecho(tp, ' ');		rawecho(tp, '\b');		len--;	}  }  return(1);				/* one character erased */}/*===========================================================================* *				reprint					     * *===========================================================================*/PRIVATE void reprint(tp)register tty_t *tp;		/* pointer to tty struct */{/* Restore what has been echoed to screen before if the user input has been * messed up by output, or if REPRINT (^R) is typed. */  int count;  u16_t *head;  tp->tty_reprint = FALSE;  /* Find the last line break in the input. */  head = tp->tty_inhead;  count = tp->tty_incount;  while (count > 0) {	if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);	if (head[-1] & IN_EOT) break;	head--;	count--;  }  if (count == tp->tty_incount) return;		/* no reason to reprint */  /* Show REPRINT (^R) and move to a new line. */  (void) tty_echo(tp, tp->tty_termios.c_cc[VREPRINT] | IN_ESC);  rawecho(tp, '\r');  rawecho(tp, '\n');  /* Reprint from the last break onwards. */  do {	if (head == bufend(tp->tty_inbuf)) head = tp->tty_inbuf;	*head = tty_echo(tp, *head);	head++;	count++;  } while (count < tp->tty_incount);}/*===========================================================================* *				out_process				     * *===========================================================================*/PUBLIC void out_process(tp, bstart, bpos, bend, icount, ocount)tty_t *tp;char *bstart, *bpos, *bend;	/* start/pos/end of circular buffer */int *icount;			/* # input chars / input chars used */int *ocount;			/* max output chars / output chars used */{/* Perform output processing on a circular buffer.  *icount is the number of * bytes to process, and the number of bytes actually processed on return. * *ocount is the space available on input and the space used on output. * (Naturally *icount < *ocount.)  The column position is updated modulo * the TAB size, because we really only need it for tabs. */  int tablen;  int ict = *icount;  int oct = *ocount;  int pos = tp->tty_position;  while (ict > 0) {	switch (*bpos) {	case '\7':		break;	case '\b':		pos--;		break;	case '\r':		pos = 0;		break;	case '\n':		if ((tp->tty_termios.c_oflag & (OPOST|ONLCR))							== (OPOST|ONLCR)) {			/* Map LF to CR+LF if there is space.  Note that the			 * next character in the buffer is overwritten, so			 * we stop at this point.			 */			if (oct >= 2) {				*bpos = '\r';				if (++bpos == bend) bpos = bstart;				*bpos = '\n';				pos = 0;				ict--;				oct -= 2;			}			goto out_done;	/* no space or buffer got changed */		}		break;	case '\t':		/* Best guess for the tab length. */		tablen = TAB_SIZE - (pos & TAB_MASK);		if ((tp->tty_termios.c_oflag & (OPOST|XTABS))							== (OPOST|XTABS)) {			/* Tabs must be expanded. */			if (oct >= tablen) {				pos += tablen;				ict--;				oct -= tablen;				do {					*bpos = ' ';					if (++bpos == bend) bpos = bstart;				} while (--tablen != 0);			}			goto out_done;		}		/* Tabs are output directly. */		pos += tablen;		break;	default:		/* Assume any other character prints as one character. */		pos++;	}	if (++bpos == bend) bpos = bstart;	ict--;	oct--;  }out_done:  tp->tty_position = pos & TAB_MASK;  *icount -= ict;	/* [io]ct are the number of chars not used */  *ocount -= oct;	/* *[io]count are the number of chars that are used */}/*===========================================================================* *				dev_ioctl				     * *===========================================================================*/PRIVATE void dev_ioctl(tp)tty_t *tp;{/* The ioctl's TCSETSW, TCSETSF and TCDRAIN wait for output to finish to make * sure that an attribute change doesn't affect the processing of current * output.  Once output finishes the ioctl is executed as in do_ioctl(). */  int result;  if (tp->tty_outleft > 0) return;		/* output not finished */  if (tp->tty_ioreq != TCDRAIN) {	if (tp->tty_ioreq == TCSETSF) tty_icancel(tp);	result = sys_vircopy(tp->tty_ioproc, D, tp->tty_iovir,			SELF, D, (vir_bytes) &tp->tty_termios,			(vir_bytes) sizeof(tp->tty_termios));	setattr(tp);  }  tp->tty_ioreq = 0;  tty_reply(REVIVE, tp->tty_iocaller, tp->tty_ioproc, result);}/*===========================================================================* *				setattr					     * *===========================================================================*/PRIVATE void setattr(tp)tty_t *tp;{/* Apply the new line attributes (raw/canonical, line speed, etc.) */  u16_t *inp;  int count;  if (!(tp->tty_termios.c_lflag & ICANON)) {	/* Raw mode; put a "line break" on all characters in the input queue.	 * It is undefined what happens to the input queue when ICANON is	 * switched off, a process should use TCSAFLUSH to flush the queue.	 * Keeping the queue to preserve typeahead is the Right Thing, however	 * when a process does use TCSANOW to switch to raw mode.	 */	count = tp->tty_eotct = tp->tty_incount;	inp = tp->tty_intail;	while (count > 0) {		*inp |= IN_EOT;		if (++inp == bufend(tp->tty_inbuf)) inp = tp->tty_inbuf;		--count;	}  }  /* Inspect MIN and TIME. */  settimer(tp, FALSE);  if (tp->tty_termios.c_lflag & ICANON) {	/* No MIN & TIME in canonical mode. */	tp->tty_min = 1;  } else {	/* In raw mode MIN is the number of chars wanted, and TIME how long	 * to wait for them.  With interesting exceptions if either is zero.	 */	tp->tty_min = tp->tty_termios.c_cc[VMIN];	if (tp->tty_min == 0 && tp->tty_termios.c_cc[VTIME] > 0)		tp->tty_min = 1;  }  if (!(tp->tty_termios.c_iflag & IXON)) {	/* No start/stop output control, so don't leave output inhibited. */	tp->tty_inhibited = RUNNING;	tp->tty_events = 1;  }  /* Setting the output speed to zero hangs up the phone. */  if (tp->tty_termios.c_ospeed == B0) sigchar(tp, SIGHUP);  /* Set new line speed, character size, etc at the device level. */  (*tp->tty_ioctl)(tp, 0);}/*===========================================================================* *				tty_reply				     * *===========================================================================*/PUBLIC void tty_reply(code, replyee, proc_nr, status)int code;			/* TASK_REPLY or REVIVE */int replyee;			/* destination address for the reply */int proc_nr;			/* to whom should the reply go? */int status;			/* reply code */{/* Send a reply to a process that wanted to read or write data. */  message tty_mess;  tty_mess.m_type = code;  tty_mess.REP_PROC_NR = proc_nr;  tty_mess.REP_STATUS = status;  if ((status = send(replyee, &tty_mess)) != OK) {	panic("TTY","tty_reply failed, status\n", status);  }}/*===========================================================================* *				sigchar					     * *===========================================================================*/PUBLIC void sigchar(tp, sig)register tty_t *tp;int sig;			/* SIGINT, SIGQUIT, SIGKILL or SIGHUP */{/* Process a SIGINT, SIGQUIT or SIGKILL char from the keyboard or SIGHUP from * a tty close, "stty 0", or a real RS-232 hangup.  MM will send the signal to * the process group (INT, QUIT), all processes (KILL), or the session leader * (HUP). */  int status;  if (tp->tty_pgrp != 0)       if (OK != (status = sys_kill(tp->tty_pgrp, sig)))        panic("TTY","Error, call to sys_kill failed", status);  if (!(tp->tty_termios.c_lflag & NOFLSH)) {	tp->tty_incount = tp->tty_eotct = 0;	/* kill earlier input */	tp->tty_intail = tp->tty_inhead;	(*tp->tty_ocancel)(tp, 0);			/* kill all output */	tp->tty_inhibited = RUNNING;	tp->tty_events = 1;  }}/*===========================================================================* *				tty_icancel				     * *===========================================================================*/PRIVATE void tty_icancel(tp)register tty_t *tp;{/* Discard all pending input, tty buffer or device. */  tp->tty_incount = tp->tty_eotct = 0;  tp->tty_intail = tp->tty_inhead;  (*tp->tty_icancel)(tp, 0);

⌨️ 快捷键说明

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