diff options
Diffstat (limited to 'drivers/char/tty_ioctl.c')
| -rw-r--r-- | drivers/char/tty_ioctl.c | 170 |
1 files changed, 104 insertions, 66 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 7a003504c265..1bdd2bf4f37d 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
| @@ -730,13 +730,23 @@ static int send_prio_char(struct tty_struct *tty, char ch) | |||
| 730 | return 0; | 730 | return 0; |
| 731 | } | 731 | } |
| 732 | 732 | ||
| 733 | int n_tty_ioctl(struct tty_struct * tty, struct file * file, | 733 | /** |
| 734 | unsigned int cmd, unsigned long arg) | 734 | * tty_mode_ioctl - mode related ioctls |
| 735 | * @tty: tty for the ioctl | ||
| 736 | * @file: file pointer for the tty | ||
| 737 | * @cmd: command | ||
| 738 | * @arg: ioctl argument | ||
| 739 | * | ||
| 740 | * Perform non line discipline specific mode control ioctls. This | ||
| 741 | * is designed to be called by line disciplines to ensure they provide | ||
| 742 | * consistent mode setting. | ||
| 743 | */ | ||
| 744 | |||
| 745 | int tty_mode_ioctl(struct tty_struct * tty, struct file *file, | ||
| 746 | unsigned int cmd, unsigned long arg) | ||
| 735 | { | 747 | { |
| 736 | struct tty_struct * real_tty; | 748 | struct tty_struct * real_tty; |
| 737 | void __user *p = (void __user *)arg; | 749 | void __user *p = (void __user *)arg; |
| 738 | int retval; | ||
| 739 | struct tty_ldisc *ld; | ||
| 740 | 750 | ||
| 741 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 751 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
| 742 | tty->driver->subtype == PTY_TYPE_MASTER) | 752 | tty->driver->subtype == PTY_TYPE_MASTER) |
| @@ -799,6 +809,93 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, | |||
| 799 | return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); | 809 | return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); |
| 800 | case TCSETA: | 810 | case TCSETA: |
| 801 | return set_termios(real_tty, p, TERMIOS_TERMIO); | 811 | return set_termios(real_tty, p, TERMIOS_TERMIO); |
| 812 | #ifndef TCGETS2 | ||
| 813 | case TIOCGLCKTRMIOS: | ||
| 814 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) | ||
| 815 | return -EFAULT; | ||
| 816 | return 0; | ||
| 817 | |||
| 818 | case TIOCSLCKTRMIOS: | ||
| 819 | if (!capable(CAP_SYS_ADMIN)) | ||
| 820 | return -EPERM; | ||
| 821 | if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) | ||
| 822 | return -EFAULT; | ||
| 823 | return 0; | ||
| 824 | #else | ||
| 825 | case TIOCGLCKTRMIOS: | ||
| 826 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) | ||
| 827 | return -EFAULT; | ||
| 828 | return 0; | ||
| 829 | |||
| 830 | case TIOCSLCKTRMIOS: | ||
| 831 | if (!capable(CAP_SYS_ADMIN)) | ||
| 832 | return -EPERM; | ||
| 833 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg)) | ||
| 834 | return -EFAULT; | ||
| 835 | return 0; | ||
| 836 | #endif | ||
| 837 | case TIOCGSOFTCAR: | ||
| 838 | return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg); | ||
| 839 | case TIOCSSOFTCAR: | ||
| 840 | if (get_user(arg, (unsigned int __user *) arg)) | ||
| 841 | return -EFAULT; | ||
| 842 | mutex_lock(&tty->termios_mutex); | ||
| 843 | tty->termios->c_cflag = | ||
| 844 | ((tty->termios->c_cflag & ~CLOCAL) | | ||
| 845 | (arg ? CLOCAL : 0)); | ||
| 846 | mutex_unlock(&tty->termios_mutex); | ||
| 847 | return 0; | ||
| 848 | default: | ||
| 849 | return -ENOIOCTLCMD; | ||
| 850 | } | ||
| 851 | } | ||
| 852 | |||
| 853 | EXPORT_SYMBOL_GPL(tty_mode_ioctl); | ||
| 854 | |||
| 855 | int tty_perform_flush(struct tty_struct *tty, unsigned long arg) | ||
| 856 | { | ||
| 857 | struct tty_ldisc *ld; | ||
| 858 | int retval = tty_check_change(tty); | ||
| 859 | if (retval) | ||
| 860 | return retval; | ||
| 861 | |||
| 862 | ld = tty_ldisc_ref(tty); | ||
| 863 | switch (arg) { | ||
| 864 | case TCIFLUSH: | ||
| 865 | if (ld && ld->flush_buffer) | ||
| 866 | ld->flush_buffer(tty); | ||
| 867 | break; | ||
| 868 | case TCIOFLUSH: | ||
| 869 | if (ld && ld->flush_buffer) | ||
| 870 | ld->flush_buffer(tty); | ||
| 871 | /* fall through */ | ||
| 872 | case TCOFLUSH: | ||
| 873 | if (tty->driver->flush_buffer) | ||
| 874 | tty->driver->flush_buffer(tty); | ||
| 875 | break; | ||
| 876 | default: | ||
| 877 | tty_ldisc_deref(ld); | ||
| 878 | return -EINVAL; | ||
| 879 | } | ||
| 880 | tty_ldisc_deref(ld); | ||
| 881 | return 0; | ||
| 882 | } | ||
| 883 | |||
| 884 | EXPORT_SYMBOL_GPL(tty_perform_flush); | ||
| 885 | |||
| 886 | int n_tty_ioctl(struct tty_struct * tty, struct file * file, | ||
| 887 | unsigned int cmd, unsigned long arg) | ||
| 888 | { | ||
| 889 | struct tty_struct * real_tty; | ||
| 890 | int retval; | ||
| 891 | |||
| 892 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
| 893 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
| 894 | real_tty = tty->link; | ||
| 895 | else | ||
| 896 | real_tty = tty; | ||
| 897 | |||
| 898 | switch (cmd) { | ||
| 802 | case TCXONC: | 899 | case TCXONC: |
| 803 | retval = tty_check_change(tty); | 900 | retval = tty_check_change(tty); |
| 804 | if (retval) | 901 | if (retval) |
| @@ -829,30 +926,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, | |||
| 829 | } | 926 | } |
| 830 | return 0; | 927 | return 0; |
| 831 | case TCFLSH: | 928 | case TCFLSH: |
| 832 | retval = tty_check_change(tty); | 929 | return tty_perform_flush(tty, arg); |
| 833 | if (retval) | ||
| 834 | return retval; | ||
| 835 | |||
| 836 | ld = tty_ldisc_ref(tty); | ||
| 837 | switch (arg) { | ||
| 838 | case TCIFLUSH: | ||
| 839 | if (ld && ld->flush_buffer) | ||
| 840 | ld->flush_buffer(tty); | ||
| 841 | break; | ||
| 842 | case TCIOFLUSH: | ||
| 843 | if (ld && ld->flush_buffer) | ||
| 844 | ld->flush_buffer(tty); | ||
| 845 | /* fall through */ | ||
| 846 | case TCOFLUSH: | ||
| 847 | if (tty->driver->flush_buffer) | ||
| 848 | tty->driver->flush_buffer(tty); | ||
| 849 | break; | ||
| 850 | default: | ||
| 851 | tty_ldisc_deref(ld); | ||
| 852 | return -EINVAL; | ||
| 853 | } | ||
| 854 | tty_ldisc_deref(ld); | ||
| 855 | return 0; | ||
| 856 | case TIOCOUTQ: | 930 | case TIOCOUTQ: |
| 857 | return put_user(tty->driver->chars_in_buffer ? | 931 | return put_user(tty->driver->chars_in_buffer ? |
| 858 | tty->driver->chars_in_buffer(tty) : 0, | 932 | tty->driver->chars_in_buffer(tty) : 0, |
| @@ -862,32 +936,6 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, | |||
| 862 | if (L_ICANON(tty)) | 936 | if (L_ICANON(tty)) |
| 863 | retval = inq_canon(tty); | 937 | retval = inq_canon(tty); |
| 864 | return put_user(retval, (unsigned int __user *) arg); | 938 | return put_user(retval, (unsigned int __user *) arg); |
| 865 | #ifndef TCGETS2 | ||
| 866 | case TIOCGLCKTRMIOS: | ||
| 867 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) | ||
| 868 | return -EFAULT; | ||
| 869 | return 0; | ||
| 870 | |||
| 871 | case TIOCSLCKTRMIOS: | ||
| 872 | if (!capable(CAP_SYS_ADMIN)) | ||
| 873 | return -EPERM; | ||
| 874 | if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) | ||
| 875 | return -EFAULT; | ||
| 876 | return 0; | ||
| 877 | #else | ||
| 878 | case TIOCGLCKTRMIOS: | ||
| 879 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) | ||
| 880 | return -EFAULT; | ||
| 881 | return 0; | ||
| 882 | |||
| 883 | case TIOCSLCKTRMIOS: | ||
| 884 | if (!capable(CAP_SYS_ADMIN)) | ||
| 885 | return -EPERM; | ||
| 886 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg)) | ||
| 887 | return -EFAULT; | ||
| 888 | return 0; | ||
| 889 | #endif | ||
| 890 | |||
| 891 | case TIOCPKT: | 939 | case TIOCPKT: |
| 892 | { | 940 | { |
| 893 | int pktmode; | 941 | int pktmode; |
| @@ -906,19 +954,9 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, | |||
| 906 | tty->packet = 0; | 954 | tty->packet = 0; |
| 907 | return 0; | 955 | return 0; |
| 908 | } | 956 | } |
| 909 | case TIOCGSOFTCAR: | ||
| 910 | return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg); | ||
| 911 | case TIOCSSOFTCAR: | ||
| 912 | if (get_user(arg, (unsigned int __user *) arg)) | ||
| 913 | return -EFAULT; | ||
| 914 | mutex_lock(&tty->termios_mutex); | ||
| 915 | tty->termios->c_cflag = | ||
| 916 | ((tty->termios->c_cflag & ~CLOCAL) | | ||
| 917 | (arg ? CLOCAL : 0)); | ||
| 918 | mutex_unlock(&tty->termios_mutex); | ||
| 919 | return 0; | ||
| 920 | default: | 957 | default: |
| 921 | return -ENOIOCTLCMD; | 958 | /* Try the mode commands */ |
| 959 | return tty_mode_ioctl(tty, file, cmd, arg); | ||
| 922 | } | 960 | } |
| 923 | } | 961 | } |
| 924 | 962 | ||
