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 bdae8327143c..428f4fe0b5f7 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) | |||
1102 | if (I_IUCLC(tty) && L_IEXTEN(tty)) | 1102 | if (I_IUCLC(tty) && L_IEXTEN(tty)) |
1103 | c = tolower(c); | 1103 | c = tolower(c); |
1104 | 1104 | ||
1105 | if (L_EXTPROC(tty)) { | ||
1106 | put_tty_queue(c, tty); | ||
1107 | return; | ||
1108 | } | ||
1109 | |||
1105 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && | 1110 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && |
1106 | I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && | 1111 | I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && |
1107 | c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { | 1112 | 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, | |||
1409 | 1414 | ||
1410 | n_tty_set_room(tty); | 1415 | n_tty_set_room(tty); |
1411 | 1416 | ||
1412 | if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) { | 1417 | if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || |
1418 | L_EXTPROC(tty)) { | ||
1413 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); | 1419 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); |
1414 | if (waitqueue_active(&tty->read_wait)) | 1420 | if (waitqueue_active(&tty->read_wait)) |
1415 | wake_up_interruptible(&tty->read_wait); | 1421 | wake_up_interruptible(&tty->read_wait); |
@@ -1585,7 +1591,7 @@ static int n_tty_open(struct tty_struct *tty) | |||
1585 | static inline int input_available_p(struct tty_struct *tty, int amt) | 1591 | static inline int input_available_p(struct tty_struct *tty, int amt) |
1586 | { | 1592 | { |
1587 | tty_flush_to_ldisc(tty); | 1593 | tty_flush_to_ldisc(tty); |
1588 | if (tty->icanon) { | 1594 | if (tty->icanon && !L_EXTPROC(tty)) { |
1589 | if (tty->canon_data) | 1595 | if (tty->canon_data) |
1590 | return 1; | 1596 | return 1; |
1591 | } else if (tty->read_cnt >= (amt ? amt : 1)) | 1597 | } else if (tty->read_cnt >= (amt ? amt : 1)) |
@@ -1632,6 +1638,11 @@ static int copy_from_read_buf(struct tty_struct *tty, | |||
1632 | spin_lock_irqsave(&tty->read_lock, flags); | 1638 | spin_lock_irqsave(&tty->read_lock, flags); |
1633 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); | 1639 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); |
1634 | tty->read_cnt -= n; | 1640 | tty->read_cnt -= n; |
1641 | /* Turn single EOF into zero-length read */ | ||
1642 | if (L_EXTPROC(tty) && tty->icanon && n == 1) { | ||
1643 | if (!tty->read_cnt && (*b)[n-1] == EOF_CHAR(tty)) | ||
1644 | n--; | ||
1645 | } | ||
1635 | spin_unlock_irqrestore(&tty->read_lock, flags); | 1646 | spin_unlock_irqrestore(&tty->read_lock, flags); |
1636 | *b += n; | 1647 | *b += n; |
1637 | *nr -= n; | 1648 | *nr -= n; |
@@ -1812,7 +1823,7 @@ do_it_again: | |||
1812 | nr--; | 1823 | nr--; |
1813 | } | 1824 | } |
1814 | 1825 | ||
1815 | if (tty->icanon) { | 1826 | if (tty->icanon && !L_EXTPROC(tty)) { |
1816 | /* N.B. avoid overrun if nr == 0 */ | 1827 | /* N.B. avoid overrun if nr == 0 */ |
1817 | while (nr && tty->read_cnt) { | 1828 | while (nr && tty->read_cnt) { |
1818 | int eol; | 1829 | int eol; |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d83a43130df4..b640ef29be1c 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) | |||
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | /* Send a signal to the slave */ | ||
175 | static int pty_signal(struct tty_struct *tty, int sig) | ||
176 | { | ||
177 | unsigned long flags; | ||
178 | struct pid *pgrp; | ||
179 | |||
180 | if (tty->link) { | ||
181 | spin_lock_irqsave(&tty->link->ctrl_lock, flags); | ||
182 | pgrp = get_pid(tty->link->pgrp); | ||
183 | spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); | ||
184 | |||
185 | kill_pgrp(pgrp, sig, 1); | ||
186 | put_pid(pgrp); | ||
187 | } | ||
188 | return 0; | ||
189 | } | ||
190 | |||
174 | static void pty_flush_buffer(struct tty_struct *tty) | 191 | static void pty_flush_buffer(struct tty_struct *tty) |
175 | { | 192 | { |
176 | struct tty_struct *to = tty->link; | 193 | struct tty_struct *to = tty->link; |
@@ -321,6 +338,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, | |||
321 | switch (cmd) { | 338 | switch (cmd) { |
322 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ | 339 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ |
323 | return pty_set_lock(tty, (int __user *) arg); | 340 | return pty_set_lock(tty, (int __user *) arg); |
341 | case TIOCSIG: /* Send signal to other side of pty */ | ||
342 | return pty_signal(tty, (int) arg); | ||
324 | } | 343 | } |
325 | return -ENOIOCTLCMD; | 344 | return -ENOIOCTLCMD; |
326 | } | 345 | } |
@@ -476,6 +495,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, | |||
476 | return pty_set_lock(tty, (int __user *)arg); | 495 | return pty_set_lock(tty, (int __user *)arg); |
477 | case TIOCGPTN: /* Get PT Number */ | 496 | case TIOCGPTN: /* Get PT Number */ |
478 | return put_user(tty->index, (unsigned int __user *)arg); | 497 | return put_user(tty->index, (unsigned int __user *)arg); |
498 | case TIOCSIG: /* Send signal to other side of pty */ | ||
499 | return pty_signal(tty, (int) arg); | ||
479 | } | 500 | } |
480 | 501 | ||
481 | return -ENOIOCTLCMD; | 502 | return -ENOIOCTLCMD; |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 6bd5f8866c74..0c1889971459 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) | |||
517 | 517 | ||
518 | /* See if packet mode change of state. */ | 518 | /* See if packet mode change of state. */ |
519 | if (tty->link && tty->link->packet) { | 519 | if (tty->link && tty->link->packet) { |
520 | int extproc = (old_termios.c_lflag & EXTPROC) | | ||
521 | (tty->termios->c_lflag & EXTPROC); | ||
520 | int old_flow = ((old_termios.c_iflag & IXON) && | 522 | int old_flow = ((old_termios.c_iflag & IXON) && |
521 | (old_termios.c_cc[VSTOP] == '\023') && | 523 | (old_termios.c_cc[VSTOP] == '\023') && |
522 | (old_termios.c_cc[VSTART] == '\021')); | 524 | (old_termios.c_cc[VSTART] == '\021')); |
523 | int new_flow = (I_IXON(tty) && | 525 | int new_flow = (I_IXON(tty) && |
524 | STOP_CHAR(tty) == '\023' && | 526 | STOP_CHAR(tty) == '\023' && |
525 | START_CHAR(tty) == '\021'); | 527 | START_CHAR(tty) == '\021'); |
526 | if (old_flow != new_flow) { | 528 | if ((old_flow != new_flow) || extproc) { |
527 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 529 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
528 | tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); | 530 | if (old_flow != new_flow) { |
529 | if (new_flow) | 531 | tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); |
530 | tty->ctrl_status |= TIOCPKT_DOSTOP; | 532 | if (new_flow) |
531 | else | 533 | tty->ctrl_status |= TIOCPKT_DOSTOP; |
532 | tty->ctrl_status |= TIOCPKT_NOSTOP; | 534 | else |
535 | tty->ctrl_status |= TIOCPKT_NOSTOP; | ||
536 | } | ||
537 | if (extproc) | ||
538 | tty->ctrl_status |= TIOCPKT_IOCTL; | ||
533 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 539 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
534 | wake_up_interruptible(&tty->link->read_wait); | 540 | wake_up_interruptible(&tty->link->read_wait); |
535 | } | 541 | } |