This source file includes following definitions.
- put_tty_queue
- get_tty_queue
- tty_write_flush
- tty_read_flush
- hung_up_tty_read
- hung_up_tty_write
- hung_up_tty_select
- tty_lseek
- tty_hangup
- hung_up
- vt_waitactive
- complete_change_console
- 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
- init_dev
- release_dev
- tty_open
- tty_release
- tty_select
- do_SAK
- initialize_tty_struct
- initialize_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/timer.h>
32 #include <linux/ctype.h>
33 #include <linux/kd.h>
34 #include <linux/mm.h>
35 #include <linux/string.h>
36 #include <linux/keyboard.h>
37
38 #include <asm/segment.h>
39 #include <asm/system.h>
40 #include <asm/bitops.h>
41
42 #include "vt_kern.h"
43
44 struct tty_struct *tty_table[256];
45 struct termios *tty_termios[256];
46
47
48
49
50
51
52
53 int fg_console = 0;
54 struct tty_struct * redirect = NULL;
55 struct wait_queue * keypress_wait = NULL;
56
57 static void initialize_tty_struct(int line, struct tty_struct *tty);
58 static void initialize_termios(int line, struct termios *tp);
59
60 static int tty_read(struct inode *, struct file *, char *, int);
61 static int tty_write(struct inode *, struct file *, char *, int);
62 static int tty_select(struct inode *, struct file *, int, select_table *);
63 static int tty_open(struct inode *, struct file *);
64 static void tty_release(struct inode *, struct file *);
65
66 void put_tty_queue(char c, struct tty_queue * queue)
67 {
68 int head;
69 unsigned long flags;
70
71 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
72 head = (queue->head + 1) & (TTY_BUF_SIZE-1);
73 if (head != queue->tail) {
74 queue->buf[queue->head] = c;
75 queue->head = head;
76 }
77 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
78 }
79
80 int get_tty_queue(struct tty_queue * queue)
81 {
82 int result = -1;
83 unsigned long flags;
84
85 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
86 if (queue->tail != queue->head) {
87 result = 0xff & queue->buf[queue->tail];
88 queue->tail = (queue->tail + 1) & (TTY_BUF_SIZE-1);
89 }
90 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
91 return result;
92 }
93
94 void tty_write_flush(struct tty_struct * tty)
95 {
96 if (!tty->write || EMPTY(&tty->write_q))
97 return;
98 if (set_bit(TTY_WRITE_BUSY,&tty->flags))
99 return;
100 tty->write(tty);
101 if (clear_bit(TTY_WRITE_BUSY,&tty->flags))
102 printk("tty_write_flush: bit already cleared\n");
103 }
104
105 void tty_read_flush(struct tty_struct * tty)
106 {
107 if (!tty || EMPTY(&tty->read_q))
108 return;
109 if (set_bit(TTY_READ_BUSY, &tty->flags))
110 return;
111 copy_to_cooked(tty);
112 if (clear_bit(TTY_READ_BUSY, &tty->flags))
113 printk("tty_read_flush: bit already cleared\n");
114 }
115
116 static int hung_up_tty_read(struct inode * inode, struct file * file, char * buf, int count)
117 {
118 return 0;
119 }
120
121 static int hung_up_tty_write(struct inode * inode, struct file * file, char * buf, int count)
122 {
123 return -EIO;
124 }
125
126 static int hung_up_tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
127 {
128 return 1;
129 }
130
131 static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
132 {
133 return -ESPIPE;
134 }
135
136 static struct file_operations tty_fops = {
137 tty_lseek,
138 tty_read,
139 tty_write,
140 NULL,
141 tty_select,
142 tty_ioctl,
143 NULL,
144 tty_open,
145 tty_release
146 };
147
148 static struct file_operations hung_up_tty_fops = {
149 tty_lseek,
150 hung_up_tty_read,
151 hung_up_tty_write,
152 NULL,
153 hung_up_tty_select,
154 tty_ioctl,
155 NULL,
156 tty_open,
157 tty_release
158 };
159
160 void tty_hangup(struct tty_struct * tty)
161 {
162 struct file * filp;
163 int dev;
164
165 if (!tty)
166 return;
167 dev = 0x0400 + tty->line;
168 filp = file_table + NR_FILE;
169 while (filp-- > file_table) {
170 if (!filp->f_count)
171 continue;
172 if (filp->f_rdev != dev)
173 continue;
174 if (filp->f_op != &tty_fops)
175 continue;
176 filp->f_op = &hung_up_tty_fops;
177 }
178 wake_up_interruptible(&tty->secondary.proc_list);
179 wake_up_interruptible(&tty->read_q.proc_list);
180 wake_up_interruptible(&tty->write_q.proc_list);
181 if (tty->session > 0)
182 kill_sl(tty->session,SIGHUP,1);
183 }
184
185 static inline int hung_up(struct file * filp)
186 {
187 return filp->f_op == &hung_up_tty_fops;
188 }
189
190
191
192
193
194
195
196
197 static struct wait_queue *vt_activate_queue = NULL;
198
199
200
201
202
203 int vt_waitactive(void)
204 {
205 interruptible_sleep_on(&vt_activate_queue);
206 return (current->signal & ~current->blocked) ? -1 : 0;
207 }
208
209 #define vt_wake_waitactive() wake_up(&vt_activate_queue)
210
211 extern int kill_proc(int pid, int sig, int priv);
212
213
214
215
216 void complete_change_console(unsigned int new_console)
217 {
218 unsigned char old_vc_mode;
219
220 if (new_console == fg_console || new_console >= NR_CONSOLES)
221 return;
222
223
224
225
226
227
228 old_vc_mode = vt_cons[fg_console].vc_mode;
229 update_screen(new_console);
230
231
232
233
234
235
236 if (vt_cons[new_console].vt_mode.mode == VT_PROCESS)
237 {
238
239
240
241
242
243 if (kill_proc(vt_cons[new_console].vt_pid,
244 vt_cons[new_console].vt_mode.acqsig,
245 1) != 0)
246 {
247
248
249
250
251
252
253
254
255
256 vt_cons[new_console].vc_mode = KD_TEXT;
257 clr_vc_kbd_flag(kbd_table + new_console, VC_RAW);
258 vt_cons[new_console].vt_mode.mode = VT_AUTO;
259 vt_cons[new_console].vt_mode.waitv = 0;
260 vt_cons[new_console].vt_mode.relsig = 0;
261 vt_cons[new_console].vt_mode.acqsig = 0;
262 vt_cons[new_console].vt_mode.frsig = 0;
263 vt_cons[new_console].vt_pid = -1;
264 vt_cons[new_console].vt_newvt = -1;
265 }
266 }
267
268
269
270
271
272 if (old_vc_mode != vt_cons[new_console].vc_mode)
273 {
274 if (vt_cons[new_console].vc_mode == KD_TEXT)
275 unblank_screen();
276 else
277 {
278 timer_active &= ~(1<<BLANK_TIMER);
279 blank_screen();
280 }
281 }
282
283
284
285
286 vt_wake_waitactive();
287 return;
288 }
289
290
291
292
293 void change_console(unsigned int new_console)
294 {
295 if (new_console == fg_console || new_console >= NR_CONSOLES)
296 return;
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 if (vt_cons[fg_console].vt_mode.mode == VT_PROCESS)
314 {
315
316
317
318
319
320 if (kill_proc(vt_cons[fg_console].vt_pid,
321 vt_cons[fg_console].vt_mode.relsig,
322 1) == 0)
323 {
324
325
326
327
328
329 vt_cons[fg_console].vt_newvt = new_console;
330 return;
331 }
332
333
334
335
336
337
338
339
340
341
342 vt_cons[fg_console].vc_mode = KD_TEXT;
343 clr_vc_kbd_flag(kbd_table + fg_console, VC_RAW);
344 vt_cons[fg_console].vt_mode.mode = VT_AUTO;
345 vt_cons[fg_console].vt_mode.waitv = 0;
346 vt_cons[fg_console].vt_mode.relsig = 0;
347 vt_cons[fg_console].vt_mode.acqsig = 0;
348 vt_cons[fg_console].vt_mode.frsig = 0;
349 vt_cons[fg_console].vt_pid = -1;
350 vt_cons[fg_console].vt_newvt = -1;
351
352
353
354 }
355
356
357
358
359 if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
360 return;
361
362 complete_change_console(new_console);
363 }
364
365 void wait_for_keypress(void)
366 {
367 interruptible_sleep_on(&keypress_wait);
368 }
369
370 void copy_to_cooked(struct tty_struct * tty)
371 {
372 int c;
373
374 if (!tty) {
375 printk("copy_to_cooked: called with NULL tty\n");
376 return;
377 }
378 if (!tty->write) {
379 printk("copy_to_cooked: tty %d has null write routine\n",
380 tty->line);
381 }
382 while (1) {
383
384
385
386
387
388 c = LEFT(&tty->secondary);
389 if (tty->throttle && (c < SQ_THRESHOLD_LW)
390 && !set_bit(TTY_SQ_THROTTLED, &tty->flags))
391 tty->throttle(tty, TTY_THROTTLE_SQ_FULL);
392 if (c == 0)
393 break;
394 c = get_tty_queue(&tty->read_q);
395 if (c < 0)
396 break;
397 if (I_STRP(tty))
398 c &= 0x7f;
399 if (c==13) {
400 if (I_CRNL(tty))
401 c=10;
402 else if (I_NOCR(tty))
403 continue;
404 } else if (c==10 && I_NLCR(tty))
405 c=13;
406 if (I_UCLC(tty))
407 c=tolower(c);
408 if (L_CANON(tty)) {
409 if ((KILL_CHAR(tty) != __DISABLED_CHAR) &&
410 (c==KILL_CHAR(tty))) {
411
412 while(!(EMPTY(&tty->secondary) ||
413 (c=LAST(&tty->secondary))==10 ||
414 ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
415 (c==EOF_CHAR(tty))))) {
416 if (L_ECHO(tty)) {
417 if (c<32) {
418 put_tty_queue(8, &tty->write_q);
419 put_tty_queue(' ', &tty->write_q);
420 put_tty_queue(8,&tty->write_q);
421 }
422 put_tty_queue(8,&tty->write_q);
423 put_tty_queue(' ',&tty->write_q);
424 put_tty_queue(8,&tty->write_q);
425 }
426 DEC(tty->secondary.head);
427 }
428 continue;
429 }
430 if ((ERASE_CHAR(tty) != __DISABLED_CHAR) &&
431 (c==ERASE_CHAR(tty))) {
432 if (EMPTY(&tty->secondary) ||
433 (c=LAST(&tty->secondary))==10 ||
434 ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
435 (c==EOF_CHAR(tty))))
436 continue;
437 if (L_ECHO(tty)) {
438 if (c<32) {
439 put_tty_queue(8,&tty->write_q);
440 put_tty_queue(' ',&tty->write_q);
441 put_tty_queue(8,&tty->write_q);
442 }
443 put_tty_queue(8,&tty->write_q);
444 put_tty_queue(32,&tty->write_q);
445 put_tty_queue(8,&tty->write_q);
446 }
447 DEC(tty->secondary.head);
448 continue;
449 }
450 }
451 if (I_IXON(tty)) {
452 if ((STOP_CHAR(tty) != __DISABLED_CHAR) &&
453 (c==STOP_CHAR(tty))) {
454 tty->status_changed = 1;
455 tty->ctrl_status |= TIOCPKT_STOP;
456 tty->stopped=1;
457 continue;
458 }
459 if (((I_IXANY(tty)) && tty->stopped) ||
460 ((START_CHAR(tty) != __DISABLED_CHAR) &&
461 (c==START_CHAR(tty)))) {
462 tty->status_changed = 1;
463 tty->ctrl_status |= TIOCPKT_START;
464 tty->stopped=0;
465 continue;
466 }
467 }
468 if (L_ISIG(tty)) {
469 if ((INTR_CHAR(tty) != __DISABLED_CHAR) &&
470 (c==INTR_CHAR(tty))) {
471 kill_pg(tty->pgrp, SIGINT, 1);
472 flush_input(tty);
473 continue;
474 }
475 if ((QUIT_CHAR(tty) != __DISABLED_CHAR) &&
476 (c==QUIT_CHAR(tty))) {
477 kill_pg(tty->pgrp, SIGQUIT, 1);
478 flush_input(tty);
479 continue;
480 }
481 if ((SUSPEND_CHAR(tty) != __DISABLED_CHAR) &&
482 (c==SUSPEND_CHAR(tty))) {
483 if (!is_orphaned_pgrp(tty->pgrp))
484 kill_pg(tty->pgrp, SIGTSTP, 1);
485 continue;
486 }
487 }
488 if (c==10 || (EOF_CHAR(tty) != __DISABLED_CHAR &&
489 c==EOF_CHAR(tty)))
490 tty->secondary.data++;
491 if ((c==10) && (L_ECHO(tty) || (L_CANON(tty) && L_ECHONL(tty)))) {
492 put_tty_queue(10,&tty->write_q);
493 put_tty_queue(13,&tty->write_q);
494 } else if (L_ECHO(tty)) {
495 if (c<32 && L_ECHOCTL(tty)) {
496 put_tty_queue('^',&tty->write_q);
497 put_tty_queue(c+64, &tty->write_q);
498 } else
499 put_tty_queue(c, &tty->write_q);
500 }
501 put_tty_queue(c, &tty->secondary);
502 }
503 TTY_WRITE_FLUSH(tty);
504 if (!EMPTY(&tty->secondary))
505 wake_up_interruptible(&tty->secondary.proc_list);
506 if (tty->write_q.proc_list && LEFT(&tty->write_q) > TTY_BUF_SIZE/2)
507 wake_up_interruptible(&tty->write_q.proc_list);
508 if (tty->throttle && (LEFT(&tty->read_q) >= RQ_THRESHOLD_HW)
509 && !clear_bit(TTY_RQ_THROTTLED, &tty->flags))
510 tty->throttle(tty, TTY_THROTTLE_RQ_AVAIL);
511 if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW)
512 && !clear_bit(TTY_SQ_THROTTLED, &tty->flags))
513 tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL);
514 }
515
516 int is_ignored(int sig)
517 {
518 return ((current->blocked & (1<<(sig-1))) ||
519 (current->sigaction[sig-1].sa_handler == SIG_IGN));
520 }
521
522 static int available_canon_input(struct tty_struct *);
523 static void __wait_for_canon_input(struct file * file, struct tty_struct *);
524
525 static void wait_for_canon_input(struct file * file, struct tty_struct * tty)
526 {
527 if (!available_canon_input(tty)) {
528 if (current->signal & ~current->blocked)
529 return;
530 __wait_for_canon_input(file, tty);
531 }
532 }
533
534 static int read_chan(struct tty_struct * tty, struct file * file, char * buf, int nr)
535 {
536 struct wait_queue wait = { current, NULL };
537 int c;
538 char * b=buf;
539 int minimum,time;
540
541 if (L_CANON(tty))
542 minimum = time = current->timeout = 0;
543 else {
544 time = 10L*tty->termios->c_cc[VTIME];
545 minimum = tty->termios->c_cc[VMIN];
546 if (minimum)
547 current->timeout = 0xffffffff;
548 else {
549 if (time)
550 current->timeout = time + jiffies;
551 else
552 current->timeout = 0;
553 time = 0;
554 minimum = 1;
555 }
556 }
557 if (file->f_flags & O_NONBLOCK) {
558 time = current->timeout = 0;
559 if (L_CANON(tty)) {
560 if (!available_canon_input(tty))
561 return -EAGAIN;
562 }
563 } else if (L_CANON(tty)) {
564 wait_for_canon_input(file, tty);
565 if (current->signal & ~current->blocked)
566 return -ERESTARTSYS;
567 }
568 if (minimum>nr)
569 minimum = nr;
570
571
572 if (tty->packet && tty->link && tty->link->status_changed) {
573 put_fs_byte (tty->link->ctrl_status, b);
574 tty->link->status_changed = 0;
575 return 1;
576 }
577
578
579 if (tty->packet) {
580 put_fs_byte (0,b++);
581 nr--;
582
583
584 if (nr == 0)
585 return 1;
586 }
587 add_wait_queue(&tty->secondary.proc_list, &wait);
588 while (nr>0) {
589 TTY_READ_FLUSH(tty);
590 if (tty->link)
591 TTY_WRITE_FLUSH(tty->link);
592 while (nr > 0 && ((c = get_tty_queue(&tty->secondary)) >= 0)) {
593 if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
594 c==EOF_CHAR(tty)) || c==10)
595 tty->secondary.data--;
596 if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
597 c==EOF_CHAR(tty)) && L_CANON(tty))
598 break;
599 put_fs_byte(c,b++);
600 nr--;
601 if (time)
602 current->timeout = time+jiffies;
603 if (c==10 && L_CANON(tty))
604 break;
605 };
606 wake_up_interruptible(&tty->read_q.proc_list);
607
608
609
610
611 if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW)
612 && !clear_bit(TTY_SQ_THROTTLED, &tty->flags))
613 tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL);
614 if (b-buf >= minimum || !current->timeout)
615 break;
616 if (current->signal & ~current->blocked)
617 break;
618 if (tty->link && !tty->link->count)
619 break;
620 TTY_READ_FLUSH(tty);
621 if (tty->link)
622 TTY_WRITE_FLUSH(tty->link);
623 if (!EMPTY(&tty->secondary))
624 continue;
625 if (hung_up(file))
626 break;
627 current->state = TASK_INTERRUPTIBLE;
628 if (EMPTY(&tty->secondary))
629 schedule();
630 current->state = TASK_RUNNING;
631 }
632 remove_wait_queue(&tty->secondary.proc_list, &wait);
633 TTY_READ_FLUSH(tty);
634 if (tty->link && tty->link->write)
635 TTY_WRITE_FLUSH(tty->link);
636 current->timeout = 0;
637
638
639
640 if (tty->packet) {
641 if ((b-buf) > 1)
642 return b-buf;
643 } else {
644 if (b-buf)
645 return b-buf;
646 }
647
648 if (current->signal & ~current->blocked)
649 return -ERESTARTSYS;
650 if (file->f_flags & O_NONBLOCK)
651 return -EAGAIN;
652 return 0;
653 }
654
655 static void __wait_for_canon_input(struct file * file, struct tty_struct * tty)
656 {
657 struct wait_queue wait = { current, NULL };
658
659 add_wait_queue(&tty->secondary.proc_list, &wait);
660 while (1) {
661 current->state = TASK_INTERRUPTIBLE;
662 if (available_canon_input(tty))
663 break;
664 if (current->signal & ~current->blocked)
665 break;
666 if (hung_up(file))
667 break;
668 schedule();
669 }
670 current->state = TASK_RUNNING;
671 remove_wait_queue(&tty->secondary.proc_list, &wait);
672 }
673
674 static int available_canon_input(struct tty_struct * tty)
675 {
676 TTY_READ_FLUSH(tty);
677 if (tty->link)
678 if (tty->link->count)
679 TTY_WRITE_FLUSH(tty->link);
680 else
681 return 1;
682 if (FULL(&tty->read_q))
683 return 1;
684 if (tty->secondary.data)
685 return 1;
686 return 0;
687 }
688
689 static int write_chan(struct tty_struct * tty, struct file * file, char * buf, int nr)
690 {
691 struct wait_queue wait = { current, NULL };
692 char c, *b=buf;
693
694 if (nr < 0)
695 return -EINVAL;
696 if (!nr)
697 return 0;
698 add_wait_queue(&tty->write_q.proc_list, &wait);
699 while (nr>0) {
700 if (current->signal & ~current->blocked)
701 break;
702 if (hung_up(file))
703 break;
704 if (tty->link && !tty->link->count) {
705 send_sig(SIGPIPE,current,0);
706 break;
707 }
708 current->state = TASK_INTERRUPTIBLE;
709 if (FULL(&tty->write_q)) {
710 TTY_WRITE_FLUSH(tty);
711 if (FULL(&tty->write_q))
712 schedule();
713 current->state = TASK_RUNNING;
714 continue;
715 }
716 current->state = TASK_RUNNING;
717 while (nr>0 && !FULL(&tty->write_q)) {
718 c=get_fs_byte(b);
719 if (O_POST(tty)) {
720 if (c=='\r' && O_CRNL(tty))
721 c='\n';
722 else if (c=='\n' && O_NLRET(tty))
723 c='\r';
724 if (c=='\n' && O_NLCR(tty) &&
725 !set_bit(TTY_CR_PENDING,&tty->flags)) {
726 put_tty_queue(13,&tty->write_q);
727 continue;
728 }
729 if (O_LCUC(tty))
730 c=toupper(c);
731 }
732 b++; nr--;
733 clear_bit(TTY_CR_PENDING,&tty->flags);
734 put_tty_queue(c,&tty->write_q);
735 }
736 if (need_resched)
737 schedule();
738 }
739 remove_wait_queue(&tty->write_q.proc_list, &wait);
740 TTY_WRITE_FLUSH(tty);
741 if (b-buf)
742 return b-buf;
743 if (tty->link && !tty->link->count)
744 return -EPIPE;
745 if (current->signal & ~current->blocked)
746 return -ERESTARTSYS;
747 return 0;
748 }
749
750 static int tty_read(struct inode * inode, struct file * file, char * buf, int count)
751 {
752 int i, dev;
753 struct tty_struct * tty;
754
755 dev = file->f_rdev;
756 if (MAJOR(dev) != 4) {
757 printk("tty_read: pseudo-major != 4\n");
758 return -EINVAL;
759 }
760 dev = MINOR(dev);
761 tty = TTY_TABLE(dev);
762 if (!tty || (tty->flags & (1 << TTY_IO_ERROR)))
763 return -EIO;
764 if (MINOR(inode->i_rdev) && (tty->pgrp > 0) &&
765 (current->tty == dev) &&
766 (tty->pgrp != current->pgrp))
767 if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
768 return -EIO;
769 else {
770 (void) kill_pg(current->pgrp, SIGTTIN, 1);
771 return -ERESTARTSYS;
772 }
773 i = read_chan(tty,file,buf,count);
774 if (i > 0)
775 inode->i_atime = CURRENT_TIME;
776 return i;
777 }
778
779 static int tty_write(struct inode * inode, struct file * file, char * buf, int count)
780 {
781 int dev, i, is_console;
782 struct tty_struct * tty;
783
784 dev = file->f_rdev;
785 is_console = (inode->i_rdev == 0x0400);
786 if (MAJOR(dev) != 4) {
787 printk("tty_write: pseudo-major != 4\n");
788 return -EINVAL;
789 }
790 dev = MINOR(dev);
791 if (is_console && redirect)
792 tty = redirect;
793 else
794 tty = TTY_TABLE(dev);
795 if (!tty || !tty->write || (tty->flags & (1 << TTY_IO_ERROR)))
796 return -EIO;
797 if (!is_console && L_TOSTOP(tty) && (tty->pgrp > 0) &&
798 (current->tty == dev) && (tty->pgrp != current->pgrp)) {
799 if (is_orphaned_pgrp(current->pgrp))
800 return -EIO;
801 if (!is_ignored(SIGTTOU)) {
802 (void) kill_pg(current->pgrp, SIGTTOU, 1);
803 return -ERESTARTSYS;
804 }
805 }
806 i = write_chan(tty,file,buf,count);
807 if (i > 0)
808 inode->i_mtime = CURRENT_TIME;
809 return i;
810 }
811
812
813
814
815
816
817 static int init_dev(int dev)
818 {
819 struct tty_struct *tty, *o_tty;
820 struct termios *tp, *o_tp;
821 int retval;
822 int o_dev;
823
824 o_dev = PTY_OTHER(dev);
825 tty = o_tty = NULL;
826 tp = o_tp = NULL;
827 repeat:
828 retval = -EAGAIN;
829 if (IS_A_PTY_MASTER(dev) && tty_table[dev] && tty_table[dev]->count)
830 goto end_init;
831 retval = -ENOMEM;
832 if (!tty_table[dev] && !tty) {
833 tty = (struct tty_struct *) get_free_page(GFP_KERNEL);
834 if (!tty)
835 goto end_init;
836 initialize_tty_struct(dev, tty);
837 goto repeat;
838 }
839 if (!tty_termios[dev] && !tp) {
840 tp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL);
841 if (!tp)
842 goto end_init;
843 initialize_termios(dev, tp);
844 goto repeat;
845 }
846 if (IS_A_PTY(dev)) {
847 if (!tty_table[o_dev] && !o_tty) {
848 o_tty = (struct tty_struct *) get_free_page(GFP_KERNEL);
849 if (!o_tty)
850 goto end_init;
851 initialize_tty_struct(o_dev, o_tty);
852 goto repeat;
853 }
854 if (!tty_termios[o_dev] && !o_tp) {
855 o_tp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL);
856 if (!o_tp)
857 goto end_init;
858 initialize_termios(o_dev, o_tp);
859 goto repeat;
860 }
861 }
862
863 if (!tty_termios[dev]) {
864 tty_termios[dev] = tp;
865 tp = NULL;
866 }
867 if (!tty_table[dev]) {
868 tty->termios = tty_termios[dev];
869 tty_table[dev] = tty;
870 tty = NULL;
871 }
872 if (IS_A_PTY(dev)) {
873 if (!tty_termios[o_dev]) {
874 tty_termios[o_dev] = o_tp;
875 o_tp = NULL;
876 }
877 if (!tty_table[o_dev]) {
878 o_tty->termios = tty_termios[o_dev];
879 tty_table[o_dev] = o_tty;
880 o_tty = NULL;
881 }
882 tty_table[dev]->link = tty_table[o_dev];
883 tty_table[o_dev]->link = tty_table[dev];
884 }
885 tty_table[dev]->count++;
886 if (IS_A_PTY_MASTER(dev))
887 tty_table[o_dev]->count++;
888 retval = 0;
889 end_init:
890 if (tty)
891 free_page((unsigned long) tty);
892 if (o_tty)
893 free_page((unsigned long) tty);
894 if (tp)
895 kfree_s(tp, sizeof(struct termios));
896 if (o_tp)
897 kfree_s(o_tp, sizeof(struct termios));
898 return retval;
899 }
900
901
902
903
904
905
906 static void release_dev(int dev, struct file * filp)
907 {
908 struct tty_struct *tty, *o_tty;
909 struct termios *tp, *o_tp;
910
911 tty = tty_table[dev];
912 tp = tty_termios[dev];
913 o_tty = NULL;
914 o_tp = NULL;
915 if (!tty) {
916 printk("release_dev: tty_table[%d] was NULL\n", dev);
917 return;
918 }
919 if (!tp) {
920 printk("release_dev: tty_termios[%d] was NULL\n", dev);
921 return;
922 }
923 if (IS_A_PTY(dev)) {
924 o_tty = tty_table[PTY_OTHER(dev)];
925 o_tp = tty_termios[PTY_OTHER(dev)];
926 if (!o_tty) {
927 printk("release_dev: pty pair(%d) was NULL\n", dev);
928 return;
929 }
930 if (!o_tp) {
931 printk("release_dev: pty pair(%d) termios was NULL\n", dev);
932 return;
933 }
934 if (tty->link != o_tty || o_tty->link != tty) {
935 printk("release_dev: bad pty pointers\n");
936 return;
937 }
938 }
939 if (tty->count < 2 && tty->close)
940 tty->close(tty, filp);
941 if (IS_A_PTY_MASTER(dev)) {
942 if (--tty->link->count < 0) {
943 printk("release_dev: bad tty slave count (dev = %d): %d\n",
944 dev, tty->count);
945 tty->link->count = 0;
946 }
947 }
948 if (--tty->count < 0) {
949 printk("release_dev: bad tty_table[%d]->count: %d\n",
950 dev, tty->count);
951 tty->count = 0;
952 }
953 if (tty->count)
954 return;
955 if (o_tty) {
956 if (o_tty->count)
957 return;
958 else {
959 tty_table[PTY_OTHER(dev)] = NULL;
960 tty_termios[PTY_OTHER(dev)] = NULL;
961 }
962 }
963 tty_table[dev] = NULL;
964 if (IS_A_PTY(dev)) {
965 tty_termios[dev] = NULL;
966 kfree_s(tp, sizeof(struct termios));
967 }
968 free_page((unsigned long) tty);
969 if (o_tty)
970 free_page((unsigned long) o_tty);
971 if (o_tp)
972 kfree_s(o_tp, sizeof(struct termios));
973 }
974
975
976
977
978
979
980
981
982
983
984
985
986 static int tty_open(struct inode * inode, struct file * filp)
987 {
988 struct tty_struct *tty;
989 int dev, retval;
990
991 dev = inode->i_rdev;
992 if (MAJOR(dev) == 5)
993 dev = current->tty;
994 else
995 dev = MINOR(dev);
996 if (dev < 0)
997 return -ENXIO;
998 if (!dev)
999 dev = fg_console + 1;
1000 filp->f_rdev = 0x0400 | dev;
1001 retval = init_dev(dev);
1002 if (retval)
1003 return retval;
1004 tty = tty_table[dev];
1005
1006 tty->status_changed = 0;
1007 tty->ctrl_status = 0;
1008 tty->packet = 0;
1009
1010 if (tty->open) {
1011 retval = tty->open(tty, filp);
1012 } else {
1013 retval = -ENODEV;
1014 }
1015 if (retval) {
1016 release_dev(dev, filp);
1017 return retval;
1018 }
1019 if (!(filp->f_flags & O_NOCTTY) &&
1020 current->leader &&
1021 current->tty<0 &&
1022 tty->session==0) {
1023 current->tty = dev;
1024 tty->session = current->session;
1025 tty->pgrp = current->pgrp;
1026 }
1027 return 0;
1028 }
1029
1030
1031
1032
1033
1034
1035 static void tty_release(struct inode * inode, struct file * filp)
1036 {
1037 int dev;
1038
1039 dev = filp->f_rdev;
1040 if (MAJOR(dev) != 4) {
1041 printk("tty_release: tty pseudo-major != 4\n");
1042 return;
1043 }
1044 dev = MINOR(filp->f_rdev);
1045 if (!dev) {
1046 printk("tty_release: bad f_rdev\n");
1047 return;
1048 }
1049 release_dev(dev, filp);
1050 }
1051
1052 static int tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
1053 {
1054 int dev;
1055 struct tty_struct * tty;
1056
1057 dev = filp->f_rdev;
1058 if (MAJOR(dev) != 4) {
1059 printk("tty_select: tty pseudo-major != 4\n");
1060 return 0;
1061 }
1062 dev = MINOR(filp->f_rdev);
1063 tty = TTY_TABLE(dev);
1064 if (!tty) {
1065 printk("tty_select: tty struct for dev %d was NULL\n", dev);
1066 return 0;
1067 }
1068 switch (sel_type) {
1069 case SEL_IN:
1070 if (L_CANON(tty)) {
1071 if (available_canon_input(tty))
1072 return 1;
1073 } else if (!EMPTY(&tty->secondary))
1074 return 1;
1075 if (tty->link && !tty->link->count)
1076 return 1;
1077
1078
1079 if (tty->packet && tty->link &&
1080 tty->link->status_changed)
1081 return 1;
1082
1083 select_wait(&tty->secondary.proc_list, wait);
1084 return 0;
1085 case SEL_OUT:
1086 if (!FULL(&tty->write_q))
1087 return 1;
1088 select_wait(&tty->write_q.proc_list, wait);
1089 return 0;
1090 case SEL_EX:
1091 if (tty->link && !tty->link->count)
1092 return 1;
1093 return 0;
1094 }
1095 return 0;
1096 }
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110 void do_SAK( struct tty_struct *tty)
1111 {
1112 struct task_struct **p;
1113 int line = tty->line;
1114 int session = tty->session;
1115 int i;
1116 struct file *filp;
1117
1118 flush_input(tty);
1119 flush_output(tty);
1120 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
1121 if (!(*p))
1122 continue;
1123 if (((*p)->tty == line) ||
1124 ((session > 0) && ((*p)->session == session)))
1125 send_sig(SIGKILL, *p, 1);
1126 else {
1127 for (i=0; i < NR_FILE; i++) {
1128 filp = (*p)->filp[i];
1129 if (filp && (filp->f_op == &tty_fops) &&
1130 (MINOR(filp->f_rdev) == line)) {
1131 send_sig(SIGKILL, *p, 1);
1132 break;
1133 }
1134 }
1135 }
1136 }
1137 }
1138
1139
1140
1141
1142
1143 static void initialize_tty_struct(int line, struct tty_struct *tty)
1144 {
1145 memset(tty, 0, sizeof(struct tty_struct));
1146 tty->line = line;
1147 tty->pgrp = -1;
1148 tty->winsize.ws_row = 24;
1149 tty->winsize.ws_col = 80;
1150 if (IS_A_CONSOLE(line)) {
1151 tty->open = con_open;
1152 tty->winsize.ws_row = video_num_lines;
1153 tty->winsize.ws_col = video_num_columns;
1154 } else if IS_A_SERIAL(line) {
1155 tty->open = rs_open;
1156 } else if IS_A_PTY(line) {
1157 tty->open = pty_open;
1158 }
1159 }
1160
1161 static void initialize_termios(int line, struct termios * tp)
1162 {
1163 memset(tp, 0, sizeof(struct termios));
1164 memcpy(tp->c_cc, INIT_C_CC, NCCS);
1165 if (IS_A_CONSOLE(line)) {
1166 tp->c_iflag = ICRNL | IXON;
1167 tp->c_oflag = OPOST | ONLCR;
1168 tp->c_cflag = B38400 | CS8 | CREAD;
1169 tp->c_lflag = ISIG | ICANON | ECHO |
1170 ECHOCTL | ECHOKE;
1171 } else if (IS_A_SERIAL(line)) {
1172 tp->c_cflag = B2400 | CS8 | CREAD | HUPCL;
1173 } else if (IS_A_PTY_MASTER(line)) {
1174 tp->c_cflag = B9600 | CS8 | CREAD;
1175 } else if (IS_A_PTY_SLAVE(line)) {
1176 tp->c_iflag = ICRNL | IXON;
1177 tp->c_oflag = OPOST | ONLCR;
1178 tp->c_cflag = B38400 | CS8 | CREAD;
1179 tp->c_lflag = ISIG | ICANON | ECHO |
1180 ECHOCTL | ECHOKE;
1181 }
1182 }
1183
1184 long tty_init(long kmem_start)
1185 {
1186 int i;
1187
1188 chrdev_fops[4] = &tty_fops;
1189 chrdev_fops[5] = &tty_fops;
1190 for (i=0 ; i<256 ; i++) {
1191 tty_table[i] = 0;
1192 tty_termios[i] = 0;
1193 }
1194 kmem_start = kbd_init(kmem_start);
1195 kmem_start = con_init(kmem_start);
1196 kmem_start = rs_init(kmem_start);
1197 printk("%d virtual consoles\n\r",NR_CONSOLES);
1198 return kmem_start;
1199 }