This source file includes following definitions.
- flush
- flush_input
- flush_output
- wait_until_sent
- do_get_ps_info
- get_termios
- set_termios
- get_termio
- set_termio
- set_window_size
- get_window_size
- tty_ioctl
1
2
3
4
5
6
7 #include <linux/types.h>
8 #include <linux/termios.h>
9 #include <linux/errno.h>
10 #include <linux/sched.h>
11 #include <linux/kernel.h>
12 #include <linux/tty.h>
13 #include <linux/fcntl.h>
14
15 #include <asm/io.h>
16 #include <asm/segment.h>
17 #include <asm/system.h>
18
19 extern int session_of_pgrp(int pgrp);
20 extern int do_screendump(int arg);
21 extern int kill_pg(int pgrp, int sig, int priv);
22 extern int vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg);
23
24 static void flush(struct tty_queue * queue)
25 {
26 if (queue) {
27 cli();
28 queue->head = queue->tail;
29 sti();
30 wake_up(&queue->proc_list);
31 }
32 }
33
34 void flush_input(struct tty_struct * tty)
35 {
36 if (tty->read_q) {
37 flush(tty->read_q);
38 wake_up(&tty->read_q->proc_list);
39 }
40 if (tty->secondary) {
41 flush(tty->secondary);
42 tty->secondary->data = 0;
43 }
44 if ((tty = tty->link) && tty->write_q) {
45 flush(tty->write_q);
46 wake_up(&tty->write_q->proc_list);
47 }
48 }
49
50 void flush_output(struct tty_struct * tty)
51 {
52 if (tty->write_q) {
53 flush(tty->write_q);
54 wake_up(&tty->write_q->proc_list);
55 }
56 if (tty = tty->link) {
57 if (tty->read_q) {
58 flush(tty->read_q);
59 wake_up(&tty->read_q->proc_list);
60 }
61 if (tty->secondary) {
62 flush(tty->secondary);
63 tty->secondary->data = 0;
64 }
65 }
66 }
67
68 void wait_until_sent(struct tty_struct * tty)
69 {
70 while (!(current->signal & ~current->blocked) && !EMPTY(tty->write_q)) {
71 TTY_WRITE_FLUSH(tty);
72 current->counter = 0;
73 cli();
74 if (EMPTY(tty->write_q))
75 break;
76 else
77 interruptible_sleep_on(&tty->write_q->proc_list);
78 sti();
79 }
80 sti();
81 }
82
83 static int do_get_ps_info(int arg)
84 {
85 struct tstruct {
86 int flag;
87 int present[NR_TASKS];
88 struct task_struct tasks[NR_TASKS];
89 };
90 struct tstruct *ts = (struct tstruct *)arg;
91 struct task_struct **p;
92 char *c, *d;
93 int i, n = 0;
94
95 verify_area((void *)arg, sizeof(struct tstruct));
96
97 for (p = &FIRST_TASK ; p <= &LAST_TASK ; p++, n++)
98 if (*p)
99 {
100 c = (char *)(*p);
101 d = (char *)(ts->tasks+n);
102 for (i=0 ; i<sizeof(struct task_struct) ; i++)
103 put_fs_byte(*c++, d++);
104 put_fs_long(1, (unsigned long *)(ts->present+n));
105 }
106 else
107 put_fs_long(0, (unsigned long *)(ts->present+n));
108 return(0);
109 }
110
111 static int get_termios(struct tty_struct * tty, struct termios * termios)
112 {
113 int i;
114
115 verify_area(termios, sizeof (*termios));
116 for (i=0 ; i< (sizeof (*termios)) ; i++)
117 put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );
118 return 0;
119 }
120
121 static int set_termios(struct tty_struct * tty, struct termios * termios,
122 int channel)
123 {
124 int i;
125 unsigned short old_cflag = tty->termios.c_cflag;
126
127
128
129
130 if ((current->tty == channel) &&
131 (tty->pgrp != current->pgrp)) {
132 if (is_orphaned_pgrp(current->pgrp))
133 return -EIO;
134 if (!is_ignored(SIGTTOU))
135 return tty_signal(SIGTTOU, tty);
136 }
137 for (i=0 ; i< (sizeof (*termios)) ; i++)
138 ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
139 if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
140 change_speed(channel-64);
141 return 0;
142 }
143
144 static int get_termio(struct tty_struct * tty, struct termio * termio)
145 {
146 int i;
147 struct termio tmp_termio;
148
149 verify_area(termio, sizeof (*termio));
150 tmp_termio.c_iflag = tty->termios.c_iflag;
151 tmp_termio.c_oflag = tty->termios.c_oflag;
152 tmp_termio.c_cflag = tty->termios.c_cflag;
153 tmp_termio.c_lflag = tty->termios.c_lflag;
154 tmp_termio.c_line = tty->termios.c_line;
155 for(i=0 ; i < NCC ; i++)
156 tmp_termio.c_cc[i] = tty->termios.c_cc[i];
157 for (i=0 ; i< (sizeof (*termio)) ; i++)
158 put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
159 return 0;
160 }
161
162
163
164
165 static int set_termio(struct tty_struct * tty, struct termio * termio,
166 int channel)
167 {
168 int i;
169 struct termio tmp_termio;
170 unsigned short old_cflag = tty->termios.c_cflag;
171
172 if ((current->tty == channel) &&
173 (tty->pgrp > 0) &&
174 (tty->pgrp != current->pgrp)) {
175 if (is_orphaned_pgrp(current->pgrp))
176 return -EIO;
177 if (!is_ignored(SIGTTOU))
178 return tty_signal(SIGTTOU, tty);
179 }
180 for (i=0 ; i< (sizeof (*termio)) ; i++)
181 ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
182 *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
183 *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
184 *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
185 *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;
186 tty->termios.c_line = tmp_termio.c_line;
187 for(i=0 ; i < NCC ; i++)
188 tty->termios.c_cc[i] = tmp_termio.c_cc[i];
189 if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
190 change_speed(channel-64);
191 return 0;
192 }
193
194 static int set_window_size(struct tty_struct * tty, struct winsize * ws)
195 {
196 int i,changed;
197 char c, * tmp;
198
199 if (!ws)
200 return -EINVAL;
201 tmp = (char *) &tty->winsize;
202 changed = 0;
203 for (i = 0; i < sizeof (*ws) ; i++,tmp++) {
204 c = get_fs_byte(i + (char *) ws);
205 if (c == *tmp)
206 continue;
207 changed = 1;
208 *tmp = c;
209 }
210 if (changed)
211 kill_pg(tty->pgrp, SIGWINCH, 1);
212 return 0;
213 }
214
215 static int get_window_size(struct tty_struct * tty, struct winsize * ws)
216 {
217 int i;
218 char * tmp;
219
220 if (!ws)
221 return -EINVAL;
222 verify_area(ws, sizeof (*ws));
223 tmp = (char *) ws;
224 for (i = 0; i < sizeof (struct winsize) ; i++,tmp++)
225 put_fs_byte(((char *) &tty->winsize)[i], tmp);
226 return 0;
227 }
228
229 int tty_ioctl(struct inode * inode, struct file * file,
230 unsigned int cmd, unsigned int arg)
231 {
232 struct tty_struct * tty;
233 struct tty_struct * other_tty;
234 int pgrp;
235 int dev;
236
237 if (MAJOR(file->f_rdev) != 4) {
238 printk("tty_ioctl: tty pseudo-major != 4\n");
239 return -EINVAL;
240 }
241 dev = MINOR(file->f_rdev);
242 tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);
243
244 if (IS_A_PTY(dev))
245 other_tty = tty_table + PTY_OTHER(dev);
246 else
247 other_tty = NULL;
248
249 if (!(tty->write_q && tty->read_q && tty->secondary && tty->write))
250 return -EINVAL;
251 switch (cmd) {
252 case TCGETS:
253 return get_termios(tty,(struct termios *) arg);
254 case TCSETSF:
255 flush_input(tty);
256
257 case TCSETSW:
258 wait_until_sent(tty);
259
260 case TCSETS:
261 return set_termios(tty,(struct termios *) arg, dev);
262 case TCGETA:
263 return get_termio(tty,(struct termio *) arg);
264 case TCSETAF:
265 flush_input(tty);
266
267 case TCSETAW:
268 wait_until_sent(tty);
269 case TCSETA:
270 return set_termio(tty,(struct termio *) arg, dev);
271 case TCSBRK:
272 if (!IS_A_SERIAL(dev))
273 return -EINVAL;
274 wait_until_sent(tty);
275 if (!arg)
276 send_break(dev-64);
277 return 0;
278 case TCXONC:
279 switch (arg) {
280 case TCOOFF:
281 tty->stopped = 1;
282 TTY_WRITE_FLUSH(tty);
283 return 0;
284 case TCOON:
285 tty->stopped = 0;
286 TTY_WRITE_FLUSH(tty);
287 return 0;
288 case TCIOFF:
289 if (STOP_CHAR(tty))
290 put_tty_queue(STOP_CHAR(tty),tty->write_q);
291 return 0;
292 case TCION:
293 if (START_CHAR(tty))
294 put_tty_queue(START_CHAR(tty),tty->write_q);
295 return 0;
296 }
297 return -EINVAL;
298 case TCFLSH:
299 if (arg==0)
300 flush_input(tty);
301 else if (arg==1)
302 flush_output(tty);
303 else if (arg==2) {
304 flush_input(tty);
305 flush_output(tty);
306 } else
307 return -EINVAL;
308 return 0;
309 case TIOCEXCL:
310 return -EINVAL;
311 case TIOCNXCL:
312 return -EINVAL;
313 case TIOCSCTTY:
314 return -EINVAL;
315 case TIOCGPGRP:
316 verify_area((void *) arg,4);
317 put_fs_long(tty->pgrp,(unsigned long *) arg);
318 return 0;
319 case TIOCSPGRP:
320 if ((current->tty < 0) ||
321 (current->tty != dev) ||
322 (tty->session != current->session))
323 return -ENOTTY;
324 pgrp=get_fs_long((unsigned long *) arg);
325 if (pgrp < 0)
326 return -EINVAL;
327 if (session_of_pgrp(pgrp) != current->session)
328 return -EPERM;
329 tty->pgrp = pgrp;
330 return 0;
331 case TIOCOUTQ:
332 verify_area((void *) arg,4);
333 put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
334 return 0;
335 case TIOCINQ:
336 verify_area((void *) arg,4);
337 if (L_CANON(tty) && !tty->secondary->data)
338 put_fs_long(0, (unsigned long *) arg);
339 else
340 put_fs_long(CHARS(tty->secondary),
341 (unsigned long *) arg);
342 return 0;
343 case TIOCSTI:
344 return -EINVAL;
345 case TIOCGWINSZ:
346 return get_window_size(tty,(struct winsize *) arg);
347 case TIOCSWINSZ:
348 if (IS_A_PTY_MASTER(dev))
349 set_window_size(other_tty,(struct winsize *) arg);
350 return set_window_size(tty,(struct winsize *) arg);
351 case TIOCMGET:
352 return -EINVAL;
353 case TIOCMBIS:
354 return -EINVAL;
355 case TIOCMBIC:
356 return -EINVAL;
357 case TIOCMSET:
358 return -EINVAL;
359 case TIOCGSOFTCAR:
360 return -EINVAL;
361 case TIOCSSOFTCAR:
362 return -EINVAL;
363 case TIOCLINUX:
364 switch (get_fs_byte((char *)arg))
365 {
366 case 0:
367 return do_screendump(arg);
368 case 1:
369 return do_get_ps_info(arg);
370 default:
371 return -EINVAL;
372 }
373 case TIOCCONS:
374 if (!IS_A_PTY(dev))
375 return -EINVAL;
376 if (redirect)
377 return -EBUSY;
378 if (!suser())
379 return -EPERM;
380 if (IS_A_PTY_MASTER(dev))
381 redirect = other_tty;
382 else
383 redirect = tty;
384 return 0;
385 case TIOCGSERIAL:
386 if (!IS_A_SERIAL(dev))
387 return -EINVAL;
388 verify_area((void *) arg,sizeof(struct serial_struct));
389 return get_serial_info(dev-64,(struct serial_struct *) arg);
390 case TIOCSSERIAL:
391 if (!IS_A_SERIAL(dev))
392 return -EINVAL;
393 return set_serial_info(dev-64,(struct serial_struct *) arg);
394 case FIONBIO:
395 if (arg)
396 file->f_flags |= O_NONBLOCK;
397 else
398 file->f_flags &= ~O_NONBLOCK;
399 return 0;
400 case TIOCNOTTY:
401 if (MINOR(file->f_rdev) != current->tty)
402 return -EINVAL;
403 current->tty = -1;
404 if (current->leader) {
405 if (tty->pgrp > 0)
406 kill_pg(tty->pgrp, SIGHUP, 0);
407 tty->pgrp = -1;
408 tty->session = 0;
409 }
410 return 0;
411 default:
412 return vt_ioctl(tty, dev, cmd, arg);
413 }
414 }