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

📄 tty_io.c

📁 最早的linux操作系统源代码(3)
💻 C
字号:
/* * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles * or rs-channels. It also implements echoing, cooked mode etc (well, * not currently, but ...) */#include <ctype.h>#include <errno.h>#include <signal.h>#define ALRMMASK (1<<(SIGALRM-1))#include <linux/sched.h>#include <linux/tty.h>#include <asm/segment.h>#include <asm/system.h>#define _L_FLAG(tty,f)	((tty)->termios.c_lflag & f)#define _I_FLAG(tty,f)	((tty)->termios.c_iflag & f)#define _O_FLAG(tty,f)	((tty)->termios.c_oflag & f)#define L_CANON(tty)	_L_FLAG((tty),ICANON)#define L_ISIG(tty)	_L_FLAG((tty),ISIG)#define L_ECHO(tty)	_L_FLAG((tty),ECHO)#define L_ECHOE(tty)	_L_FLAG((tty),ECHOE)#define L_ECHOK(tty)	_L_FLAG((tty),ECHOK)#define L_ECHOCTL(tty)	_L_FLAG((tty),ECHOCTL)#define L_ECHOKE(tty)	_L_FLAG((tty),ECHOKE)#define I_UCLC(tty)	_I_FLAG((tty),IUCLC)#define I_NLCR(tty)	_I_FLAG((tty),INLCR)#define I_CRNL(tty)	_I_FLAG((tty),ICRNL)#define I_NOCR(tty)	_I_FLAG((tty),IGNCR)#define O_POST(tty)	_O_FLAG((tty),OPOST)#define O_NLCR(tty)	_O_FLAG((tty),ONLCR)#define O_CRNL(tty)	_O_FLAG((tty),OCRNL)#define O_NLRET(tty)	_O_FLAG((tty),ONLRET)#define O_LCUC(tty)	_O_FLAG((tty),OLCUC)struct tty_struct tty_table[] = {	{		{0,		OPOST|ONLCR,	/* change outgoing NL to CRNL */		0,		ICANON | ECHO | ECHOCTL | ECHOKE,		0,		/* console termio */		INIT_C_CC},		0,			/* initial pgrp */		0,			/* initial stopped */		con_write,		{0,0,0,0,""},		/* console read-queue */		{0,0,0,0,""},		/* console write-queue */		{0,0,0,0,""}		/* console secondary queue */	},{		{0, /*IGNCR*/		OPOST | ONLRET,		/* change outgoing NL to CR */		B2400 | CS8,		0,		0,		INIT_C_CC},		0,		0,		rs_write,		{0x3f8,0,0,0,""},		/* rs 1 */		{0x3f8,0,0,0,""},		{0,0,0,0,""}	},{		{0, /*IGNCR*/		OPOST | ONLRET,		/* change outgoing NL to CR */		B2400 | CS8,		0,		0,		INIT_C_CC},		0,		0,		rs_write,		{0x2f8,0,0,0,""},		/* rs 2 */		{0x2f8,0,0,0,""},		{0,0,0,0,""}	}};/* * these are the tables used by the machine code handlers. * you can implement pseudo-tty's or something by changing * them. Currently not done. */struct tty_queue * table_list[]={	&tty_table[0].read_q, &tty_table[0].write_q,	&tty_table[1].read_q, &tty_table[1].write_q,	&tty_table[2].read_q, &tty_table[2].write_q	};void tty_init(void){	rs_init();	con_init();}void tty_intr(struct tty_struct * tty, int signal){	int i;	if (tty->pgrp <= 0)		return;	for (i=0;i<NR_TASKS;i++)		if (task[i] && task[i]->pgrp==tty->pgrp)			task[i]->signal |= 1<<(signal-1);}static void sleep_if_empty(struct tty_queue * queue){	cli();	while (!current->signal && EMPTY(*queue))		interruptible_sleep_on(&queue->proc_list);	sti();}static void sleep_if_full(struct tty_queue * queue){	if (!FULL(*queue))		return;	cli();	while (!current->signal && LEFT(*queue)<128)		interruptible_sleep_on(&queue->proc_list);	sti();}void copy_to_cooked(struct tty_struct * tty){	signed char c;	while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {		GETCH(tty->read_q,c);		if (c==13)			if (I_CRNL(tty))				c=10;			else if (I_NOCR(tty))				continue;			else ;		else if (c==10 && I_NLCR(tty))			c=13;		if (I_UCLC(tty))			c=tolower(c);		if (L_CANON(tty)) {			if (c==ERASE_CHAR(tty)) {				if (EMPTY(tty->secondary) ||				   (c=LAST(tty->secondary))==10 ||				   c==EOF_CHAR(tty))					continue;				if (L_ECHO(tty)) {					if (c<32)						PUTCH(127,tty->write_q);					PUTCH(127,tty->write_q);					tty->write(tty);				}				DEC(tty->secondary.head);				continue;			}			if (c==STOP_CHAR(tty)) {				tty->stopped=1;				continue;			}			if (c==START_CHAR(tty)) {				tty->stopped=0;				continue;			}		}		if (!L_ISIG(tty)) {			if (c==INTR_CHAR(tty)) {				tty_intr(tty,SIGINT);				continue;			}		}		if (c==10 || c==EOF_CHAR(tty))			tty->secondary.data++;		if (L_ECHO(tty)) {			if (c==10) {				PUTCH(10,tty->write_q);				PUTCH(13,tty->write_q);			} else if (c<32) {				if (L_ECHOCTL(tty)) {					PUTCH('^',tty->write_q);					PUTCH(c+64,tty->write_q);				}			} else				PUTCH(c,tty->write_q);			tty->write(tty);		}		PUTCH(c,tty->secondary);	}	wake_up(&tty->secondary.proc_list);}int tty_read(unsigned channel, char * buf, int nr){	struct tty_struct * tty;	char c, * b=buf;	int minimum,time,flag=0;	long oldalarm;	if (channel>2 || nr<0) return -1;	tty = &tty_table[channel];	oldalarm = current->alarm;	time = (unsigned) 10*tty->termios.c_cc[VTIME];	minimum = (unsigned) tty->termios.c_cc[VMIN];	if (time && !minimum) {		minimum=1;		if (flag=(!oldalarm || time+jiffies<oldalarm))			current->alarm = time+jiffies;	}	if (minimum>nr)		minimum=nr;	while (nr>0) {		if (flag && (current->signal & ALRMMASK)) {			current->signal &= ~ALRMMASK;			break;		}		if (current->signal)			break;		if (EMPTY(tty->secondary) || (L_CANON(tty) &&		!tty->secondary.data && LEFT(tty->secondary)>20)) {			sleep_if_empty(&tty->secondary);			continue;		}		do {			GETCH(tty->secondary,c);			if (c==EOF_CHAR(tty) || c==10)				tty->secondary.data--;			if (c==EOF_CHAR(tty) && L_CANON(tty))				return (b-buf);			else {				put_fs_byte(c,b++);				if (!--nr)					break;			}		} while (nr>0 && !EMPTY(tty->secondary));		if (time && !L_CANON(tty))			if (flag=(!oldalarm || time+jiffies<oldalarm))				current->alarm = time+jiffies;			else				current->alarm = oldalarm;		if (L_CANON(tty)) {			if (b-buf)				break;		} else if (b-buf >= minimum)			break;	}	current->alarm = oldalarm;	if (current->signal && !(b-buf))		return -EINTR;	return (b-buf);}int tty_write(unsigned channel, char * buf, int nr){	static cr_flag=0;	struct tty_struct * tty;	char c, *b=buf;	if (channel>2 || nr<0) return -1;	tty = channel + tty_table;	while (nr>0) {		sleep_if_full(&tty->write_q);		if (current->signal)			break;		while (nr>0 && !FULL(tty->write_q)) {			c=get_fs_byte(b);			if (O_POST(tty)) {				if (c=='\r' && O_CRNL(tty))					c='\n';				else if (c=='\n' && O_NLRET(tty))					c='\r';				if (c=='\n' && !cr_flag && O_NLCR(tty)) {					cr_flag = 1;					PUTCH(13,tty->write_q);					continue;				}				if (O_LCUC(tty))					c=toupper(c);			}			b++; nr--;			cr_flag = 0;			PUTCH(c,tty->write_q);		}		tty->write(tty);		if (nr>0)			schedule();	}	return (b-buf);}/* * Jeh, sometimes I really like the 386. * This routine is called from an interrupt, * and there should be absolutely no problem * with sleeping even in an interrupt (I hope). * Of course, if somebody proves me wrong, I'll * hate intel for all time :-). We'll have to * be careful and see to reinstating the interrupt * chips before calling this, though. */void do_tty_interrupt(int tty){	copy_to_cooked(tty_table+tty);}/*void os_shell(){      unsigned char a;            a=keybuf;      printk(" %x ",a);}*/

⌨️ 快捷键说明

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