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