?? tty_ioctl.c
字號:
/* * linux/kernel/drivers/char/tty_ioctl.c * * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds * * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines * which can be dynamically activated and de-activated by the line * discipline handling modules (like SLIP). */#include <linux/types.h>#include <linux/termios.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/tty.h>#include <linux/fcntl.h>#include <linux/string.h>#include <asm/io.h>#include <asm/bitops.h>#include <asm/segment.h>#include <asm/system.h>#undef DEBUG#ifdef DEBUG# define PRINTK(x) printk (x)#else# define PRINTK(x) /**/#endifextern int session_of_pgrp(int pgrp);extern int do_screendump(int arg);extern int kill_pg(int pgrp, int sig, int priv);#ifdef CONFIG_SELECTIONextern int set_selection(const int arg);extern int paste_selection(struct tty_struct *tty);#endif /* CONFIG_SELECTION */static int tty_set_ldisc(struct tty_struct *tty, int ldisc);void flush_input(struct tty_struct * tty){ cli(); tty->read_q.head = tty->read_q.tail = 0; tty->secondary.head = tty->secondary.tail = 0; tty->canon_head = tty->canon_data = tty->erasing = 0; memset(&tty->readq_flags, 0, sizeof tty->readq_flags); memset(&tty->secondary_flags, 0, sizeof tty->secondary_flags); sti(); if (!tty->link) return; /* No cli() since ptys don't use interrupts. */ tty->link->write_q.head = tty->link->write_q.tail = 0; wake_up_interruptible(&tty->link->write_q.proc_list); if (tty->link->packet) { tty->ctrl_status |= TIOCPKT_FLUSHREAD; wake_up_interruptible(&tty->link->secondary.proc_list); }}void flush_output(struct tty_struct * tty){ cli(); tty->write_q.head = tty->write_q.tail = 0; sti(); wake_up_interruptible(&tty->write_q.proc_list); if (!tty->link) return; /* No cli() since ptys don't use interrupts. */ tty->link->read_q.head = tty->link->read_q.tail = 0; tty->link->secondary.head = tty->link->secondary.tail = 0; tty->link->canon_head = tty->link->canon_data = tty->link->erasing = 0; memset(&tty->link->readq_flags, 0, sizeof tty->readq_flags); memset(&tty->link->secondary_flags, 0, sizeof tty->secondary_flags); if (tty->link->packet) { tty->ctrl_status |= TIOCPKT_FLUSHWRITE; wake_up_interruptible(&tty->link->secondary.proc_list); }}void wait_until_sent(struct tty_struct * tty, int timeout){ struct wait_queue wait = { current, NULL }; TTY_WRITE_FLUSH(tty); if (EMPTY(&tty->write_q)) return; add_wait_queue(&tty->write_q.proc_list, &wait); current->counter = 0; /* make us low-priority */ if (timeout) current->timeout = timeout + jiffies; else current->timeout = (unsigned) -1; do { current->state = TASK_INTERRUPTIBLE; if (current->signal & ~current->blocked) break; TTY_WRITE_FLUSH(tty); if (EMPTY(&tty->write_q)) break; schedule(); } while (current->timeout); current->state = TASK_RUNNING; remove_wait_queue(&tty->write_q.proc_list, &wait);}static int do_get_ps_info(int arg){ struct tstruct { int flag; int present[NR_TASKS]; struct task_struct tasks[NR_TASKS]; }; struct tstruct *ts = (struct tstruct *)arg; struct task_struct **p; char *c, *d; int i, n = 0; i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct tstruct)); if (i) return i; for (p = &FIRST_TASK ; p <= &LAST_TASK ; p++, n++) if (*p) { c = (char *)(*p); d = (char *)(ts->tasks+n); for (i=0 ; i<sizeof(struct task_struct) ; i++) put_fs_byte(*c++, d++); put_fs_long(1, (unsigned long *)(ts->present+n)); } else put_fs_long(0, (unsigned long *)(ts->present+n)); return(0); }static void unset_locked_termios(struct termios *termios, struct termios *old, struct termios *locked){ int i; #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z))) if (!locked) { printk("Warning?!? termios_locked is NULL.\n"); return; } NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag); NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag); NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag); NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag); termios->c_line = locked->c_line ? old->c_line : termios->c_line; for (i=0; i < NCCS; i++) termios->c_cc[i] = locked->c_cc[i] ? old->c_cc[i] : termios->c_cc[i];}int check_change(struct tty_struct * tty, int channel){ /* If we try to set the state of terminal and we're not in the foreground, send a SIGTTOU. If the signal is blocked or ignored, go ahead and perform the operation. POSIX 7.2) */ if (current->tty != channel) return 0; if (tty->pgrp <= 0) { printk("check_change: tty->pgrp <= 0!\n"); return 0; } if (current->pgrp == tty->pgrp) return 0; if (is_ignored(SIGTTOU)) return 0; if (is_orphaned_pgrp(current->pgrp)) return -EIO; (void) kill_pg(current->pgrp,SIGTTOU,1); return -ERESTARTSYS;}static int set_termios_2(struct tty_struct * tty, struct termios * termios){ struct termios old_termios = *tty->termios; int canon_change; canon_change = (old_termios.c_lflag ^ termios->c_lflag) & ICANON; cli(); *tty->termios = *termios; if (canon_change) { memset(&tty->secondary_flags, 0, sizeof tty->secondary_flags); tty->canon_head = tty->secondary.tail; tty->canon_data = 0; tty->erasing = 0; } sti(); if (canon_change && !L_ICANON(tty) && !EMPTY(&tty->secondary)) /* Get characters left over from canonical mode. */ wake_up_interruptible(&tty->secondary.proc_list); /* see if packet mode change of state */ if (tty->link && tty->link->packet) { int old_flow = ((old_termios.c_iflag & IXON) && (old_termios.c_cc[VSTOP] == '\023') && (old_termios.c_cc[VSTART] == '\021')); int new_flow = (I_IXON(tty) && STOP_CHAR(tty) == '\023' && START_CHAR(tty) == '\021'); if (old_flow != new_flow) { tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); if (new_flow) tty->ctrl_status |= TIOCPKT_DOSTOP; else tty->ctrl_status |= TIOCPKT_NOSTOP; wake_up_interruptible(&tty->link->secondary.proc_list); } } unset_locked_termios(tty->termios, &old_termios, termios_locked[tty->line]); if (tty->set_termios) (*tty->set_termios)(tty, &old_termios); return 0;}static int set_termios(struct tty_struct * tty, struct termios * termios, int channel){ struct termios tmp_termios; memcpy_fromfs(&tmp_termios, termios, sizeof (struct termios)); return set_termios_2(tty, &tmp_termios);}static int get_termio(struct tty_struct * tty, struct termio * termio){ int i; struct termio tmp_termio; i = verify_area(VERIFY_WRITE, termio, sizeof (struct termio)); if (i) return i; tmp_termio.c_iflag = tty->termios->c_iflag; tmp_termio.c_oflag = tty->termios->c_oflag; tmp_termio.c_cflag = tty->termios->c_cflag; tmp_termio.c_lflag = tty->termios->c_lflag; tmp_termio.c_line = tty->termios->c_line; for(i=0 ; i < NCC ; i++) tmp_termio.c_cc[i] = tty->termios->c_cc[i]; memcpy_tofs(termio, &tmp_termio, sizeof (struct termio)); return 0;}static int set_termio(struct tty_struct * tty, struct termio * termio, int channel){ struct termio tmp_termio; struct termios tmp_termios; tmp_termios = *tty->termios; memcpy_fromfs(&tmp_termio, termio, sizeof (struct termio));#define SET_LOW_BITS(x,y) ((x) = (0xffff0000 & (x)) | (y)) SET_LOW_BITS(tmp_termios.c_iflag, tmp_termio.c_iflag); SET_LOW_BITS(tmp_termios.c_oflag, tmp_termio.c_oflag); SET_LOW_BITS(tmp_termios.c_cflag, tmp_termio.c_cflag); SET_LOW_BITS(tmp_termios.c_lflag, tmp_termio.c_lflag); memcpy(&tmp_termios.c_cc, &tmp_termio.c_cc, NCC);#undef SET_LOW_BITS return set_termios_2(tty, &tmp_termios);}static int set_window_size(struct tty_struct * tty, struct winsize * ws){ struct winsize tmp_ws; memcpy_fromfs(&tmp_ws, ws, sizeof (struct winsize)); if (memcmp(&tmp_ws, &tty->winsize, sizeof (struct winsize)) && tty->pgrp > 0) kill_pg(tty->pgrp, SIGWINCH, 1); tty->winsize = tmp_ws; return 0;}/* Set the discipline of a tty line. */static int tty_set_ldisc(struct tty_struct *tty, int ldisc){ if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS) || !(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) return -EINVAL; if (tty->disc == ldisc) return 0; /* We are already in the desired discipline */ /* Shutdown the current discipline. */ wait_until_sent(tty, 0); flush_input(tty); if (ldiscs[tty->disc].close) ldiscs[tty->disc].close(tty); /* Now set up the new line discipline. */ tty->disc = ldisc; tty->termios->c_line = ldisc; if (ldiscs[tty->disc].open) return(ldiscs[tty->disc].open(tty)); else return 0;}static unsigned long inq_canon(struct tty_struct * tty){ int nr, head, tail; if (!tty->canon_data) return 0; head = tty->canon_head; tail = tty->secondary.tail; nr = (head - tail) & (TTY_BUF_SIZE-1); /* Skip EOF-chars.. */ while (head != tail) { if (test_bit(tail, &tty->secondary_flags) && tty->secondary.buf[tail] == __DISABLED_CHAR) nr--; INC(tail); } return nr;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -