termios.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/termios_internal.h>
  3. /*
  4. * c_cc characters in the termio structure. Oh, how I love being
  5. * backwardly compatible. Notice that character 4 and 5 are
  6. * interpreted differently depending on whether ICANON is set in
  7. * c_lflag. If it's set, they are used as _VEOF and _VEOL, otherwise
  8. * as _VMIN and V_TIME. This is for compatibility with OSF/1 (which
  9. * is compatible with sysV)...
  10. */
  11. #define _VMIN 4
  12. #define _VTIME 5
  13. int kernel_termios_to_user_termio(struct termio __user *termio,
  14. struct ktermios *termios)
  15. {
  16. struct termio v;
  17. memset(&v, 0, sizeof(struct termio));
  18. v.c_iflag = termios->c_iflag;
  19. v.c_oflag = termios->c_oflag;
  20. v.c_cflag = termios->c_cflag;
  21. v.c_lflag = termios->c_lflag;
  22. v.c_line = termios->c_line;
  23. memcpy(v.c_cc, termios->c_cc, NCC);
  24. if (!(v.c_lflag & ICANON)) {
  25. v.c_cc[_VMIN] = termios->c_cc[VMIN];
  26. v.c_cc[_VTIME] = termios->c_cc[VTIME];
  27. }
  28. return copy_to_user(termio, &v, sizeof(struct termio));
  29. }
  30. int user_termios_to_kernel_termios(struct ktermios *k,
  31. struct termios2 __user *u)
  32. {
  33. int err;
  34. err = get_user(k->c_iflag, &u->c_iflag);
  35. err |= get_user(k->c_oflag, &u->c_oflag);
  36. err |= get_user(k->c_cflag, &u->c_cflag);
  37. err |= get_user(k->c_lflag, &u->c_lflag);
  38. err |= get_user(k->c_line, &u->c_line);
  39. err |= copy_from_user(k->c_cc, u->c_cc, NCCS);
  40. if (k->c_lflag & ICANON) {
  41. err |= get_user(k->c_cc[VEOF], &u->c_cc[VEOF]);
  42. err |= get_user(k->c_cc[VEOL], &u->c_cc[VEOL]);
  43. } else {
  44. err |= get_user(k->c_cc[VMIN], &u->c_cc[_VMIN]);
  45. err |= get_user(k->c_cc[VTIME], &u->c_cc[_VTIME]);
  46. }
  47. err |= get_user(k->c_ispeed, &u->c_ispeed);
  48. err |= get_user(k->c_ospeed, &u->c_ospeed);
  49. return err;
  50. }
  51. int kernel_termios_to_user_termios(struct termios2 __user *u,
  52. struct ktermios *k)
  53. {
  54. int err;
  55. err = put_user(k->c_iflag, &u->c_iflag);
  56. err |= put_user(k->c_oflag, &u->c_oflag);
  57. err |= put_user(k->c_cflag, &u->c_cflag);
  58. err |= put_user(k->c_lflag, &u->c_lflag);
  59. err |= put_user(k->c_line, &u->c_line);
  60. err |= copy_to_user(u->c_cc, k->c_cc, NCCS);
  61. if (!(k->c_lflag & ICANON)) {
  62. err |= put_user(k->c_cc[VMIN], &u->c_cc[_VMIN]);
  63. err |= put_user(k->c_cc[VTIME], &u->c_cc[_VTIME]);
  64. } else {
  65. err |= put_user(k->c_cc[VEOF], &u->c_cc[VEOF]);
  66. err |= put_user(k->c_cc[VEOL], &u->c_cc[VEOL]);
  67. }
  68. err |= put_user(k->c_ispeed, &u->c_ispeed);
  69. err |= put_user(k->c_ospeed, &u->c_ospeed);
  70. return err;
  71. }
  72. int user_termios_to_kernel_termios_1(struct ktermios *k,
  73. struct termios __user *u)
  74. {
  75. int err;
  76. err = get_user(k->c_iflag, &u->c_iflag);
  77. err |= get_user(k->c_oflag, &u->c_oflag);
  78. err |= get_user(k->c_cflag, &u->c_cflag);
  79. err |= get_user(k->c_lflag, &u->c_lflag);
  80. err |= get_user(k->c_line, &u->c_line);
  81. err |= copy_from_user(k->c_cc, u->c_cc, NCCS);
  82. if (k->c_lflag & ICANON) {
  83. err |= get_user(k->c_cc[VEOF], &u->c_cc[VEOF]);
  84. err |= get_user(k->c_cc[VEOL], &u->c_cc[VEOL]);
  85. } else {
  86. err |= get_user(k->c_cc[VMIN], &u->c_cc[_VMIN]);
  87. err |= get_user(k->c_cc[VTIME], &u->c_cc[_VTIME]);
  88. }
  89. return err;
  90. }
  91. int kernel_termios_to_user_termios_1(struct termios __user *u,
  92. struct ktermios *k)
  93. {
  94. int err;
  95. err = put_user(k->c_iflag, &u->c_iflag);
  96. err |= put_user(k->c_oflag, &u->c_oflag);
  97. err |= put_user(k->c_cflag, &u->c_cflag);
  98. err |= put_user(k->c_lflag, &u->c_lflag);
  99. err |= put_user(k->c_line, &u->c_line);
  100. err |= copy_to_user(u->c_cc, k->c_cc, NCCS);
  101. if (!(k->c_lflag & ICANON)) {
  102. err |= put_user(k->c_cc[VMIN], &u->c_cc[_VMIN]);
  103. err |= put_user(k->c_cc[VTIME], &u->c_cc[_VTIME]);
  104. } else {
  105. err |= put_user(k->c_cc[VEOF], &u->c_cc[VEOF]);
  106. err |= put_user(k->c_cc[VEOL], &u->c_cc[VEOL]);
  107. }
  108. return err;
  109. }