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