diff options
Diffstat (limited to 'drivers/char/tty_ioctl.c')
-rw-r--r-- | drivers/char/tty_ioctl.c | 362 |
1 files changed, 180 insertions, 182 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index d4b6d64e858b..f95a80b2265f 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -50,11 +50,11 @@ | |||
50 | * Locking: none | 50 | * Locking: none |
51 | */ | 51 | */ |
52 | 52 | ||
53 | void tty_wait_until_sent(struct tty_struct * tty, long timeout) | 53 | void tty_wait_until_sent(struct tty_struct *tty, long timeout) |
54 | { | 54 | { |
55 | #ifdef TTY_DEBUG_WAIT_UNTIL_SENT | 55 | #ifdef TTY_DEBUG_WAIT_UNTIL_SENT |
56 | char buf[64]; | 56 | char buf[64]; |
57 | 57 | ||
58 | printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf)); | 58 | printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf)); |
59 | #endif | 59 | #endif |
60 | if (!tty->driver->chars_in_buffer) | 60 | if (!tty->driver->chars_in_buffer) |
@@ -67,7 +67,6 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout) | |||
67 | if (tty->driver->wait_until_sent) | 67 | if (tty->driver->wait_until_sent) |
68 | tty->driver->wait_until_sent(tty, timeout); | 68 | tty->driver->wait_until_sent(tty, timeout); |
69 | } | 69 | } |
70 | |||
71 | EXPORT_SYMBOL(tty_wait_until_sent); | 70 | EXPORT_SYMBOL(tty_wait_until_sent); |
72 | 71 | ||
73 | static void unset_locked_termios(struct ktermios *termios, | 72 | static void unset_locked_termios(struct ktermios *termios, |
@@ -75,8 +74,8 @@ static void unset_locked_termios(struct ktermios *termios, | |||
75 | struct ktermios *locked) | 74 | struct ktermios *locked) |
76 | { | 75 | { |
77 | int i; | 76 | int i; |
78 | 77 | ||
79 | #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z))) | 78 | #define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z))) |
80 | 79 | ||
81 | if (!locked) { | 80 | if (!locked) { |
82 | printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n"); | 81 | printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n"); |
@@ -88,7 +87,7 @@ static void unset_locked_termios(struct ktermios *termios, | |||
88 | NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag); | 87 | NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag); |
89 | NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag); | 88 | NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag); |
90 | termios->c_line = locked->c_line ? old->c_line : termios->c_line; | 89 | termios->c_line = locked->c_line ? old->c_line : termios->c_line; |
91 | for (i=0; i < NCCS; i++) | 90 | for (i = 0; i < NCCS; i++) |
92 | termios->c_cc[i] = locked->c_cc[i] ? | 91 | termios->c_cc[i] = locked->c_cc[i] ? |
93 | old->c_cc[i] : termios->c_cc[i]; | 92 | old->c_cc[i] : termios->c_cc[i]; |
94 | /* FIXME: What should we do for i/ospeed */ | 93 | /* FIXME: What should we do for i/ospeed */ |
@@ -163,7 +162,6 @@ speed_t tty_termios_baud_rate(struct ktermios *termios) | |||
163 | } | 162 | } |
164 | return baud_table[cbaud]; | 163 | return baud_table[cbaud]; |
165 | } | 164 | } |
166 | |||
167 | EXPORT_SYMBOL(tty_termios_baud_rate); | 165 | EXPORT_SYMBOL(tty_termios_baud_rate); |
168 | 166 | ||
169 | /** | 167 | /** |
@@ -203,7 +201,6 @@ speed_t tty_termios_input_baud_rate(struct ktermios *termios) | |||
203 | return tty_termios_baud_rate(termios); | 201 | return tty_termios_baud_rate(termios); |
204 | #endif | 202 | #endif |
205 | } | 203 | } |
206 | |||
207 | EXPORT_SYMBOL(tty_termios_input_baud_rate); | 204 | EXPORT_SYMBOL(tty_termios_input_baud_rate); |
208 | 205 | ||
209 | /** | 206 | /** |
@@ -338,7 +335,6 @@ speed_t tty_get_baud_rate(struct tty_struct *tty) | |||
338 | 335 | ||
339 | return baud; | 336 | return baud; |
340 | } | 337 | } |
341 | |||
342 | EXPORT_SYMBOL(tty_get_baud_rate); | 338 | EXPORT_SYMBOL(tty_get_baud_rate); |
343 | 339 | ||
344 | /** | 340 | /** |
@@ -361,7 +357,6 @@ void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old) | |||
361 | new->c_ispeed = old->c_ispeed; | 357 | new->c_ispeed = old->c_ispeed; |
362 | new->c_ospeed = old->c_ospeed; | 358 | new->c_ospeed = old->c_ospeed; |
363 | } | 359 | } |
364 | |||
365 | EXPORT_SYMBOL(tty_termios_copy_hw); | 360 | EXPORT_SYMBOL(tty_termios_copy_hw); |
366 | 361 | ||
367 | /** | 362 | /** |
@@ -395,16 +390,16 @@ EXPORT_SYMBOL(tty_termios_hw_change); | |||
395 | * Locking: termios_sem | 390 | * Locking: termios_sem |
396 | */ | 391 | */ |
397 | 392 | ||
398 | static void change_termios(struct tty_struct * tty, struct ktermios * new_termios) | 393 | static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) |
399 | { | 394 | { |
400 | int canon_change; | 395 | int canon_change; |
401 | struct ktermios old_termios = *tty->termios; | 396 | struct ktermios old_termios = *tty->termios; |
402 | struct tty_ldisc *ld; | 397 | struct tty_ldisc *ld; |
403 | 398 | ||
404 | /* | 399 | /* |
405 | * Perform the actual termios internal changes under lock. | 400 | * Perform the actual termios internal changes under lock. |
406 | */ | 401 | */ |
407 | 402 | ||
408 | 403 | ||
409 | /* FIXME: we need to decide on some locking/ordering semantics | 404 | /* FIXME: we need to decide on some locking/ordering semantics |
410 | for the set_termios notification eventually */ | 405 | for the set_termios notification eventually */ |
@@ -419,7 +414,7 @@ static void change_termios(struct tty_struct * tty, struct ktermios * new_termio | |||
419 | tty->canon_data = 0; | 414 | tty->canon_data = 0; |
420 | tty->erasing = 0; | 415 | tty->erasing = 0; |
421 | } | 416 | } |
422 | 417 | ||
423 | /* This bit should be in the ldisc code */ | 418 | /* This bit should be in the ldisc code */ |
424 | if (canon_change && !L_ICANON(tty) && tty->read_cnt) | 419 | if (canon_change && !L_ICANON(tty) && tty->read_cnt) |
425 | /* Get characters left over from canonical mode. */ | 420 | /* Get characters left over from canonical mode. */ |
@@ -442,7 +437,7 @@ static void change_termios(struct tty_struct * tty, struct ktermios * new_termio | |||
442 | wake_up_interruptible(&tty->link->read_wait); | 437 | wake_up_interruptible(&tty->link->read_wait); |
443 | } | 438 | } |
444 | } | 439 | } |
445 | 440 | ||
446 | if (tty->driver->set_termios) | 441 | if (tty->driver->set_termios) |
447 | (*tty->driver->set_termios)(tty, &old_termios); | 442 | (*tty->driver->set_termios)(tty, &old_termios); |
448 | else | 443 | else |
@@ -470,7 +465,7 @@ static void change_termios(struct tty_struct * tty, struct ktermios * new_termio | |||
470 | * Called functions take ldisc and termios_sem locks | 465 | * Called functions take ldisc and termios_sem locks |
471 | */ | 466 | */ |
472 | 467 | ||
473 | static int set_termios(struct tty_struct * tty, void __user *arg, int opt) | 468 | static int set_termios(struct tty_struct *tty, void __user *arg, int opt) |
474 | { | 469 | { |
475 | struct ktermios tmp_termios; | 470 | struct ktermios tmp_termios; |
476 | struct tty_ldisc *ld; | 471 | struct tty_ldisc *ld; |
@@ -501,19 +496,19 @@ static int set_termios(struct tty_struct * tty, void __user *arg, int opt) | |||
501 | return -EFAULT; | 496 | return -EFAULT; |
502 | #endif | 497 | #endif |
503 | 498 | ||
504 | /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed | 499 | /* If old style Bfoo values are used then load c_ispeed/c_ospeed |
505 | so its unconditionally usable */ | 500 | * with the real speed so its unconditionally usable */ |
506 | tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); | 501 | tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); |
507 | tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); | 502 | tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); |
508 | 503 | ||
509 | ld = tty_ldisc_ref(tty); | 504 | ld = tty_ldisc_ref(tty); |
510 | 505 | ||
511 | if (ld != NULL) { | 506 | if (ld != NULL) { |
512 | if ((opt & TERMIOS_FLUSH) && ld->flush_buffer) | 507 | if ((opt & TERMIOS_FLUSH) && ld->flush_buffer) |
513 | ld->flush_buffer(tty); | 508 | ld->flush_buffer(tty); |
514 | tty_ldisc_deref(ld); | 509 | tty_ldisc_deref(ld); |
515 | } | 510 | } |
516 | 511 | ||
517 | if (opt & TERMIOS_WAIT) { | 512 | if (opt & TERMIOS_WAIT) { |
518 | tty_wait_until_sent(tty, 0); | 513 | tty_wait_until_sent(tty, 0); |
519 | if (signal_pending(current)) | 514 | if (signal_pending(current)) |
@@ -529,14 +524,14 @@ static int set_termios(struct tty_struct * tty, void __user *arg, int opt) | |||
529 | return 0; | 524 | return 0; |
530 | } | 525 | } |
531 | 526 | ||
532 | static int get_termio(struct tty_struct * tty, struct termio __user * termio) | 527 | static int get_termio(struct tty_struct *tty, struct termio __user *termio) |
533 | { | 528 | { |
534 | if (kernel_termios_to_user_termio(termio, tty->termios)) | 529 | if (kernel_termios_to_user_termio(termio, tty->termios)) |
535 | return -EFAULT; | 530 | return -EFAULT; |
536 | return 0; | 531 | return 0; |
537 | } | 532 | } |
538 | 533 | ||
539 | static unsigned long inq_canon(struct tty_struct * tty) | 534 | static unsigned long inq_canon(struct tty_struct *tty) |
540 | { | 535 | { |
541 | int nr, head, tail; | 536 | int nr, head, tail; |
542 | 537 | ||
@@ -561,7 +556,7 @@ static unsigned long inq_canon(struct tty_struct * tty) | |||
561 | * | 556 | * |
562 | * The "sg_flags" translation is a joke.. | 557 | * The "sg_flags" translation is a joke.. |
563 | */ | 558 | */ |
564 | static int get_sgflags(struct tty_struct * tty) | 559 | static int get_sgflags(struct tty_struct *tty) |
565 | { | 560 | { |
566 | int flags = 0; | 561 | int flags = 0; |
567 | 562 | ||
@@ -579,7 +574,7 @@ static int get_sgflags(struct tty_struct * tty) | |||
579 | return flags; | 574 | return flags; |
580 | } | 575 | } |
581 | 576 | ||
582 | static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) | 577 | static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) |
583 | { | 578 | { |
584 | struct sgttyb tmp; | 579 | struct sgttyb tmp; |
585 | 580 | ||
@@ -590,11 +585,11 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) | |||
590 | tmp.sg_kill = tty->termios->c_cc[VKILL]; | 585 | tmp.sg_kill = tty->termios->c_cc[VKILL]; |
591 | tmp.sg_flags = get_sgflags(tty); | 586 | tmp.sg_flags = get_sgflags(tty); |
592 | mutex_unlock(&tty->termios_mutex); | 587 | mutex_unlock(&tty->termios_mutex); |
593 | 588 | ||
594 | return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; | 589 | return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
595 | } | 590 | } |
596 | 591 | ||
597 | static void set_sgflags(struct ktermios * termios, int flags) | 592 | static void set_sgflags(struct ktermios *termios, int flags) |
598 | { | 593 | { |
599 | termios->c_iflag = ICRNL | IXON; | 594 | termios->c_iflag = ICRNL | IXON; |
600 | termios->c_oflag = 0; | 595 | termios->c_oflag = 0; |
@@ -631,7 +626,7 @@ static void set_sgflags(struct ktermios * termios, int flags) | |||
631 | * Locking: termios_sem | 626 | * Locking: termios_sem |
632 | */ | 627 | */ |
633 | 628 | ||
634 | static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) | 629 | static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) |
635 | { | 630 | { |
636 | int retval; | 631 | int retval; |
637 | struct sgttyb tmp; | 632 | struct sgttyb tmp; |
@@ -640,7 +635,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) | |||
640 | retval = tty_check_change(tty); | 635 | retval = tty_check_change(tty); |
641 | if (retval) | 636 | if (retval) |
642 | return retval; | 637 | return retval; |
643 | 638 | ||
644 | if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) | 639 | if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) |
645 | return -EFAULT; | 640 | return -EFAULT; |
646 | 641 | ||
@@ -651,7 +646,8 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) | |||
651 | set_sgflags(&termios, tmp.sg_flags); | 646 | set_sgflags(&termios, tmp.sg_flags); |
652 | /* Try and encode into Bfoo format */ | 647 | /* Try and encode into Bfoo format */ |
653 | #ifdef BOTHER | 648 | #ifdef BOTHER |
654 | tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed); | 649 | tty_termios_encode_baud_rate(&termios, termios.c_ispeed, |
650 | termios.c_ospeed); | ||
655 | #endif | 651 | #endif |
656 | mutex_unlock(&tty->termios_mutex); | 652 | mutex_unlock(&tty->termios_mutex); |
657 | change_termios(tty, &termios); | 653 | change_termios(tty, &termios); |
@@ -660,7 +656,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) | |||
660 | #endif | 656 | #endif |
661 | 657 | ||
662 | #ifdef TIOCGETC | 658 | #ifdef TIOCGETC |
663 | static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars) | 659 | static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars) |
664 | { | 660 | { |
665 | struct tchars tmp; | 661 | struct tchars tmp; |
666 | 662 | ||
@@ -673,7 +669,7 @@ static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars) | |||
673 | return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; | 669 | return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
674 | } | 670 | } |
675 | 671 | ||
676 | static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars) | 672 | static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars) |
677 | { | 673 | { |
678 | struct tchars tmp; | 674 | struct tchars tmp; |
679 | 675 | ||
@@ -690,20 +686,22 @@ static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars) | |||
690 | #endif | 686 | #endif |
691 | 687 | ||
692 | #ifdef TIOCGLTC | 688 | #ifdef TIOCGLTC |
693 | static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars) | 689 | static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) |
694 | { | 690 | { |
695 | struct ltchars tmp; | 691 | struct ltchars tmp; |
696 | 692 | ||
697 | tmp.t_suspc = tty->termios->c_cc[VSUSP]; | 693 | tmp.t_suspc = tty->termios->c_cc[VSUSP]; |
698 | tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */ | 694 | /* what is dsuspc anyway? */ |
695 | tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; | ||
699 | tmp.t_rprntc = tty->termios->c_cc[VREPRINT]; | 696 | tmp.t_rprntc = tty->termios->c_cc[VREPRINT]; |
700 | tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */ | 697 | /* what is flushc anyway? */ |
698 | tmp.t_flushc = tty->termios->c_cc[VEOL2]; | ||
701 | tmp.t_werasc = tty->termios->c_cc[VWERASE]; | 699 | tmp.t_werasc = tty->termios->c_cc[VWERASE]; |
702 | tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; | 700 | tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; |
703 | return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; | 701 | return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
704 | } | 702 | } |
705 | 703 | ||
706 | static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars) | 704 | static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) |
707 | { | 705 | { |
708 | struct ltchars tmp; | 706 | struct ltchars tmp; |
709 | 707 | ||
@@ -711,9 +709,11 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars) | |||
711 | return -EFAULT; | 709 | return -EFAULT; |
712 | 710 | ||
713 | tty->termios->c_cc[VSUSP] = tmp.t_suspc; | 711 | tty->termios->c_cc[VSUSP] = tmp.t_suspc; |
714 | tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */ | 712 | /* what is dsuspc anyway? */ |
713 | tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; | ||
715 | tty->termios->c_cc[VREPRINT] = tmp.t_rprntc; | 714 | tty->termios->c_cc[VREPRINT] = tmp.t_rprntc; |
716 | tty->termios->c_cc[VEOL2] = tmp.t_flushc; /* what is flushc anyway? */ | 715 | /* what is flushc anyway? */ |
716 | tty->termios->c_cc[VEOL2] = tmp.t_flushc; | ||
717 | tty->termios->c_cc[VWERASE] = tmp.t_werasc; | 717 | tty->termios->c_cc[VWERASE] = tmp.t_werasc; |
718 | tty->termios->c_cc[VLNEXT] = tmp.t_lnextc; | 718 | tty->termios->c_cc[VLNEXT] = tmp.t_lnextc; |
719 | return 0; | 719 | return 0; |
@@ -761,10 +761,10 @@ static int send_prio_char(struct tty_struct *tty, char ch) | |||
761 | * consistent mode setting. | 761 | * consistent mode setting. |
762 | */ | 762 | */ |
763 | 763 | ||
764 | int tty_mode_ioctl(struct tty_struct * tty, struct file *file, | 764 | int tty_mode_ioctl(struct tty_struct *tty, struct file *file, |
765 | unsigned int cmd, unsigned long arg) | 765 | unsigned int cmd, unsigned long arg) |
766 | { | 766 | { |
767 | struct tty_struct * real_tty; | 767 | struct tty_struct *real_tty; |
768 | void __user *p = (void __user *)arg; | 768 | void __user *p = (void __user *)arg; |
769 | 769 | ||
770 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 770 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -775,100 +775,100 @@ int tty_mode_ioctl(struct tty_struct * tty, struct file *file, | |||
775 | 775 | ||
776 | switch (cmd) { | 776 | switch (cmd) { |
777 | #ifdef TIOCGETP | 777 | #ifdef TIOCGETP |
778 | case TIOCGETP: | 778 | case TIOCGETP: |
779 | return get_sgttyb(real_tty, (struct sgttyb __user *) arg); | 779 | return get_sgttyb(real_tty, (struct sgttyb __user *) arg); |
780 | case TIOCSETP: | 780 | case TIOCSETP: |
781 | case TIOCSETN: | 781 | case TIOCSETN: |
782 | return set_sgttyb(real_tty, (struct sgttyb __user *) arg); | 782 | return set_sgttyb(real_tty, (struct sgttyb __user *) arg); |
783 | #endif | 783 | #endif |
784 | #ifdef TIOCGETC | 784 | #ifdef TIOCGETC |
785 | case TIOCGETC: | 785 | case TIOCGETC: |
786 | return get_tchars(real_tty, p); | 786 | return get_tchars(real_tty, p); |
787 | case TIOCSETC: | 787 | case TIOCSETC: |
788 | return set_tchars(real_tty, p); | 788 | return set_tchars(real_tty, p); |
789 | #endif | 789 | #endif |
790 | #ifdef TIOCGLTC | 790 | #ifdef TIOCGLTC |
791 | case TIOCGLTC: | 791 | case TIOCGLTC: |
792 | return get_ltchars(real_tty, p); | 792 | return get_ltchars(real_tty, p); |
793 | case TIOCSLTC: | 793 | case TIOCSLTC: |
794 | return set_ltchars(real_tty, p); | 794 | return set_ltchars(real_tty, p); |
795 | #endif | 795 | #endif |
796 | case TCSETSF: | 796 | case TCSETSF: |
797 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD); | 797 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD); |
798 | case TCSETSW: | 798 | case TCSETSW: |
799 | return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD); | 799 | return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD); |
800 | case TCSETS: | 800 | case TCSETS: |
801 | return set_termios(real_tty, p, TERMIOS_OLD); | 801 | return set_termios(real_tty, p, TERMIOS_OLD); |
802 | #ifndef TCGETS2 | 802 | #ifndef TCGETS2 |
803 | case TCGETS: | 803 | case TCGETS: |
804 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) | 804 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) |
805 | return -EFAULT; | 805 | return -EFAULT; |
806 | return 0; | 806 | return 0; |
807 | #else | 807 | #else |
808 | case TCGETS: | 808 | case TCGETS: |
809 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) | 809 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) |
810 | return -EFAULT; | 810 | return -EFAULT; |
811 | return 0; | 811 | return 0; |
812 | case TCGETS2: | 812 | case TCGETS2: |
813 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) | 813 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) |
814 | return -EFAULT; | 814 | return -EFAULT; |
815 | return 0; | 815 | return 0; |
816 | case TCSETSF2: | 816 | case TCSETSF2: |
817 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); | 817 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); |
818 | case TCSETSW2: | 818 | case TCSETSW2: |
819 | return set_termios(real_tty, p, TERMIOS_WAIT); | 819 | return set_termios(real_tty, p, TERMIOS_WAIT); |
820 | case TCSETS2: | 820 | case TCSETS2: |
821 | return set_termios(real_tty, p, 0); | 821 | return set_termios(real_tty, p, 0); |
822 | #endif | 822 | #endif |
823 | case TCGETA: | 823 | case TCGETA: |
824 | return get_termio(real_tty, p); | 824 | return get_termio(real_tty, p); |
825 | case TCSETAF: | 825 | case TCSETAF: |
826 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO); | 826 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO); |
827 | case TCSETAW: | 827 | case TCSETAW: |
828 | return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); | 828 | return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); |
829 | case TCSETA: | 829 | case TCSETA: |
830 | return set_termios(real_tty, p, TERMIOS_TERMIO); | 830 | return set_termios(real_tty, p, TERMIOS_TERMIO); |
831 | #ifndef TCGETS2 | 831 | #ifndef TCGETS2 |
832 | case TIOCGLCKTRMIOS: | 832 | case TIOCGLCKTRMIOS: |
833 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) | 833 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) |
834 | return -EFAULT; | 834 | return -EFAULT; |
835 | return 0; | 835 | return 0; |
836 | 836 | case TIOCSLCKTRMIOS: | |
837 | case TIOCSLCKTRMIOS: | 837 | if (!capable(CAP_SYS_ADMIN)) |
838 | if (!capable(CAP_SYS_ADMIN)) | 838 | return -EPERM; |
839 | return -EPERM; | 839 | if (user_termios_to_kernel_termios(real_tty->termios_locked, |
840 | if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) | 840 | (struct termios __user *) arg)) |
841 | return -EFAULT; | 841 | return -EFAULT; |
842 | return 0; | 842 | return 0; |
843 | #else | 843 | #else |
844 | case TIOCGLCKTRMIOS: | 844 | case TIOCGLCKTRMIOS: |
845 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) | 845 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) |
846 | return -EFAULT; | 846 | return -EFAULT; |
847 | return 0; | 847 | return 0; |
848 | 848 | case TIOCSLCKTRMIOS: | |
849 | case TIOCSLCKTRMIOS: | 849 | if (!capable(CAP_SYS_ADMIN)) |
850 | if (!capable(CAP_SYS_ADMIN)) | 850 | return -EPERM; |
851 | return -EPERM; | 851 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, |
852 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg)) | 852 | (struct termios __user *) arg)) |
853 | return -EFAULT; | 853 | return -EFAULT; |
854 | return 0; | 854 | return 0; |
855 | #endif | 855 | #endif |
856 | case TIOCGSOFTCAR: | 856 | case TIOCGSOFTCAR: |
857 | return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg); | 857 | return put_user(C_CLOCAL(tty) ? 1 : 0, |
858 | case TIOCSSOFTCAR: | 858 | (int __user *)arg); |
859 | if (get_user(arg, (unsigned int __user *) arg)) | 859 | case TIOCSSOFTCAR: |
860 | return -EFAULT; | 860 | if (get_user(arg, (unsigned int __user *) arg)) |
861 | mutex_lock(&tty->termios_mutex); | 861 | return -EFAULT; |
862 | tty->termios->c_cflag = | 862 | mutex_lock(&tty->termios_mutex); |
863 | ((tty->termios->c_cflag & ~CLOCAL) | | 863 | tty->termios->c_cflag = |
864 | (arg ? CLOCAL : 0)); | 864 | ((tty->termios->c_cflag & ~CLOCAL) | |
865 | mutex_unlock(&tty->termios_mutex); | 865 | (arg ? CLOCAL : 0)); |
866 | return 0; | 866 | mutex_unlock(&tty->termios_mutex); |
867 | default: | 867 | return 0; |
868 | return -ENOIOCTLCMD; | 868 | default: |
869 | return -ENOIOCTLCMD; | ||
869 | } | 870 | } |
870 | } | 871 | } |
871 | |||
872 | EXPORT_SYMBOL_GPL(tty_mode_ioctl); | 872 | EXPORT_SYMBOL_GPL(tty_mode_ioctl); |
873 | 873 | ||
874 | int tty_perform_flush(struct tty_struct *tty, unsigned long arg) | 874 | int tty_perform_flush(struct tty_struct *tty, unsigned long arg) |
@@ -899,13 +899,12 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg) | |||
899 | tty_ldisc_deref(ld); | 899 | tty_ldisc_deref(ld); |
900 | return 0; | 900 | return 0; |
901 | } | 901 | } |
902 | |||
903 | EXPORT_SYMBOL_GPL(tty_perform_flush); | 902 | EXPORT_SYMBOL_GPL(tty_perform_flush); |
904 | 903 | ||
905 | int n_tty_ioctl(struct tty_struct * tty, struct file * file, | 904 | int n_tty_ioctl(struct tty_struct *tty, struct file *file, |
906 | unsigned int cmd, unsigned long arg) | 905 | unsigned int cmd, unsigned long arg) |
907 | { | 906 | { |
908 | struct tty_struct * real_tty; | 907 | struct tty_struct *real_tty; |
909 | int retval; | 908 | int retval; |
910 | 909 | ||
911 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 910 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -915,68 +914,67 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, | |||
915 | real_tty = tty; | 914 | real_tty = tty; |
916 | 915 | ||
917 | switch (cmd) { | 916 | switch (cmd) { |
918 | case TCXONC: | 917 | case TCXONC: |
919 | retval = tty_check_change(tty); | 918 | retval = tty_check_change(tty); |
920 | if (retval) | 919 | if (retval) |
921 | return retval; | 920 | return retval; |
922 | switch (arg) { | 921 | switch (arg) { |
923 | case TCOOFF: | 922 | case TCOOFF: |
924 | if (!tty->flow_stopped) { | 923 | if (!tty->flow_stopped) { |
925 | tty->flow_stopped = 1; | 924 | tty->flow_stopped = 1; |
926 | stop_tty(tty); | 925 | stop_tty(tty); |
927 | } | ||
928 | break; | ||
929 | case TCOON: | ||
930 | if (tty->flow_stopped) { | ||
931 | tty->flow_stopped = 0; | ||
932 | start_tty(tty); | ||
933 | } | ||
934 | break; | ||
935 | case TCIOFF: | ||
936 | if (STOP_CHAR(tty) != __DISABLED_CHAR) | ||
937 | return send_prio_char(tty, STOP_CHAR(tty)); | ||
938 | break; | ||
939 | case TCION: | ||
940 | if (START_CHAR(tty) != __DISABLED_CHAR) | ||
941 | return send_prio_char(tty, START_CHAR(tty)); | ||
942 | break; | ||
943 | default: | ||
944 | return -EINVAL; | ||
945 | } | 926 | } |
946 | return 0; | 927 | break; |
947 | case TCFLSH: | 928 | case TCOON: |
948 | return tty_perform_flush(tty, arg); | 929 | if (tty->flow_stopped) { |
949 | case TIOCOUTQ: | 930 | tty->flow_stopped = 0; |
950 | return put_user(tty->driver->chars_in_buffer ? | 931 | start_tty(tty); |
951 | tty->driver->chars_in_buffer(tty) : 0, | 932 | } |
952 | (int __user *) arg); | 933 | break; |
953 | case TIOCINQ: | 934 | case TCIOFF: |
954 | retval = tty->read_cnt; | 935 | if (STOP_CHAR(tty) != __DISABLED_CHAR) |
955 | if (L_ICANON(tty)) | 936 | return send_prio_char(tty, STOP_CHAR(tty)); |
956 | retval = inq_canon(tty); | 937 | break; |
957 | return put_user(retval, (unsigned int __user *) arg); | 938 | case TCION: |
958 | case TIOCPKT: | 939 | if (START_CHAR(tty) != __DISABLED_CHAR) |
959 | { | 940 | return send_prio_char(tty, START_CHAR(tty)); |
960 | int pktmode; | 941 | break; |
961 | |||
962 | if (tty->driver->type != TTY_DRIVER_TYPE_PTY || | ||
963 | tty->driver->subtype != PTY_TYPE_MASTER) | ||
964 | return -ENOTTY; | ||
965 | if (get_user(pktmode, (int __user *) arg)) | ||
966 | return -EFAULT; | ||
967 | if (pktmode) { | ||
968 | if (!tty->packet) { | ||
969 | tty->packet = 1; | ||
970 | tty->link->ctrl_status = 0; | ||
971 | } | ||
972 | } else | ||
973 | tty->packet = 0; | ||
974 | return 0; | ||
975 | } | ||
976 | default: | 942 | default: |
977 | /* Try the mode commands */ | 943 | return -EINVAL; |
978 | return tty_mode_ioctl(tty, file, cmd, arg); | ||
979 | } | 944 | } |
945 | return 0; | ||
946 | case TCFLSH: | ||
947 | return tty_perform_flush(tty, arg); | ||
948 | case TIOCOUTQ: | ||
949 | return put_user(tty->driver->chars_in_buffer ? | ||
950 | tty->driver->chars_in_buffer(tty) : 0, | ||
951 | (int __user *) arg); | ||
952 | case TIOCINQ: | ||
953 | retval = tty->read_cnt; | ||
954 | if (L_ICANON(tty)) | ||
955 | retval = inq_canon(tty); | ||
956 | return put_user(retval, (unsigned int __user *) arg); | ||
957 | case TIOCPKT: | ||
958 | { | ||
959 | int pktmode; | ||
960 | |||
961 | if (tty->driver->type != TTY_DRIVER_TYPE_PTY || | ||
962 | tty->driver->subtype != PTY_TYPE_MASTER) | ||
963 | return -ENOTTY; | ||
964 | if (get_user(pktmode, (int __user *) arg)) | ||
965 | return -EFAULT; | ||
966 | if (pktmode) { | ||
967 | if (!tty->packet) { | ||
968 | tty->packet = 1; | ||
969 | tty->link->ctrl_status = 0; | ||
970 | } | ||
971 | } else | ||
972 | tty->packet = 0; | ||
973 | return 0; | ||
974 | } | ||
975 | default: | ||
976 | /* Try the mode commands */ | ||
977 | return tty_mode_ioctl(tty, file, cmd, arg); | ||
978 | } | ||
980 | } | 979 | } |
981 | |||
982 | EXPORT_SYMBOL(n_tty_ioctl); | 980 | EXPORT_SYMBOL(n_tty_ioctl); |