diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/n_tty.c | 17 | ||||
-rw-r--r-- | drivers/char/pty.c | 21 | ||||
-rw-r--r-- | drivers/char/tty_ioctl.c | 18 |
3 files changed, 47 insertions, 9 deletions
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index bdae832..428f4fe 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -1102,6 +1102,11 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) if (I_IUCLC(tty) && L_IEXTEN(tty)) c = tolower(c); + if (L_EXTPROC(tty)) { + put_tty_queue(c, tty); + return; + } + if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { @@ -1409,7 +1414,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, n_tty_set_room(tty); - if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) { + if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || + L_EXTPROC(tty)) { kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) wake_up_interruptible(&tty->read_wait); @@ -1585,7 +1591,7 @@ static int n_tty_open(struct tty_struct *tty) static inline int input_available_p(struct tty_struct *tty, int amt) { tty_flush_to_ldisc(tty); - if (tty->icanon) { + if (tty->icanon && !L_EXTPROC(tty)) { if (tty->canon_data) return 1; } else if (tty->read_cnt >= (amt ? amt : 1)) @@ -1632,6 +1638,11 @@ static int copy_from_read_buf(struct tty_struct *tty, spin_lock_irqsave(&tty->read_lock, flags); tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); tty->read_cnt -= n; + /* Turn single EOF into zero-length read */ + if (L_EXTPROC(tty) && tty->icanon && n == 1) { + if (!tty->read_cnt && (*b)[n-1] == EOF_CHAR(tty)) + n--; + } spin_unlock_irqrestore(&tty->read_lock, flags); *b += n; *nr -= n; @@ -1812,7 +1823,7 @@ do_it_again: nr--; } - if (tty->icanon) { + if (tty->icanon && !L_EXTPROC(tty)) { /* N.B. avoid overrun if nr == 0 */ while (nr && tty->read_cnt) { int eol; diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d83a431..b640ef2 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -171,6 +171,23 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg) return 0; } +/* Send a signal to the slave */ +static int pty_signal(struct tty_struct *tty, int sig) +{ + unsigned long flags; + struct pid *pgrp; + + if (tty->link) { + spin_lock_irqsave(&tty->link->ctrl_lock, flags); + pgrp = get_pid(tty->link->pgrp); + spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); + + kill_pgrp(pgrp, sig, 1); + put_pid(pgrp); + } + return 0; +} + static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; @@ -321,6 +338,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, 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; } @@ -476,6 +495,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, return pty_set_lock(tty, (int __user *)arg); case TIOCGPTN: /* Get PT Number */ return put_user(tty->index, (unsigned 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); } |