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