diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index bdae832..bbc42e6 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -780,6 +780,8 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab, static void echo_char_raw(unsigned char c, struct tty_struct *tty) { + if (L_EXTPROC(tty)) return; + mutex_lock(&tty->echo_lock); if (c == ECHO_OP_START) { @@ -808,6 +810,8 @@ static void echo_char_raw(unsigned char c, struct tty_struct *tty) static void echo_char(unsigned char c, struct tty_struct *tty) { + if (L_EXTPROC(tty)) return; + mutex_lock(&tty->echo_lock); if (c == ECHO_OP_START) { @@ -1767,6 +1771,13 @@ do_it_again: break; } nr--; + if (cs & TIOCPKT_IOCTL) { + c = sizeof(struct termios); + if (c > nr) c = nr; + copy_to_user(b, tty->link->termios, c); + nr -= c; + b += c; + } break; } /* This statement must be first before checking for input diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d83a431..7485efb 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -315,12 +315,21 @@ free_mem_out: return -ENOMEM; } +static int pty_signal(struct tty_struct *tty, int sig) +{ + if (tty->link && tty->link->pgrp > 0) + kill_pgrp(tty->link->pgrp, sig, 1); + return 0; +} + static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ return pty_set_lock(tty, (int __user *) arg); + case TIOCSIG: /* Send signal to other side of pty */ + return pty_signal(tty, (int) arg); } return -ENOIOCTLCMD; } diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 6bd5f88..0c18899 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -517,19 +517,25 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) /* See if packet mode change of state. */ if (tty->link && tty->link->packet) { + int extproc = (old_termios.c_lflag & EXTPROC) | + (tty->termios->c_lflag & EXTPROC); 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) { + if ((old_flow != new_flow) || extproc) { spin_lock_irqsave(&tty->ctrl_lock, flags); - tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); - if (new_flow) - tty->ctrl_status |= TIOCPKT_DOSTOP; - else - tty->ctrl_status |= TIOCPKT_NOSTOP; + 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; + } + if (extproc) + tty->ctrl_status |= TIOCPKT_IOCTL; spin_unlock_irqrestore(&tty->ctrl_lock, flags); wake_up_interruptible(&tty->link->read_wait); } diff --git a/include/asm-generic/ioctls.h b/include/asm-generic/ioctls.h index a799e20..3ac6908 100644 --- a/include/asm-generic/ioctls.h +++ b/include/asm-generic/ioctls.h @@ -65,6 +65,7 @@ #define TIOCSRS485 0x542F #define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ +#define TIOCSIG _IO ('T', 0x32) /* pty: generate signal */ #define TCGETX 0x5432 /* SYS5 TCGETX compatibility */ #define TCSETX 0x5433 #define TCSETXF 0x5434 @@ -104,6 +105,7 @@ #define TIOCPKT_START 8 #define TIOCPKT_NOSTOP 16 #define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64 #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ diff --git a/include/asm-generic/termbits.h b/include/asm-generic/termbits.h index 1c9773d..232b478 100644 --- a/include/asm-generic/termbits.h +++ b/include/asm-generic/termbits.h @@ -178,6 +178,7 @@ struct ktermios { #define FLUSHO 0010000 #define PENDIN 0040000 #define IEXTEN 0100000 +#define EXTPROC 0200000 /* tcflow() and TCXONC use these */ #define TCOOFF 0 diff --git a/include/linux/tty.h b/include/linux/tty.h index 4409967..3cfe448 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -178,6 +178,7 @@ struct tty_bufhead { #define L_FLUSHO(tty) _L_FLAG((tty), FLUSHO) #define L_PENDIN(tty) _L_FLAG((tty), PENDIN) #define L_IEXTEN(tty) _L_FLAG((tty), IEXTEN) +#define L_EXTPROC(tty) _L_FLAG((tty), EXTPROC) struct device; struct signal_struct;