欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

n_tty.c

linux 内核源代码
C
第 1 页 / 共 3 页
字号:
				unsigned long tail = tty->canon_head;				/* Find the column of the last char. */				while (tail != tty->read_head) {					c = tty->read_buf[tail];					if (c == '\t')						col = (col | 7) + 1;					else if (iscntrl(c)) {						if (L_ECHOCTL(tty))							col += 2;					} else if (!is_continuation(c, tty))						col++;					tail = (tail+1) & (N_TTY_BUF_SIZE-1);				}				/* should never happen */				if (tty->column > 0x80000000)					tty->column = 0; 				/* Now backup to that column. */				while (tty->column > col) {					/* Can't use opost here. */					put_char('\b', tty);					if (tty->column > 0)						tty->column--;				}			} else {				if (iscntrl(c) && L_ECHOCTL(tty)) {					put_char('\b', tty);					put_char(' ', tty);					put_char('\b', tty);					if (tty->column > 0)						tty->column--;				}				if (!iscntrl(c) || L_ECHOCTL(tty)) {					put_char('\b', tty);					put_char(' ', tty);					put_char('\b', tty);					if (tty->column > 0)						tty->column--;				}			}		}		if (kill_type == ERASE)			break;	}	if (tty->read_head == tty->canon_head)		finish_erasing(tty);}/** *	isig		-	handle the ISIG optio *	@sig: signal *	@tty: terminal *	@flush: force flush * *	Called when a signal is being sent due to terminal input. This *	may caus terminal flushing to take place according to the termios *	settings and character used. Called from the driver receive_buf *	path so serialized. */ static inline void isig(int sig, struct tty_struct *tty, int flush){	if (tty->pgrp)		kill_pgrp(tty->pgrp, sig, 1);	if (flush || !L_NOFLSH(tty)) {		n_tty_flush_buffer(tty);		if (tty->driver->flush_buffer)			tty->driver->flush_buffer(tty);	}}/** *	n_tty_receive_break	-	handle break *	@tty: terminal * *	An RS232 break event has been hit in the incoming bitstream. This *	can cause a variety of events depending upon the termios settings. * *	Called from the receive_buf path so single threaded. */ static inline void n_tty_receive_break(struct tty_struct *tty){	if (I_IGNBRK(tty))		return;	if (I_BRKINT(tty)) {		isig(SIGINT, tty, 1);		return;	}	if (I_PARMRK(tty)) {		put_tty_queue('\377', tty);		put_tty_queue('\0', tty);	}	put_tty_queue('\0', tty);	wake_up_interruptible(&tty->read_wait);}/** *	n_tty_receive_overrun	-	handle overrun reporting *	@tty: terminal * *	Data arrived faster than we could process it. While the tty *	driver has flagged this the bits that were missed are gone *	forever. * *	Called from the receive_buf path so single threaded. Does not *	need locking as num_overrun and overrun_time are function *	private. */ static inline void n_tty_receive_overrun(struct tty_struct *tty){	char buf[64];	tty->num_overrun++;	if (time_before(tty->overrun_time, jiffies - HZ) ||			time_after(tty->overrun_time, jiffies)) {		printk(KERN_WARNING "%s: %d input overrun(s)\n",			tty_name(tty, buf),			tty->num_overrun);		tty->overrun_time = jiffies;		tty->num_overrun = 0;	}}/** *	n_tty_receive_parity_error	-	error notifier *	@tty: terminal device *	@c: character * *	Process a parity error and queue the right data to indicate *	the error case if necessary. Locking as per n_tty_receive_buf. */static inline void n_tty_receive_parity_error(struct tty_struct *tty,					      unsigned char c){	if (I_IGNPAR(tty)) {		return;	}	if (I_PARMRK(tty)) {		put_tty_queue('\377', tty);		put_tty_queue('\0', tty);		put_tty_queue(c, tty);	} else	if (I_INPCK(tty))		put_tty_queue('\0', tty);	else		put_tty_queue(c, tty);	wake_up_interruptible(&tty->read_wait);}/** *	n_tty_receive_char	-	perform processing *	@tty: terminal device *	@c: character * *	Process an individual character of input received from the driver. *	This is serialized with respect to itself by the rules for the  *	driver above. */static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c){	unsigned long flags;	if (tty->raw) {		put_tty_queue(c, tty);		return;	}		if (tty->stopped && !tty->flow_stopped &&	    I_IXON(tty) && I_IXANY(tty)) {		start_tty(tty);		return;	}		if (I_ISTRIP(tty))		c &= 0x7f;	if (I_IUCLC(tty) && L_IEXTEN(tty))		c=tolower(c);	if (tty->closing) {		if (I_IXON(tty)) {			if (c == START_CHAR(tty))				start_tty(tty);			else if (c == STOP_CHAR(tty))				stop_tty(tty);		}		return;	}	/*	 * If the previous character was LNEXT, or we know that this	 * character is not one of the characters that we'll have to	 * handle specially, do shortcut processing to speed things	 * up.	 */	if (!test_bit(c, tty->process_char_map) || tty->lnext) {		finish_erasing(tty);		tty->lnext = 0;		if (L_ECHO(tty)) {			if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {				put_char('\a', tty); /* beep if no space */				return;			}			/* Record the column of first canon char. */			if (tty->canon_head == tty->read_head)				tty->canon_column = tty->column;			echo_char(c, tty);		}		if (I_PARMRK(tty) && c == (unsigned char) '\377')			put_tty_queue(c, tty);		put_tty_queue(c, tty);		return;	}			if (c == '\r') {		if (I_IGNCR(tty))			return;		if (I_ICRNL(tty))			c = '\n';	} else if (c == '\n' && I_INLCR(tty))		c = '\r';	if (I_IXON(tty)) {		if (c == START_CHAR(tty)) {			start_tty(tty);			return;		}		if (c == STOP_CHAR(tty)) {			stop_tty(tty);			return;		}	}	if (L_ISIG(tty)) {		int signal;		signal = SIGINT;		if (c == INTR_CHAR(tty))			goto send_signal;		signal = SIGQUIT;		if (c == QUIT_CHAR(tty))			goto send_signal;		signal = SIGTSTP;		if (c == SUSP_CHAR(tty)) {send_signal:			isig(signal, tty, 0);			return;		}	}	if (tty->icanon) {		if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||		    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {			eraser(c, tty);			return;		}		if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {			tty->lnext = 1;			if (L_ECHO(tty)) {				finish_erasing(tty);				if (L_ECHOCTL(tty)) {					put_char('^', tty);					put_char('\b', tty);				}			}			return;		}		if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&		    L_IEXTEN(tty)) {			unsigned long tail = tty->canon_head;			finish_erasing(tty);			echo_char(c, tty);			opost('\n', tty);			while (tail != tty->read_head) {				echo_char(tty->read_buf[tail], tty);				tail = (tail+1) & (N_TTY_BUF_SIZE-1);			}			return;		}		if (c == '\n') {			if (L_ECHO(tty) || L_ECHONL(tty)) {				if (tty->read_cnt >= N_TTY_BUF_SIZE-1)					put_char('\a', tty);				opost('\n', tty);			}			goto handle_newline;		}		if (c == EOF_CHAR(tty)) {		        if (tty->canon_head != tty->read_head)			        set_bit(TTY_PUSH, &tty->flags);			c = __DISABLED_CHAR;			goto handle_newline;		}		if ((c == EOL_CHAR(tty)) ||		    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {			/*			 * XXX are EOL_CHAR and EOL2_CHAR echoed?!?			 */			if (L_ECHO(tty)) {				if (tty->read_cnt >= N_TTY_BUF_SIZE-1)					put_char('\a', tty);				/* Record the column of first canon char. */				if (tty->canon_head == tty->read_head)					tty->canon_column = tty->column;				echo_char(c, tty);			}			/*			 * XXX does PARMRK doubling happen for			 * EOL_CHAR and EOL2_CHAR?			 */			if (I_PARMRK(tty) && c == (unsigned char) '\377')				put_tty_queue(c, tty);		handle_newline:			spin_lock_irqsave(&tty->read_lock, flags);			set_bit(tty->read_head, tty->read_flags);			put_tty_queue_nolock(c, tty);			tty->canon_head = tty->read_head;			tty->canon_data++;			spin_unlock_irqrestore(&tty->read_lock, flags);			kill_fasync(&tty->fasync, SIGIO, POLL_IN);			if (waitqueue_active(&tty->read_wait))				wake_up_interruptible(&tty->read_wait);			return;		}	}		finish_erasing(tty);	if (L_ECHO(tty)) {		if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {			put_char('\a', tty); /* beep if no space */			return;		}		if (c == '\n')			opost('\n', tty);		else {			/* Record the column of first canon char. */			if (tty->canon_head == tty->read_head)				tty->canon_column = tty->column;			echo_char(c, tty);		}	}	if (I_PARMRK(tty) && c == (unsigned char) '\377')		put_tty_queue(c, tty);	put_tty_queue(c, tty);}	/** *	n_tty_write_wakeup	-	asynchronous I/O notifier *	@tty: tty device * *	Required for the ptys, serial driver etc. since processes *	that attach themselves to the master and rely on ASYNC *	IO must be woken up */static void n_tty_write_wakeup(struct tty_struct *tty){	if (tty->fasync)	{ 		set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);		kill_fasync(&tty->fasync, SIGIO, POLL_OUT);	}	return;}/** *	n_tty_receive_buf	-	data receive *	@tty: terminal device *	@cp: buffer *	@fp: flag buffer *	@count: characters * *	Called by the terminal driver when a block of characters has *	been received. This function must be called from soft contexts *	not from interrupt context. The driver is responsible for making *	calls one at a time and in order (or using flush_to_ldisc) */ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,			      char *fp, int count){	const unsigned char *p;	char *f, flags = TTY_NORMAL;	int	i;	char	buf[64];	unsigned long cpuflags;	if (!tty->read_buf)		return;	if (tty->real_raw) {		spin_lock_irqsave(&tty->read_lock, cpuflags);		i = min(N_TTY_BUF_SIZE - tty->read_cnt,			N_TTY_BUF_SIZE - tty->read_head);		i = min(count, i);		memcpy(tty->read_buf + tty->read_head, cp, i);		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);		tty->read_cnt += i;		cp += i;		count -= i;		i = min(N_TTY_BUF_SIZE - tty->read_cnt,			N_TTY_BUF_SIZE - tty->read_head);		i = min(count, i);		memcpy(tty->read_buf + tty->read_head, cp, i);		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);		tty->read_cnt += i;		spin_unlock_irqrestore(&tty->read_lock, cpuflags);	} else {		for (i=count, p = cp, f = fp; i; i--, p++) {			if (f)				flags = *f++;			switch (flags) {			case TTY_NORMAL:				n_tty_receive_char(tty, *p);				break;			case TTY_BREAK:				n_tty_receive_break(tty);				break;			case TTY_PARITY:			case TTY_FRAME:				n_tty_receive_parity_error(tty, *p);				break;			case TTY_OVERRUN:				n_tty_receive_overrun(tty);				break;			default:				printk("%s: unknown flag %d\n",				       tty_name(tty, buf), flags);				break;			}		}		if (tty->driver->flush_chars)			tty->driver->flush_chars(tty);	}	n_tty_set_room(tty);	if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {		kill_fasync(&tty->fasync, SIGIO, POLL_IN);		if (waitqueue_active(&tty->read_wait))			wake_up_interruptible(&tty->read_wait);	}	/*	 * Check the remaining room for the input canonicalization	 * mode.  We don't want to throttle the driver if we're in	 * canonical mode and don't have a newline yet!	 */	if (tty->receive_room < TTY_THRESHOLD_THROTTLE) {		/* check TTY_THROTTLED first so it indicates our state */		if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&		    tty->driver->throttle)			tty->driver->throttle(tty);	}}int is_ignored(int sig){	return (sigismember(&current->blocked, sig) ||	        current->sighand->action[sig-1].sa.sa_handler == SIG_IGN);}/** *	n_tty_set_termios	-	termios data changed *	@tty: terminal *	@old: previous data * *	Called by the tty layer when the user changes termios flags so *	that the line discipline can plan ahead. This function cannot sleep *	and is protected from re-entry by the tty layer. The user is  *	guaranteed that this function will not be re-entered or in progress *	when the ldisc is closed. */ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios * old){	if (!tty)		return;		tty->icanon = (L_ICANON(tty) != 0);	if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {		tty->raw = 1;		tty->real_raw = 1;		n_tty_set_room(tty);		return;	}	if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||	    I_PARMRK(tty)) {		memset(tty->process_char_map, 0, 256/8);		if (I_IGNCR(tty) || I_ICRNL(tty))			set_bit('\r', tty->process_char_map);		if (I_INLCR(tty))			set_bit('\n', tty->process_char_map);		if (L_ICANON(tty)) {			set_bit(ERASE_CHAR(tty), tty->process_char_map);			set_bit(KILL_CHAR(tty), tty->process_char_map);			set_bit(EOF_CHAR(tty), tty->process_char_map);			set_bit('\n', tty->process_char_map);			set_bit(EOL_CHAR(tty), tty->process_char_map);			if (L_IEXTEN(tty)) {				set_bit(WERASE_CHAR(tty),					tty->process_char_map);				set_bit(LNEXT_CHAR(tty),					tty->process_char_map);				set_bit(EOL2_CHAR(tty),					tty->process_char_map);				if (L_ECHO(tty))					set_bit(REPRINT_CHAR(tty),						tty->process_char_map);			}		}		if (I_IXON(tty)) {			set_bit(START_CHAR(tty), tty->process_char_map);			set_bit(STOP_CHAR(tty), tty->process_char_map);		}		if (L_ISIG(tty)) {			set_bit(INTR_CHAR(tty), tty->process_char_map);

⌨️ 快捷键说明

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