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