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

source code of linux/arch/sparc/kernel/termios.c