?? tty_io.c
字號:
{ /* * It worked. Mark the vt to switch to and * return. The process needs to send us a * VT_RELDISP ioctl to complete the switch. */ vt_cons[fg_console].vt_newvt = new_console; return; } /* * The controlling process has died, so we revert back to * normal operation. In this case, we'll also change back * to KD_TEXT mode. I'm not sure if this is strictly correct * but it saves the agony when the X server dies and the screen * remains blanked due to KD_GRAPHICS! It would be nice to do * this outside of VT_PROCESS but there is no single process * to account for and tracking tty count may be undesirable. */ vt_cons[fg_console].vc_mode = KD_TEXT; clr_vc_kbd_mode(kbd_table + fg_console, VC_RAW); clr_vc_kbd_mode(kbd_table + fg_console, VC_MEDIUMRAW); vt_cons[fg_console].vt_mode.mode = VT_AUTO; vt_cons[fg_console].vt_mode.waitv = 0; vt_cons[fg_console].vt_mode.relsig = 0; vt_cons[fg_console].vt_mode.acqsig = 0; vt_cons[fg_console].vt_mode.frsig = 0; vt_cons[fg_console].vt_pid = -1; vt_cons[fg_console].vt_newvt = -1; /* * Fall through to normal (VT_AUTO) handling of the switch... */ } /* * Ignore all switches in KD_GRAPHICS+VT_AUTO mode */ if (vt_cons[fg_console].vc_mode == KD_GRAPHICS) return; complete_change_console(new_console);}void wait_for_keypress(void){ sleep_on(&keypress_wait);}void stop_tty(struct tty_struct *tty){ if (tty->stopped) return; tty->stopped = 1; if (tty->link && tty->link->packet) { tty->ctrl_status &= ~TIOCPKT_START; tty->ctrl_status |= TIOCPKT_STOP; wake_up_interruptible(&tty->link->secondary.proc_list); } if (tty->stop) (tty->stop)(tty); if (IS_A_CONSOLE(tty->line)) { set_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK); set_leds(); }}void start_tty(struct tty_struct *tty){ if (!tty->stopped) return; tty->stopped = 0; if (tty->link && tty->link->packet) { tty->ctrl_status &= ~TIOCPKT_STOP; tty->ctrl_status |= TIOCPKT_START; wake_up_interruptible(&tty->link->secondary.proc_list); } if (tty->start) (tty->start)(tty); TTY_WRITE_FLUSH(tty); if (IS_A_CONSOLE(tty->line)) { clr_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK); set_leds(); }}/* Perform OPOST processing. Returns -1 when the write_q becomes full and the character must be retried. */static int opost(unsigned char c, struct tty_struct *tty){ if (FULL(&tty->write_q)) return -1; if (O_OPOST(tty)) { switch (c) { case '\n': if (O_ONLRET(tty)) tty->column = 0; if (O_ONLCR(tty)) { if (LEFT(&tty->write_q) < 2) return -1; put_tty_queue('\r', &tty->write_q); tty->column = 0; } tty->canon_column = tty->column; break; case '\r': if (O_ONOCR(tty) && tty->column == 0) return 0; if (O_OCRNL(tty)) { c = '\n'; if (O_ONLRET(tty)) tty->canon_column = tty->column = 0; break; } tty->canon_column = tty->column = 0; break; case '\t': if (O_TABDLY(tty) == XTABS) { if (LEFT(&tty->write_q) < 8) return -1; do put_tty_queue(' ', &tty->write_q); while (++tty->column % 8); return 0; } tty->column = (tty->column | 7) + 1; break; case '\b': if (tty->column > 0) tty->column--; break; default: if (O_OLCUC(tty)) c = toupper(c); if (!iscntrl(c)) tty->column++; break; } } put_tty_queue(c, &tty->write_q); return 0;}/* Must be called only when L_ECHO(tty) is true. */static void echo_char(unsigned char c, struct tty_struct *tty){ if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') { opost('^', tty); opost(c ^ 0100, tty); } else opost(c, tty);}static void eraser(unsigned char c, struct tty_struct *tty){ enum { ERASE, WERASE, KILL } kill_type; int seen_alnums; if (tty->secondary.head == tty->canon_head) { /* opost('\a', tty); */ /* what do you think? */ return; } if (c == ERASE_CHAR(tty)) kill_type = ERASE; else if (c == WERASE_CHAR(tty)) kill_type = WERASE; else { if (!L_ECHO(tty)) { tty->secondary.head = tty->canon_head; return; } if (!L_ECHOK(tty) || !L_ECHOKE(tty)) { tty->secondary.head = tty->canon_head; if (tty->erasing) { opost('/', tty); tty->erasing = 0; } echo_char(KILL_CHAR(tty), tty); /* Add a newline if ECHOK is on and ECHOKE is off. */ if (L_ECHOK(tty)) opost('\n', tty); return; } kill_type = KILL; } seen_alnums = 0; while (tty->secondary.head != tty->canon_head) { c = LAST(&tty->secondary); if (kill_type == WERASE) { /* Equivalent to BSD's ALTWERASE. */ if (isalnum(c) || c == '_') seen_alnums++; else if (seen_alnums) break; } DEC(tty->secondary.head); if (L_ECHO(tty)) { if (L_ECHOPRT(tty)) { if (!tty->erasing) { opost('\\', tty); tty->erasing = 1; } echo_char(c, tty); } else if (!L_ECHOE(tty)) { echo_char(ERASE_CHAR(tty), tty); } else if (c == '\t') { unsigned int col = tty->canon_column; unsigned long tail = tty->canon_head; /* Find the column of the last char. */ while (tail != tty->secondary.head) { c = tty->secondary.buf[tail]; if (c == '\t') col = (col | 7) + 1; else if (iscntrl(c)) { if (L_ECHOCTL(tty)) col += 2; } else col++; INC(tail); } /* Now backup to that column. */ while (tty->column > col) { /* Can't use opost here. */ put_tty_queue('\b', &tty->write_q); tty->column--; } } else { if (iscntrl(c) && L_ECHOCTL(tty)) { opost('\b', tty); opost(' ', tty); opost('\b', tty); } if (!iscntrl(c) || L_ECHOCTL(tty)) { opost('\b', tty); opost(' ', tty); opost('\b', tty); } } } if (kill_type == ERASE) break; } if (tty->erasing && tty->secondary.head == tty->canon_head) { opost('/', tty); tty->erasing = 0; }}static void isig(int sig, struct tty_struct *tty){ kill_pg(tty->pgrp, sig, 1); if (!L_NOFLSH(tty)) { flush_input(tty); flush_output(tty); }}static void copy_to_cooked(struct tty_struct * tty){ int c, special_flag; unsigned long flags; if (!tty) { printk("copy_to_cooked: called with NULL tty\n"); return; } if (!tty->write) { printk("copy_to_cooked: tty %d has null write routine\n", tty->line); } while (1) { /* * Check to see how much room we have left in the * secondary queue. Send a throttle command or abort * if necessary. */ c = LEFT(&tty->secondary); if (tty->throttle && (c < SQ_THRESHOLD_LW) && !set_bit(TTY_SQ_THROTTLED, &tty->flags)) tty->throttle(tty, TTY_THROTTLE_SQ_FULL); if (c == 0) break; save_flags(flags); cli(); if (!EMPTY(&tty->read_q)) { c = tty->read_q.buf[tty->read_q.tail]; special_flag = clear_bit(tty->read_q.tail, &tty->readq_flags); INC(tty->read_q.tail); restore_flags(flags); } else { restore_flags(flags); break; } if (special_flag) { tty->char_error = c; continue; } if (tty->char_error) { if (tty->char_error == TTY_BREAK) { tty->char_error = 0; if (I_IGNBRK(tty)) continue; /* A break is handled by the lower levels. */ if (I_BRKINT(tty)) continue; if (I_PARMRK(tty)) { put_tty_queue('\377', &tty->secondary); put_tty_queue('\0', &tty->secondary); } put_tty_queue('\0', &tty->secondary); continue; } if (tty->char_error == TTY_OVERRUN) { tty->char_error = 0; printk("tty%d: input overrun\n", tty->line); continue; } /* Must be a parity or frame error */ tty->char_error = 0; if (I_IGNPAR(tty)) { continue; } if (I_PARMRK(tty)) { put_tty_queue('\377', &tty->secondary); put_tty_queue('\0', &tty->secondary); put_tty_queue(c, &tty->secondary); } else put_tty_queue('\0', &tty->secondary); continue; } if (I_ISTRIP(tty)) c &= 0x7f; if (!tty->lnext) { if (c == '\r') { if (I_IGNCR(tty)) continue; if (I_ICRNL(tty)) c = '\n'; } else if (c == '\n' && I_INLCR(tty)) c = '\r'; } if (I_IUCLC(tty) && L_IEXTEN(tty)) c=tolower(c); if (c == __DISABLED_CHAR) tty->lnext = 1; if (L_ICANON(tty) && !tty->lnext) { if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { eraser(c, tty); continue; } if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { tty->lnext = 1; if (L_ECHO(tty)) { if (tty->erasing) { opost('/', tty); tty->erasing = 0; } if (L_ECHOCTL(tty)) { opost('^', tty); opost('\b', tty); } } continue; } if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty)) { unsigned long tail = tty->canon_head; if (tty->erasing) { opost('/', tty); tty->erasing = 0; } echo_char(c, tty); opost('\n', tty); while (tail != tty->secondary.head) { echo_char(tty->secondary.buf[tail], tty); INC(tail); } continue; } } if (I_IXON(tty) && !tty->lnext) { if ((tty->stopped && I_IXANY(tty) && L_IEXTEN(tty)) || c == START_CHAR(tty)) { start_tty(tty); continue; } if (c == STOP_CHAR(tty)) { stop_tty(tty); continue; } } if (L_ISIG(tty) && !tty->lnext) { if (c == INTR_CHAR(tty)) { isig(SIGINT, tty); continue; } if (c == QUIT_CHAR(tty)) { isig(SIGQUIT, tty); continue; } if (c == SUSP_CHAR(tty)) { if (!is_orphaned_pgrp(tty->pgrp)) isig(SIGTSTP, tty); continue; } } if (tty->erasing) { opost('/', tty); tty->erasing = 0; } if (c == '\n' && !tty->lnext) { if (L_ECHO(tty) || (L_ICANON(tty) && L_ECHONL(tty))) opost('\n', tty); } else if (L_ECHO(tty)) { /* Don't echo the EOF char in canonical mode. Sun handles this differently by echoing the char and then backspacing, but that's a hack. */ if (c != EOF_CHAR(tty) || !L_ICANON(tty) || tty->lnext) { /* Record the column of first canon char. */ if (tty->canon_head == tty->secondary.head) tty->canon_column = tty->column; echo_char(c, tty); } } if (I_PARMRK(tty) && c == (unsigned char) '\377' && (c != EOF_CHAR(tty) || !L_ICANON(tty) || tty->lnext)) put_tty_queue(c, &tty->secondary); if (L_ICANON(tty) && !tty->lnext && (c == '\n' || c == EOF_CHAR(tty) || c == EOL_CHAR(tty) || (c == EOL2_CHAR(tty) && L_IEXTEN(tty)))) { if (c == EOF_CHAR(tty)) c = __DISABLED_CHAR; set_bit(tty->secondary.head, &tty->secondary_flags); put_tty_queue(c, &tty->secondary); tty->canon_head = tty->secondary.head; tty->canon_data++; } else put_tty_queue(c, &tty->secondary); tty->lnext = 0; } if (!EMPTY(&tty->write_q)) TTY_WRITE_FLUSH(tty); if (L_ICANON(tty) ? tty->canon_data : !EMPTY(&tty->secondary)) wake_up_interruptible(&tty->secondary.proc_list); if (tty->throttle && (LEFT(&tty->read_q) >= RQ_THRESHOLD_HW) && clear_bit(TTY_RQ_THROTTLED, &tty->flags)) tty->throttle(tty, TTY_THROTTLE_RQ_AVAIL);}int is_ignored(int sig)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -