diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2015-10-10 20:28:42 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-10-18 00:30:49 -0400 |
commit | 2812d9e9fd94c54b0482215f579e6aa04452a322 (patch) | |
tree | 04be4bb895b4bbde79538de1e61550fcae6d9dbe | |
parent | 71a5cd8a4a2602a6e9010b557a23af0a54df87b6 (diff) |
tty: Combine SIGTTOU/SIGTTIN handling
The job_control() check in n_tty_read() has nearly identical purpose
and results as tty_check_change(). Both functions' purpose is to
determine if the current task's pgrp is the foreground pgrp for the tty,
and if not, to signal the current pgrp.
Introduce __tty_check_change() which takes the signal to send
and performs the shared operations for job control() and
tty_check_change().
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/tty/n_tty.c | 26 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 46 | ||||
-rw-r--r-- | include/linux/tty.h | 1 |
3 files changed, 27 insertions, 46 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index ff728d32cb53..fb8ccbfdbb30 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -2138,37 +2138,15 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *, | |||
2138 | 2138 | ||
2139 | static int job_control(struct tty_struct *tty, struct file *file) | 2139 | static int job_control(struct tty_struct *tty, struct file *file) |
2140 | { | 2140 | { |
2141 | struct pid *pgrp; | ||
2142 | |||
2143 | /* Job control check -- must be done at start and after | 2141 | /* Job control check -- must be done at start and after |
2144 | every sleep (POSIX.1 7.1.1.4). */ | 2142 | every sleep (POSIX.1 7.1.1.4). */ |
2145 | /* NOTE: not yet done after every sleep pending a thorough | 2143 | /* NOTE: not yet done after every sleep pending a thorough |
2146 | check of the logic of this change. -- jlc */ | 2144 | check of the logic of this change. -- jlc */ |
2147 | /* don't stop on /dev/console */ | 2145 | /* don't stop on /dev/console */ |
2148 | if (file->f_op->write == redirected_tty_write || | 2146 | if (file->f_op->write == redirected_tty_write) |
2149 | current->signal->tty != tty) | ||
2150 | return 0; | 2147 | return 0; |
2151 | 2148 | ||
2152 | rcu_read_lock(); | 2149 | return __tty_check_change(tty, SIGTTIN); |
2153 | pgrp = task_pgrp(current); | ||
2154 | |||
2155 | spin_lock_irq(&tty->ctrl_lock); | ||
2156 | if (!tty->pgrp) | ||
2157 | printk(KERN_ERR "n_tty_read: no tty->pgrp!\n"); | ||
2158 | else if (pgrp != tty->pgrp) { | ||
2159 | spin_unlock_irq(&tty->ctrl_lock); | ||
2160 | if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) { | ||
2161 | rcu_read_unlock(); | ||
2162 | return -EIO; | ||
2163 | } | ||
2164 | kill_pgrp(pgrp, SIGTTIN, 1); | ||
2165 | rcu_read_unlock(); | ||
2166 | set_thread_flag(TIF_SIGPENDING); | ||
2167 | return -ERESTARTSYS; | ||
2168 | } | ||
2169 | spin_unlock_irq(&tty->ctrl_lock); | ||
2170 | rcu_read_unlock(); | ||
2171 | return 0; | ||
2172 | } | 2150 | } |
2173 | 2151 | ||
2174 | 2152 | ||
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 2eefaa6e3e3a..aa48367a0c79 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -390,10 +390,10 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver); | |||
390 | * Locking: ctrl_lock | 390 | * Locking: ctrl_lock |
391 | */ | 391 | */ |
392 | 392 | ||
393 | int tty_check_change(struct tty_struct *tty) | 393 | int __tty_check_change(struct tty_struct *tty, int sig) |
394 | { | 394 | { |
395 | unsigned long flags; | 395 | unsigned long flags; |
396 | struct pid *pgrp; | 396 | struct pid *pgrp, *tty_pgrp; |
397 | int ret = 0; | 397 | int ret = 0; |
398 | 398 | ||
399 | if (current->signal->tty != tty) | 399 | if (current->signal->tty != tty) |
@@ -403,33 +403,35 @@ int tty_check_change(struct tty_struct *tty) | |||
403 | pgrp = task_pgrp(current); | 403 | pgrp = task_pgrp(current); |
404 | 404 | ||
405 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 405 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
406 | 406 | tty_pgrp = tty->pgrp; | |
407 | if (!tty->pgrp) { | ||
408 | printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n"); | ||
409 | goto out_unlock; | ||
410 | } | ||
411 | if (pgrp == tty->pgrp) | ||
412 | goto out_unlock; | ||
413 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 407 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
414 | 408 | ||
415 | if (is_ignored(SIGTTOU)) | 409 | if (tty_pgrp && pgrp != tty->pgrp) { |
416 | goto out_rcuunlock; | 410 | if (is_ignored(sig)) { |
417 | if (is_current_pgrp_orphaned()) { | 411 | if (sig == SIGTTIN) |
418 | ret = -EIO; | 412 | ret = -EIO; |
419 | goto out_rcuunlock; | 413 | } else if (is_current_pgrp_orphaned()) |
414 | ret = -EIO; | ||
415 | else { | ||
416 | kill_pgrp(pgrp, sig, 1); | ||
417 | set_thread_flag(TIF_SIGPENDING); | ||
418 | ret = -ERESTARTSYS; | ||
419 | } | ||
420 | } | 420 | } |
421 | kill_pgrp(pgrp, SIGTTOU, 1); | ||
422 | rcu_read_unlock(); | ||
423 | set_thread_flag(TIF_SIGPENDING); | ||
424 | ret = -ERESTARTSYS; | ||
425 | return ret; | ||
426 | out_unlock: | ||
427 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | ||
428 | out_rcuunlock: | ||
429 | rcu_read_unlock(); | 421 | rcu_read_unlock(); |
422 | |||
423 | if (!tty_pgrp) { | ||
424 | pr_warn("%s: tty_check_change: sig=%d, tty->pgrp == NULL!\n", | ||
425 | tty_name(tty), sig); | ||
426 | } | ||
427 | |||
430 | return ret; | 428 | return ret; |
431 | } | 429 | } |
432 | 430 | ||
431 | int tty_check_change(struct tty_struct *tty) | ||
432 | { | ||
433 | return __tty_check_change(tty, SIGTTOU); | ||
434 | } | ||
433 | EXPORT_SYMBOL(tty_check_change); | 435 | EXPORT_SYMBOL(tty_check_change); |
434 | 436 | ||
435 | static ssize_t hung_up_tty_read(struct file *file, char __user *buf, | 437 | static ssize_t hung_up_tty_read(struct file *file, char __user *buf, |
diff --git a/include/linux/tty.h b/include/linux/tty.h index c2889f4331e1..533d7f6e2481 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -423,6 +423,7 @@ extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, | |||
423 | const char *routine); | 423 | const char *routine); |
424 | extern const char *tty_name(const struct tty_struct *tty); | 424 | extern const char *tty_name(const struct tty_struct *tty); |
425 | extern void tty_wait_until_sent(struct tty_struct *tty, long timeout); | 425 | extern void tty_wait_until_sent(struct tty_struct *tty, long timeout); |
426 | extern int __tty_check_change(struct tty_struct *tty, int sig); | ||
426 | extern int tty_check_change(struct tty_struct *tty); | 427 | extern int tty_check_change(struct tty_struct *tty); |
427 | extern void __stop_tty(struct tty_struct *tty); | 428 | extern void __stop_tty(struct tty_struct *tty); |
428 | extern void stop_tty(struct tty_struct *tty); | 429 | extern void stop_tty(struct tty_struct *tty); |