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