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