📄 tty_io.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 + -