This source file includes following definitions.
- put_tty_queue
- get_tty_queue
- tty_write_flush
- tty_read_flush
- change_console
- wait_for_keypress
- copy_to_cooked
- is_ignored
- wait_for_canon_input
- read_chan
- __wait_for_canon_input
- available_canon_input
- write_chan
- tty_read
- tty_write
- tty_lseek
- tty_open
- tty_release
- tty_select
- do_SAK
- initialize_tty_struct
- reset_tty_termios
- tty_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include <linux/types.h>
26 #include <linux/errno.h>
27 #include <linux/signal.h>
28 #include <linux/fcntl.h>
29 #include <linux/sched.h>
30 #include <linux/tty.h>
31 #include <linux/ctype.h>
32 #include <linux/kd.h>
33 #include <linux/mm.h>
34 #include <linux/string.h>
35 #include <linux/keyboard.h>
36
37 #include <asm/segment.h>
38 #include <asm/system.h>
39 #include <asm/bitops.h>
40
41 #include "vt_kern.h"
42
43 struct tty_struct *tty_table[256];
44 struct termios *tty_termios[256];
45
46
47
48
49
50
51
52 int fg_console = 0;
53 struct tty_struct * redirect = NULL;
54 struct wait_queue * keypress_wait = NULL;
55
56 static int initialize_tty_struct(struct tty_struct *tty, int line);
57 static void reset_tty_termios(int line);
58
59 void put_tty_queue(char c, struct tty_queue * queue)
60 {
61 int head;
62 unsigned long flags;
63
64 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
65 head = (queue->head + 1) & (TTY_BUF_SIZE-1);
66 if (head != queue->tail) {
67 queue->buf[queue->head] = c;
68 queue->head = head;
69 }
70 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
71 }
72
73 int get_tty_queue(struct tty_queue * queue)
74 {
75 int result = -1;
76 unsigned long flags;
77
78 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
79 if (queue->tail != queue->head) {
80 result = 0xff & queue->buf[queue->tail];
81 queue->tail = (queue->tail + 1) & (TTY_BUF_SIZE-1);
82 }
83 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
84 return result;
85 }
86
87 void tty_write_flush(struct tty_struct * tty)
88 {
89 if (!tty->write || EMPTY(&tty->write_q))
90 return;
91 if (set_bit(TTY_WRITE_BUSY,&tty->flags))
92 return;
93 tty->write(tty);
94 if (clear_bit(TTY_WRITE_BUSY,&tty->flags))
95 printk("tty_write_flush: bit already cleared\n");
96 }
97
98 void tty_read_flush(struct tty_struct * tty)
99 {
100 if (!tty || EMPTY(&tty->read_q))
101 return;
102 if (set_bit(TTY_READ_BUSY, &tty->flags))
103 return;
104 copy_to_cooked(tty);
105 if (clear_bit(TTY_READ_BUSY, &tty->flags))
106 printk("tty_read_flush: bit already cleared\n");
107 }
108
109 void change_console(unsigned int new_console)
110 {
111 if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
112 return;
113 if (new_console == fg_console || new_console >= NR_CONSOLES)
114 return;
115 update_screen(new_console);
116 }
117
118 void wait_for_keypress(void)
119 {
120 interruptible_sleep_on(&keypress_wait);
121 }
122
123 void copy_to_cooked(struct tty_struct * tty)
124 {
125 int c;
126
127 if (!tty) {
128 printk("copy_to_cooked: called with NULL tty\n");
129 return;
130 }
131 if (!tty->write) {
132 printk("copy_to_cooked: tty %d has null write routine\n",
133 tty->line);
134 }
135 while (1) {
136
137
138
139
140
141 c = LEFT(&tty->secondary);
142 if (tty->throttle && (c < SQ_THRESHOLD_LW)
143 && !set_bit(TTY_SQ_THROTTLED, &tty->flags))
144 tty->throttle(tty, TTY_THROTTLE_SQ_FULL);
145 if (c == 0)
146 break;
147 c = get_tty_queue(&tty->read_q);
148 if (c < 0)
149 break;
150 if (I_STRP(tty))
151 c &= 0x7f;
152 if (c==13) {
153 if (I_CRNL(tty))
154 c=10;
155 else if (I_NOCR(tty))
156 continue;
157 } else if (c==10 && I_NLCR(tty))
158 c=13;
159 if (I_UCLC(tty))
160 c=tolower(c);
161 if (L_CANON(tty)) {
162 if ((KILL_CHAR(tty) != __DISABLED_CHAR) &&
163 (c==KILL_CHAR(tty))) {
164
165 while(!(EMPTY(&tty->secondary) ||
166 (c=LAST(&tty->secondary))==10 ||
167 ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
168 (c==EOF_CHAR(tty))))) {
169 if (L_ECHO(tty)) {
170 if (c<32) {
171 put_tty_queue(8, &tty->write_q);
172 put_tty_queue(' ', &tty->write_q);
173 put_tty_queue(8,&tty->write_q);
174 }
175 put_tty_queue(8,&tty->write_q);
176 put_tty_queue(' ',&tty->write_q);
177 put_tty_queue(8,&tty->write_q);
178 }
179 DEC(tty->secondary.head);
180 }
181 continue;
182 }
183 if ((ERASE_CHAR(tty) != __DISABLED_CHAR) &&
184 (c==ERASE_CHAR(tty))) {
185 if (EMPTY(&tty->secondary) ||
186 (c=LAST(&tty->secondary))==10 ||
187 ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
188 (c==EOF_CHAR(tty))))
189 continue;
190 if (L_ECHO(tty)) {
191 if (c<32) {
192 put_tty_queue(8,&tty->write_q);
193 put_tty_queue(' ',&tty->write_q);
194 put_tty_queue(8,&tty->write_q);
195 }
196 put_tty_queue(8,&tty->write_q);
197 put_tty_queue(32,&tty->write_q);
198 put_tty_queue(8,&tty->write_q);
199 }
200 DEC(tty->secondary.head);
201 continue;
202 }
203 }
204 if (I_IXON(tty)) {
205 if ((STOP_CHAR(tty) != __DISABLED_CHAR) &&
206 (c==STOP_CHAR(tty))) {
207 tty->status_changed = 1;
208 tty->ctrl_status |= TIOCPKT_STOP;
209 tty->stopped=1;
210 continue;
211 }
212 if (((I_IXANY(tty)) && tty->stopped) ||
213 ((START_CHAR(tty) != __DISABLED_CHAR) &&
214 (c==START_CHAR(tty)))) {
215 tty->status_changed = 1;
216 tty->ctrl_status |= TIOCPKT_START;
217 tty->stopped=0;
218 continue;
219 }
220 }
221 if (L_ISIG(tty)) {
222 if ((INTR_CHAR(tty) != __DISABLED_CHAR) &&
223 (c==INTR_CHAR(tty))) {
224 kill_pg(tty->pgrp, SIGINT, 1);
225 flush_input(tty);
226 continue;
227 }
228 if ((QUIT_CHAR(tty) != __DISABLED_CHAR) &&
229 (c==QUIT_CHAR(tty))) {
230 kill_pg(tty->pgrp, SIGQUIT, 1);
231 flush_input(tty);
232 continue;
233 }
234 if ((SUSPEND_CHAR(tty) != __DISABLED_CHAR) &&
235 (c==SUSPEND_CHAR(tty))) {
236 if (!is_orphaned_pgrp(tty->pgrp))
237 kill_pg(tty->pgrp, SIGTSTP, 1);
238 continue;
239 }
240 }
241 if (c==10 || (EOF_CHAR(tty) != __DISABLED_CHAR &&
242 c==EOF_CHAR(tty)))
243 tty->secondary.data++;
244 if ((c==10) && (L_ECHO(tty) || (L_CANON(tty) && L_ECHONL(tty)))) {
245 put_tty_queue(10,&tty->write_q);
246 put_tty_queue(13,&tty->write_q);
247 } else if (L_ECHO(tty)) {
248 if (c<32 && L_ECHOCTL(tty)) {
249 put_tty_queue('^',&tty->write_q);
250 put_tty_queue(c+64, &tty->write_q);
251 } else
252 put_tty_queue(c, &tty->write_q);
253 }
254 put_tty_queue(c, &tty->secondary);
255 }
256 TTY_WRITE_FLUSH(tty);
257 if (!EMPTY(&tty->secondary))
258 wake_up_interruptible(&tty->secondary.proc_list);
259 if (tty->write_q.proc_list && LEFT(&tty->write_q) > TTY_BUF_SIZE/2)
260 wake_up_interruptible(&tty->write_q.proc_list);
261 if (tty->throttle && (LEFT(&tty->read_q) >= RQ_THRESHOLD_HW)
262 && !clear_bit(TTY_RQ_THROTTLED, &tty->flags))
263 tty->throttle(tty, TTY_THROTTLE_RQ_AVAIL);
264 if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW)
265 && !clear_bit(TTY_SQ_THROTTLED, &tty->flags))
266 tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL);
267 }
268
269 int is_ignored(int sig)
270 {
271 return ((current->blocked & (1<<(sig-1))) ||
272 (current->sigaction[sig-1].sa_handler == SIG_IGN));
273 }
274
275 static int available_canon_input(struct tty_struct *);
276 static void __wait_for_canon_input(struct tty_struct *);
277
278 static void wait_for_canon_input(struct tty_struct * tty)
279 {
280 if (!available_canon_input(tty))
281 __wait_for_canon_input(tty);
282 }
283
284 static int read_chan(struct tty_struct * tty, struct file * file, char * buf, int nr)
285 {
286 struct wait_queue wait = { current, NULL };
287 int c;
288 char * b=buf;
289 int minimum,time;
290
291 if (L_CANON(tty))
292 minimum = time = current->timeout = 0;
293 else {
294 time = 10L*tty->termios->c_cc[VTIME];
295 minimum = tty->termios->c_cc[VMIN];
296 if (minimum)
297 current->timeout = 0xffffffff;
298 else {
299 if (time)
300 current->timeout = time + jiffies;
301 else
302 current->timeout = 0;
303 time = 0;
304 minimum = 1;
305 }
306 }
307 if (file->f_flags & O_NONBLOCK) {
308 time = current->timeout = 0;
309 if (L_CANON(tty)) {
310 if (!available_canon_input(tty))
311 return -EAGAIN;
312 }
313 } else if (L_CANON(tty)) {
314 wait_for_canon_input(tty);
315 if (current->signal & ~current->blocked)
316 return -ERESTARTSYS;
317 }
318 if (minimum>nr)
319 minimum = nr;
320
321
322 if (tty->packet && tty->link && tty->link->status_changed) {
323 put_fs_byte (tty->link->ctrl_status, b);
324 tty->link->status_changed = 0;
325 return 1;
326 }
327
328
329 if (tty->packet) {
330 put_fs_byte (0,b++);
331 nr--;
332
333
334 if (nr == 0)
335 return 1;
336 }
337 add_wait_queue(&tty->secondary.proc_list, &wait);
338 while (nr>0) {
339 TTY_READ_FLUSH(tty);
340 if (tty->link)
341 TTY_WRITE_FLUSH(tty->link);
342 while (nr > 0 && ((c = get_tty_queue(&tty->secondary)) >= 0)) {
343 if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
344 c==EOF_CHAR(tty)) || c==10)
345 tty->secondary.data--;
346 if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
347 c==EOF_CHAR(tty)) && L_CANON(tty))
348 break;
349 put_fs_byte(c,b++);
350 nr--;
351 if (time)
352 current->timeout = time+jiffies;
353 if (c==10 && L_CANON(tty))
354 break;
355 };
356 wake_up_interruptible(&tty->read_q.proc_list);
357
358
359
360
361 if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW)
362 && !clear_bit(TTY_SQ_THROTTLED, &tty->flags))
363 tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL);
364 if (b-buf >= minimum || !current->timeout)
365 break;
366 if (current->signal & ~current->blocked)
367 break;
368 if (tty->link && !tty->link->count)
369 break;
370 TTY_READ_FLUSH(tty);
371 if (tty->link)
372 TTY_WRITE_FLUSH(tty->link);
373 if (!EMPTY(&tty->secondary))
374 continue;
375 current->state = TASK_INTERRUPTIBLE;
376 if (EMPTY(&tty->secondary))
377 schedule();
378 current->state = TASK_RUNNING;
379 }
380 remove_wait_queue(&tty->secondary.proc_list, &wait);
381 TTY_READ_FLUSH(tty);
382 if (tty->link && tty->link->write)
383 TTY_WRITE_FLUSH(tty->link);
384 current->timeout = 0;
385
386
387
388 if (tty->packet) {
389 if ((b-buf) > 1)
390 return b-buf;
391 } else {
392 if (b-buf)
393 return b-buf;
394 }
395
396 if (current->signal & ~current->blocked)
397 return -ERESTARTSYS;
398 if (file->f_flags & O_NONBLOCK)
399 return -EAGAIN;
400 return 0;
401 }
402
403 static void __wait_for_canon_input(struct tty_struct * tty)
404 {
405 struct wait_queue wait = { current, NULL };
406
407 add_wait_queue(&tty->secondary.proc_list, &wait);
408 while (1) {
409 current->state = TASK_INTERRUPTIBLE;
410 if (available_canon_input(tty))
411 break;
412 schedule();
413 }
414 current->state = TASK_RUNNING;
415 remove_wait_queue(&tty->secondary.proc_list, &wait);
416 }
417
418 static int available_canon_input(struct tty_struct * tty)
419 {
420 TTY_READ_FLUSH(tty);
421 if (tty->link)
422 if (tty->link->count)
423 TTY_WRITE_FLUSH(tty->link);
424 else
425 return 1;
426 if (current->signal & ~current->blocked)
427 return 1;
428 if (FULL(&tty->read_q))
429 return 1;
430 if (tty->secondary.data)
431 return 1;
432 return 0;
433 }
434
435 static int write_chan(struct tty_struct * tty, struct file * file, char * buf, int nr)
436 {
437 struct wait_queue wait = { current, NULL };
438 char c, *b=buf;
439
440 if (nr < 0)
441 return -EINVAL;
442 if (!nr)
443 return 0;
444 add_wait_queue(&tty->write_q.proc_list, &wait);
445 while (nr>0) {
446 if (current->signal & ~current->blocked)
447 break;
448 if (tty->link && !tty->link->count) {
449 send_sig(SIGPIPE,current,0);
450 break;
451 }
452 current->state = TASK_INTERRUPTIBLE;
453 if (FULL(&tty->write_q)) {
454 TTY_WRITE_FLUSH(tty);
455 if (FULL(&tty->write_q))
456 schedule();
457 current->state = TASK_RUNNING;
458 continue;
459 }
460 current->state = TASK_RUNNING;
461 while (nr>0 && !FULL(&tty->write_q)) {
462 c=get_fs_byte(b);
463 if (O_POST(tty)) {
464 if (c=='\r' && O_CRNL(tty))
465 c='\n';
466 else if (c=='\n' && O_NLRET(tty))
467 c='\r';
468 if (c=='\n' && O_NLCR(tty) &&
469 !set_bit(TTY_CR_PENDING,&tty->flags)) {
470 put_tty_queue(13,&tty->write_q);
471 continue;
472 }
473 if (O_LCUC(tty))
474 c=toupper(c);
475 }
476 b++; nr--;
477 clear_bit(TTY_CR_PENDING,&tty->flags);
478 put_tty_queue(c,&tty->write_q);
479 }
480 if (need_resched)
481 schedule();
482 }
483 remove_wait_queue(&tty->write_q.proc_list, &wait);
484 TTY_WRITE_FLUSH(tty);
485 if (b-buf)
486 return b-buf;
487 if (tty->link && !tty->link->count)
488 return -EPIPE;
489 if (current->signal & ~current->blocked)
490 return -ERESTARTSYS;
491 return 0;
492 }
493
494 static int tty_read(struct inode * inode, struct file * file, char * buf, int count)
495 {
496 int i, dev;
497 struct tty_struct * tty;
498
499 dev = file->f_rdev;
500 if (MAJOR(dev) != 4) {
501 printk("tty_read: pseudo-major != 4\n");
502 return -EINVAL;
503 }
504 dev = MINOR(dev);
505 tty = TTY_TABLE(dev);
506 if (!tty)
507 return -EIO;
508 if (MINOR(inode->i_rdev) && (tty->pgrp > 0) &&
509 (current->tty == dev) &&
510 (tty->pgrp != current->pgrp))
511 if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
512 return -EIO;
513 else {
514 (void) kill_pg(current->pgrp, SIGTTIN, 1);
515 return -ERESTARTSYS;
516 }
517 i = read_chan(tty,file,buf,count);
518 if (i > 0)
519 inode->i_atime = CURRENT_TIME;
520 return i;
521 }
522
523 static int tty_write(struct inode * inode, struct file * file, char * buf, int count)
524 {
525 int dev,i;
526 struct tty_struct * tty;
527
528 dev = file->f_rdev;
529 if (MAJOR(dev) != 4) {
530 printk("tty_write: pseudo-major != 4\n");
531 return -EINVAL;
532 }
533 dev = MINOR(dev);
534 if (redirect && ((dev == 0) || (dev == fg_console+1)))
535 tty = redirect;
536 else
537 tty = TTY_TABLE(dev);
538 if (!tty || !tty->write)
539 return -EIO;
540 if (MINOR(inode->i_rdev) &&
541 L_TOSTOP(tty) && (tty->pgrp > 0) &&
542 (current->tty == dev) && (tty->pgrp != current->pgrp)) {
543 if (is_orphaned_pgrp(tty->pgrp))
544 return -EIO;
545 if (!is_ignored(SIGTTOU)) {
546 (void) kill_pg(current->pgrp, SIGTTOU, 1);
547 return -ERESTARTSYS;
548 }
549 }
550 i = write_chan(tty,file,buf,count);
551 if (i > 0)
552 inode->i_mtime = CURRENT_TIME;
553 return i;
554 }
555
556 static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
557 {
558 return -EBADF;
559 }
560
561
562
563
564
565
566
567
568
569
570
571
572 static int tty_open(struct inode * inode, struct file * filp)
573 {
574 struct tty_struct *tty, *o_tty;
575 int dev, retval;
576
577 dev = inode->i_rdev;
578 if (MAJOR(dev) == 5)
579 dev = current->tty;
580 else
581 dev = MINOR(dev);
582 if (dev < 0)
583 return -ENXIO;
584 if (!dev)
585 dev = fg_console + 1;
586 filp->f_rdev = 0x0400 | dev;
587
588
589
590 tty = o_tty = NULL;
591 if (!tty_table[dev]) {
592 tty = (struct tty_struct *) get_free_page(GFP_KERNEL);
593 if (tty) {
594 retval = initialize_tty_struct(tty, dev);
595 if (retval) {
596 free_page((unsigned long)tty);
597 return retval;
598 }
599 }
600 }
601 if (IS_A_PTY(dev)) {
602 if (!tty_table[PTY_OTHER(dev)]) {
603 o_tty = (struct tty_struct *) get_free_page(GFP_KERNEL);
604 if (o_tty) {
605 retval = initialize_tty_struct(o_tty, PTY_OTHER(dev));
606 if (retval) {
607 free_page((unsigned long) tty);
608 free_page((unsigned long) o_tty);
609 return retval;
610 }
611 }
612 }
613 if (!o_tty && !tty_table[PTY_OTHER(dev)]) {
614 free_page((unsigned long) tty);
615 return -ENOMEM;
616 }
617 }
618 if (tty_table[dev]) {
619 free_page((unsigned long) tty);
620 tty = tty_table[dev];
621 } else if (tty)
622 tty_table[dev] = tty;
623 else {
624 free_page((unsigned long) o_tty);
625 return -ENOMEM;
626 }
627 if (IS_A_PTY(dev)) {
628 if (tty_table[PTY_OTHER(dev)]) {
629 free_page((unsigned long) o_tty);
630 o_tty = tty_table[PTY_OTHER(dev)];
631 } else
632 tty_table[PTY_OTHER(dev)] = o_tty;
633 tty->link = o_tty;
634 o_tty->link = tty;
635 }
636 if (IS_A_PTY_MASTER(dev)) {
637 if (tty->count)
638 return -EAGAIN;
639 if (tty->link && tty->link->count++ == 0)
640 reset_tty_termios(PTY_OTHER(dev));
641 reset_tty_termios(dev);
642 } else if (IS_A_PTY_SLAVE(dev)) {
643 if (tty->count == 0)
644 reset_tty_termios(dev);
645 }
646 tty->count++;
647 retval = 0;
648
649
650 tty->status_changed = 0;
651 tty->ctrl_status = 0;
652 tty->packet = 0;
653
654 if (!(filp->f_flags & O_NOCTTY) &&
655 current->leader &&
656 current->tty<0 &&
657 tty->session==0) {
658 current->tty = dev;
659 tty->session = current->session;
660 tty->pgrp = current->pgrp;
661 }
662 if (tty->open)
663 retval = tty->open(tty, filp);
664 else
665 retval = -ENODEV;
666 if (retval) {
667 tty->count--;
668 if (IS_A_PTY_MASTER(dev) && tty->link)
669 tty->link->count--;
670 }
671 return retval;
672 }
673
674
675
676
677
678
679 static void tty_release(struct inode * inode, struct file * filp)
680 {
681 int dev;
682 struct tty_struct * tty;
683
684 dev = filp->f_rdev;
685 if (MAJOR(dev) != 4) {
686 printk("tty_release: tty pseudo-major != 4\n");
687 return;
688 }
689 dev = MINOR(filp->f_rdev);
690 if (!dev)
691 dev = fg_console+1;
692 tty = tty_table[dev];
693 if (!tty) {
694 printk("tty_release: tty_table[%d] was NULL\n", dev);
695 return;
696 }
697 if (IS_A_PTY_MASTER(dev) && tty->link) {
698 if (--tty->link->count < 0) {
699 printk("tty_release: bad tty slave count (dev = %d): %d\n",
700 dev, tty->count);
701 tty->link->count = 0;
702 }
703 }
704 if (--tty->count < 0) {
705 printk("tty_release: bad tty_table[%d]->count: %d\n",
706 dev, tty->count);
707 tty->count = 0;
708 }
709 if (tty->count)
710 return;
711 if (tty->close)
712 tty->close(tty, filp);
713 if (tty == redirect)
714 redirect = NULL;
715 if (tty->link && !tty->link->count && (tty->link == redirect))
716 redirect = NULL;
717 if (tty->link) {
718 if (tty->link->count)
719 return;
720 free_page((unsigned long) tty_table[PTY_OTHER(dev)]);
721 tty_table[PTY_OTHER(dev)] = 0;
722 }
723 free_page((unsigned long) tty_table[dev]);
724 tty_table[dev] = 0;
725 }
726
727 static int tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
728 {
729 int dev;
730 struct tty_struct * tty;
731
732 dev = filp->f_rdev;
733 if (MAJOR(dev) != 4) {
734 printk("tty_select: tty pseudo-major != 4\n");
735 return 0;
736 }
737 dev = MINOR(filp->f_rdev);
738 tty = TTY_TABLE(dev);
739 if (!tty) {
740 printk("tty_select: tty struct for dev %d was NULL\n", dev);
741 return 0;
742 }
743 switch (sel_type) {
744 case SEL_IN:
745 if (!EMPTY(&tty->secondary))
746 return 1;
747 if (tty->link && !tty->link->count)
748 return 1;
749
750
751 if (tty->packet && tty->link &&
752 tty->link->status_changed)
753 return 1;
754
755 select_wait(&tty->secondary.proc_list, wait);
756 return 0;
757 case SEL_OUT:
758 if (!FULL(&tty->write_q))
759 return 1;
760 select_wait(&tty->write_q.proc_list, wait);
761 return 0;
762 case SEL_EX:
763 if (tty->link && !tty->link->count)
764 return 1;
765 return 0;
766 }
767 return 0;
768 }
769
770 static struct file_operations tty_fops = {
771 tty_lseek,
772 tty_read,
773 tty_write,
774 NULL,
775 tty_select,
776 tty_ioctl,
777 NULL,
778 tty_open,
779 tty_release
780 };
781
782
783
784
785
786
787
788
789
790
791
792
793
794 void do_SAK( struct tty_struct *tty)
795 {
796 struct task_struct **p;
797 int line = tty->line;
798 int session = tty->session;
799 int i;
800 struct file *filp;
801
802 flush_input(tty);
803 flush_output(tty);
804 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
805 if (!(*p))
806 continue;
807 if (((*p)->tty == line) ||
808 ((session > 0) && ((*p)->session == session)))
809 send_sig(SIGKILL, *p, 1);
810 else {
811 for (i=0; i < NR_FILE; i++) {
812 filp = (*p)->filp[i];
813 if (filp && (filp->f_op == &tty_fops) &&
814 (MINOR(filp->f_rdev) == line)) {
815 send_sig(SIGKILL, *p, 1);
816 break;
817 }
818 }
819 }
820 }
821 }
822
823
824
825
826
827 static int initialize_tty_struct(struct tty_struct *tty, int line)
828 {
829 memset(tty, 0, sizeof(struct tty_struct));
830 tty->line = line;
831 tty->pgrp = -1;
832 tty->winsize.ws_row = 24;
833 tty->winsize.ws_col = 80;
834 if (!tty_termios[line]) {
835 tty_termios[line] = kmalloc(sizeof(struct termios), GFP_KERNEL);
836 if (!tty_termios[line])
837 return -ENOMEM;
838 reset_tty_termios(line);
839 }
840 tty->termios = tty_termios[line];
841
842 if (IS_A_CONSOLE(line)) {
843 tty->open = con_open;
844 tty->winsize.ws_row = video_num_lines;
845 tty->winsize.ws_col = video_num_columns;
846 } else if IS_A_SERIAL(line) {
847 tty->open = rs_open;
848 } else if IS_A_PTY(line) {
849 tty->open = pty_open;
850 }
851 return 0;
852 }
853
854 static void reset_tty_termios(int line)
855 {
856 struct termios *tp = tty_termios[line];
857
858 if (!tp) {
859 printk("termios of line was NULL\n");
860 return;
861 }
862 memset(tp, 0, sizeof(struct termios));
863 memcpy(tp->c_cc, INIT_C_CC, NCCS);
864 if (IS_A_CONSOLE(line)) {
865 tp->c_iflag = ICRNL | IXON;
866 tp->c_oflag = OPOST | ONLCR;
867 tp->c_cflag = B38400 | CS8 | CREAD;
868 tp->c_lflag = ISIG | ICANON | ECHO | ECHOCTL | ECHOKE;
869 } else if (IS_A_SERIAL(line)) {
870 tp->c_cflag = B2400 | CS8 | CREAD | HUPCL;
871 } else if (IS_A_PTY_MASTER(line)) {
872 tp->c_cflag = B9600 | CS8 | CREAD;
873 } else if (IS_A_PTY_SLAVE(line)) {
874 tp->c_iflag = ICRNL | IXON;
875 tp->c_oflag = OPOST | ONLCR;
876 tp->c_cflag = B38400 | CS8 | CREAD;
877 tp->c_lflag = ISIG | ICANON | ECHO | ECHOCTL | ECHOKE;
878 }
879 }
880
881 long tty_init(long kmem_start)
882 {
883 int i;
884
885 chrdev_fops[4] = &tty_fops;
886 chrdev_fops[5] = &tty_fops;
887 for (i=0 ; i<256 ; i++) {
888 tty_table[i] = 0;
889 tty_termios[i] = 0;
890 }
891 kmem_start = kbd_init(kmem_start);
892 kmem_start = con_init(kmem_start);
893 kmem_start = rs_init(kmem_start);
894 printk("%d virtual consoles\n\r",NR_CONSOLES);
895 return kmem_start;
896 }