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