diff options
Diffstat (limited to 'drivers/char/pty.c')
-rw-r--r-- | drivers/char/pty.c | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d83a43130df4..ad46eae1f9bb 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -62,7 +62,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
62 | if (tty->driver == ptm_driver) | 62 | if (tty->driver == ptm_driver) |
63 | devpts_pty_kill(tty->link); | 63 | devpts_pty_kill(tty->link); |
64 | #endif | 64 | #endif |
65 | tty_unlock(); | ||
65 | tty_vhangup(tty->link); | 66 | tty_vhangup(tty->link); |
67 | tty_lock(); | ||
66 | } | 68 | } |
67 | } | 69 | } |
68 | 70 | ||
@@ -171,6 +173,23 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg) | |||
171 | return 0; | 173 | return 0; |
172 | } | 174 | } |
173 | 175 | ||
176 | /* Send a signal to the slave */ | ||
177 | static int pty_signal(struct tty_struct *tty, int sig) | ||
178 | { | ||
179 | unsigned long flags; | ||
180 | struct pid *pgrp; | ||
181 | |||
182 | if (tty->link) { | ||
183 | spin_lock_irqsave(&tty->link->ctrl_lock, flags); | ||
184 | pgrp = get_pid(tty->link->pgrp); | ||
185 | spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); | ||
186 | |||
187 | kill_pgrp(pgrp, sig, 1); | ||
188 | put_pid(pgrp); | ||
189 | } | ||
190 | return 0; | ||
191 | } | ||
192 | |||
174 | static void pty_flush_buffer(struct tty_struct *tty) | 193 | static void pty_flush_buffer(struct tty_struct *tty) |
175 | { | 194 | { |
176 | struct tty_struct *to = tty->link; | 195 | struct tty_struct *to = tty->link; |
@@ -321,6 +340,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, | |||
321 | switch (cmd) { | 340 | switch (cmd) { |
322 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ | 341 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ |
323 | return pty_set_lock(tty, (int __user *) arg); | 342 | return pty_set_lock(tty, (int __user *) arg); |
343 | case TIOCSIG: /* Send signal to other side of pty */ | ||
344 | return pty_signal(tty, (int) arg); | ||
324 | } | 345 | } |
325 | return -ENOIOCTLCMD; | 346 | return -ENOIOCTLCMD; |
326 | } | 347 | } |
@@ -476,6 +497,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, | |||
476 | return pty_set_lock(tty, (int __user *)arg); | 497 | return pty_set_lock(tty, (int __user *)arg); |
477 | case TIOCGPTN: /* Get PT Number */ | 498 | case TIOCGPTN: /* Get PT Number */ |
478 | return put_user(tty->index, (unsigned int __user *)arg); | 499 | return put_user(tty->index, (unsigned int __user *)arg); |
500 | case TIOCSIG: /* Send signal to other side of pty */ | ||
501 | return pty_signal(tty, (int) arg); | ||
479 | } | 502 | } |
480 | 503 | ||
481 | return -ENOIOCTLCMD; | 504 | return -ENOIOCTLCMD; |
@@ -626,7 +649,7 @@ static const struct tty_operations pty_unix98_ops = { | |||
626 | * allocated_ptys_lock handles the list of free pty numbers | 649 | * allocated_ptys_lock handles the list of free pty numbers |
627 | */ | 650 | */ |
628 | 651 | ||
629 | static int __ptmx_open(struct inode *inode, struct file *filp) | 652 | static int ptmx_open(struct inode *inode, struct file *filp) |
630 | { | 653 | { |
631 | struct tty_struct *tty; | 654 | struct tty_struct *tty; |
632 | int retval; | 655 | int retval; |
@@ -635,11 +658,14 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
635 | nonseekable_open(inode, filp); | 658 | nonseekable_open(inode, filp); |
636 | 659 | ||
637 | /* find a device that is not in use. */ | 660 | /* find a device that is not in use. */ |
661 | tty_lock(); | ||
638 | index = devpts_new_index(inode); | 662 | index = devpts_new_index(inode); |
663 | tty_unlock(); | ||
639 | if (index < 0) | 664 | if (index < 0) |
640 | return index; | 665 | return index; |
641 | 666 | ||
642 | mutex_lock(&tty_mutex); | 667 | mutex_lock(&tty_mutex); |
668 | tty_lock(); | ||
643 | tty = tty_init_dev(ptm_driver, index, 1); | 669 | tty = tty_init_dev(ptm_driver, index, 1); |
644 | mutex_unlock(&tty_mutex); | 670 | mutex_unlock(&tty_mutex); |
645 | 671 | ||
@@ -657,26 +683,21 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
657 | goto out1; | 683 | goto out1; |
658 | 684 | ||
659 | retval = ptm_driver->ops->open(tty, filp); | 685 | retval = ptm_driver->ops->open(tty, filp); |
660 | if (!retval) | 686 | if (retval) |
661 | return 0; | 687 | goto out2; |
662 | out1: | 688 | out1: |
689 | tty_unlock(); | ||
690 | return retval; | ||
691 | out2: | ||
692 | tty_unlock(); | ||
663 | tty_release(inode, filp); | 693 | tty_release(inode, filp); |
664 | return retval; | 694 | return retval; |
665 | out: | 695 | out: |
666 | devpts_kill_index(inode, index); | 696 | devpts_kill_index(inode, index); |
697 | tty_unlock(); | ||
667 | return retval; | 698 | return retval; |
668 | } | 699 | } |
669 | 700 | ||
670 | static int ptmx_open(struct inode *inode, struct file *filp) | ||
671 | { | ||
672 | int ret; | ||
673 | |||
674 | lock_kernel(); | ||
675 | ret = __ptmx_open(inode, filp); | ||
676 | unlock_kernel(); | ||
677 | return ret; | ||
678 | } | ||
679 | |||
680 | static struct file_operations ptmx_fops; | 701 | static struct file_operations ptmx_fops; |
681 | 702 | ||
682 | static void __init unix98_pty_init(void) | 703 | static void __init unix98_pty_init(void) |