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