aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/n_tty.c17
-rw-r--r--drivers/char/pty.c21
-rw-r--r--drivers/char/tty_ioctl.c18
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)
1585static inline int input_available_p(struct tty_struct *tty, int amt) 1591static 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 */
175static 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
174static void pty_flush_buffer(struct tty_struct *tty) 191static 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 }