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