This source file includes following definitions.
- wait_until_sent
- unset_locked_termios
- set_termios_2
- set_termios
- get_termio
- set_termio
- inq_canon
- n_tty_ioctl
1
2
3
4
5
6
7
8
9
10
11 #include <linux/types.h>
12 #include <linux/termios.h>
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/config.h>
16 #include <linux/kernel.h>
17 #include <linux/major.h>
18 #include <linux/tty.h>
19 #include <linux/fcntl.h>
20 #include <linux/string.h>
21
22 #include <asm/io.h>
23 #include <asm/bitops.h>
24 #include <asm/segment.h>
25 #include <asm/system.h>
26
27 #undef DEBUG
28 #ifdef DEBUG
29 # define PRINTK(x) printk (x)
30 #else
31 # define PRINTK(x)
32 #endif
33
34 extern int session_of_pgrp(int pgrp);
35 extern int kill_pg(int pgrp, int sig, int priv);
36
37 void wait_until_sent(struct tty_struct * tty, int timeout)
38 {
39 struct wait_queue wait = { current, NULL };
40
41 if (!tty->driver.chars_in_buffer ||
42 !tty->driver.chars_in_buffer(tty))
43 return;
44 add_wait_queue(&tty->write_wait, &wait);
45 current->counter = 0;
46 if (timeout)
47 current->timeout = timeout + jiffies;
48 else
49 current->timeout = (unsigned) -1;
50 do {
51 current->state = TASK_INTERRUPTIBLE;
52 if (current->signal & ~current->blocked)
53 break;
54 if (!tty->driver.chars_in_buffer(tty))
55 break;
56 schedule();
57 } while (current->timeout);
58 current->state = TASK_RUNNING;
59 remove_wait_queue(&tty->write_wait, &wait);
60 }
61
62 static void unset_locked_termios(struct termios *termios,
63 struct termios *old,
64 struct termios *locked)
65 {
66 int i;
67
68 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
69
70 if (!locked) {
71 printk("Warning?!? termios_locked is NULL.\n");
72 return;
73 }
74
75 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
76 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
77 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
78 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
79 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
80 for (i=0; i < NCCS; i++)
81 termios->c_cc[i] = locked->c_cc[i] ?
82 old->c_cc[i] : termios->c_cc[i];
83 }
84
85 static int set_termios_2(struct tty_struct * tty, struct termios * termios)
86 {
87 struct termios old_termios = *tty->termios;
88 int canon_change;
89
90 cli();
91 *tty->termios = *termios;
92 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
93 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
94 if (canon_change) {
95 memset(&tty->read_flags, 0, sizeof tty->read_flags);
96 tty->canon_head = tty->read_tail;
97 tty->canon_data = 0;
98 tty->erasing = 0;
99 }
100 sti();
101 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
102
103 wake_up_interruptible(&tty->read_wait);
104
105
106
107 if (tty->link && tty->link->packet) {
108 int old_flow = ((old_termios.c_iflag & IXON) &&
109 (old_termios.c_cc[VSTOP] == '\023') &&
110 (old_termios.c_cc[VSTART] == '\021'));
111 int new_flow = (I_IXON(tty) &&
112 STOP_CHAR(tty) == '\023' &&
113 START_CHAR(tty) == '\021');
114 if (old_flow != new_flow) {
115 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
116 if (new_flow)
117 tty->ctrl_status |= TIOCPKT_DOSTOP;
118 else
119 tty->ctrl_status |= TIOCPKT_NOSTOP;
120 wake_up_interruptible(&tty->link->read_wait);
121 }
122 }
123
124 if (tty->driver.set_termios)
125 (*tty->driver.set_termios)(tty, &old_termios);
126
127 if (tty->ldisc.set_termios)
128 (*tty->ldisc.set_termios)(tty, &old_termios);
129
130 return 0;
131 }
132
133 static int set_termios(struct tty_struct * tty, struct termios * termios)
134 {
135 struct termios tmp_termios;
136
137 memcpy_fromfs(&tmp_termios, termios, sizeof (struct termios));
138 return set_termios_2(tty, &tmp_termios);
139 }
140
141 static int get_termio(struct tty_struct * tty, struct termio * termio)
142 {
143 int i;
144 struct termio tmp_termio;
145
146 i = verify_area(VERIFY_WRITE, termio, sizeof (struct termio));
147 if (i)
148 return i;
149 tmp_termio.c_iflag = tty->termios->c_iflag;
150 tmp_termio.c_oflag = tty->termios->c_oflag;
151 tmp_termio.c_cflag = tty->termios->c_cflag;
152 tmp_termio.c_lflag = tty->termios->c_lflag;
153 tmp_termio.c_line = tty->termios->c_line;
154 for(i=0 ; i < NCC ; i++)
155 tmp_termio.c_cc[i] = tty->termios->c_cc[i];
156 memcpy_tofs(termio, &tmp_termio, sizeof (struct termio));
157 return 0;
158 }
159
160 static int set_termio(struct tty_struct * tty, struct termio * termio)
161 {
162 struct termio tmp_termio;
163 struct termios tmp_termios;
164
165 tmp_termios = *tty->termios;
166 memcpy_fromfs(&tmp_termio, termio, sizeof (struct termio));
167
168 #define SET_LOW_BITS(x,y) ((x) = (0xffff0000 & (x)) | (y))
169
170 SET_LOW_BITS(tmp_termios.c_iflag, tmp_termio.c_iflag);
171 SET_LOW_BITS(tmp_termios.c_oflag, tmp_termio.c_oflag);
172 SET_LOW_BITS(tmp_termios.c_cflag, tmp_termio.c_cflag);
173 SET_LOW_BITS(tmp_termios.c_lflag, tmp_termio.c_lflag);
174 memcpy(&tmp_termios.c_cc, &tmp_termio.c_cc, NCC);
175
176 #undef SET_LOW_BITS
177
178 return set_termios_2(tty, &tmp_termios);
179 }
180
181 static unsigned long inq_canon(struct tty_struct * tty)
182 {
183 int nr, head, tail;
184
185 if (!tty->canon_data || !tty->read_buf)
186 return 0;
187 head = tty->canon_head;
188 tail = tty->read_tail;
189 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
190
191 while (head != tail) {
192 if (test_bit(tail, &tty->read_flags) &&
193 tty->read_buf[tail] == __DISABLED_CHAR)
194 nr--;
195 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
196 }
197 return nr;
198 }
199
200 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
201 unsigned int cmd, unsigned long arg)
202 {
203 struct tty_struct * real_tty;
204 int retval;
205
206 if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
207 tty->driver.subtype == PTY_TYPE_MASTER)
208 real_tty = tty->link;
209 else
210 real_tty = tty;
211
212 switch (cmd) {
213 case TCGETS:
214 retval = verify_area(VERIFY_WRITE, (void *) arg,
215 sizeof (struct termios));
216 if (retval)
217 return retval;
218 memcpy_tofs((struct termios *) arg,
219 real_tty->termios,
220 sizeof (struct termios));
221 return 0;
222 case TCSETSF:
223 case TCSETSW:
224 case TCSETS:
225 retval = tty_check_change(real_tty);
226 if (retval)
227 return retval;
228 if (cmd == TCSETSF || cmd == TCSETSW) {
229 if (cmd == TCSETSF &&
230 real_tty->ldisc.flush_buffer)
231 real_tty->ldisc.flush_buffer(real_tty);
232 wait_until_sent(real_tty, 0);
233 }
234 return set_termios(real_tty,
235 (struct termios *) arg);
236 case TCGETA:
237 return get_termio(real_tty,(struct termio *) arg);
238 case TCSETAF:
239 case TCSETAW:
240 case TCSETA:
241 retval = tty_check_change(real_tty);
242 if (retval)
243 return retval;
244 if (cmd == TCSETAF || cmd == TCSETAW) {
245 if (cmd == TCSETAF &&
246 real_tty->ldisc.flush_buffer)
247 real_tty->ldisc.flush_buffer(real_tty);
248 wait_until_sent(real_tty, 0);
249 }
250 return set_termio(real_tty, (struct termio *) arg);
251 case TCXONC:
252 retval = tty_check_change(tty);
253 if (retval)
254 return retval;
255 switch (arg) {
256 case TCOOFF:
257 stop_tty(tty);
258 break;
259 case TCOON:
260 start_tty(tty);
261 break;
262 case TCIOFF:
263 if (STOP_CHAR(tty) != __DISABLED_CHAR)
264 tty->driver.write(tty, 0,
265 &STOP_CHAR(tty), 1);
266 break;
267 case TCION:
268 if (START_CHAR(tty) != __DISABLED_CHAR)
269 tty->driver.write(tty, 0,
270 &START_CHAR(tty), 1);
271 break;
272 default:
273 return -EINVAL;
274 }
275 return 0;
276 case TCFLSH:
277 retval = tty_check_change(tty);
278 if (retval)
279 return retval;
280 switch (arg) {
281 case TCIFLUSH:
282 if (tty->ldisc.flush_buffer)
283 tty->ldisc.flush_buffer(tty);
284 break;
285 case TCIOFLUSH:
286 if (tty->ldisc.flush_buffer)
287 tty->ldisc.flush_buffer(tty);
288
289 case TCOFLUSH:
290 if (tty->driver.flush_buffer)
291 tty->driver.flush_buffer(tty);
292 break;
293 default:
294 return -EINVAL;
295 }
296 return 0;
297 case TIOCOUTQ:
298 retval = verify_area(VERIFY_WRITE, (void *) arg,
299 sizeof (unsigned long));
300 if (retval)
301 return retval;
302 if (tty->driver.chars_in_buffer)
303 put_fs_long(tty->driver.chars_in_buffer(tty),
304 (unsigned long *) arg);
305 else
306 put_fs_long(0, (unsigned long *) arg);
307 return 0;
308 case TIOCINQ:
309 retval = verify_area(VERIFY_WRITE, (void *) arg,
310 sizeof (unsigned long));
311 if (retval)
312 return retval;
313 if (L_ICANON(tty))
314 put_fs_long(inq_canon(tty),
315 (unsigned long *) arg);
316 else
317 put_fs_long(tty->read_cnt,
318 (unsigned long *) arg);
319 return 0;
320 case TIOCGLCKTRMIOS:
321 arg = get_fs_long((unsigned long *) arg);
322 retval = verify_area(VERIFY_WRITE, (void *) arg,
323 sizeof (struct termios));
324 if (retval)
325 return retval;
326 memcpy_tofs((struct termios *) arg,
327 &real_tty->termios_locked,
328 sizeof (struct termios));
329 return 0;
330 case TIOCSLCKTRMIOS:
331 if (!suser())
332 return -EPERM;
333 arg = get_fs_long((unsigned long *) arg);
334 memcpy_fromfs(&real_tty->termios_locked,
335 (struct termios *) arg,
336 sizeof (struct termios));
337 return 0;
338 case TIOCPKT:
339 if (tty->driver.type != TTY_DRIVER_TYPE_PTY ||
340 tty->driver.subtype != PTY_TYPE_MASTER)
341 return -ENOTTY;
342 retval = verify_area(VERIFY_READ, (void *) arg,
343 sizeof (unsigned long));
344 if (retval)
345 return retval;
346 if (get_fs_long(arg)) {
347 if (!tty->packet) {
348 tty->packet = 1;
349 tty->link->ctrl_status = 0;
350 }
351 } else
352 tty->packet = 0;
353 return 0;
354
355
356 case TCSBRK: case TCSBRKP:
357 retval = tty_check_change(tty);
358 if (retval)
359 return retval;
360 wait_until_sent(tty, 0);
361 if (!tty->driver.ioctl)
362 return 0;
363 tty->driver.ioctl(tty, file, cmd, arg);
364 return 0;
365 default:
366 return -ENOIOCTLCMD;
367 }
368 }