root/kernel/chr_drv/tty_io.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. put_tty_queue
  2. get_tty_queue
  3. tty_write_flush
  4. tty_read_flush
  5. hung_up_tty_read
  6. hung_up_tty_write
  7. hung_up_tty_select
  8. tty_lseek
  9. tty_hangup
  10. hung_up
  11. complete_change_console
  12. change_console
  13. wait_for_keypress
  14. copy_to_cooked
  15. is_ignored
  16. wait_for_canon_input
  17. read_chan
  18. __wait_for_canon_input
  19. available_canon_input
  20. write_chan
  21. tty_read
  22. tty_write
  23. tty_open
  24. tty_release
  25. tty_select
  26. do_SAK
  27. initialize_tty_struct
  28. tty_init

   1 /*
   2  *  linux/kernel/tty_io.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
   9  * or rs-channels. It also implements echoing, cooked mode etc.
  10  *
  11  * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
  12  *
  13  * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
  14  * tty_struct and tty_queue structures.  Previously there was a array
  15  * of 256 tty_struct's which was statically allocated, and the
  16  * tty_queue structures were allocated at boot time.  Both are now
  17  * dynamically allocated only when the tty is open.
  18  *
  19  * Also restructured routines so that there is more of a separation
  20  * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
  21  * the low-level tty routines (serial.c, pty.c, console.c).  This
  22  * makes for cleaner and more compact code.  -TYT, 9/17/92 
  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]; /* We need to keep the termios state */
  46                                   /* around, even when a tty is closed */
  47 
  48 /*
  49  * fg_console is the current virtual console,
  50  * redirect is the pseudo-tty that console output
  51  * is redirected to if asked by TIOCCONS.
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         return 0;
 117 }
 118 
 119 static int hung_up_tty_write(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         return 1;
 127 }
 128 
 129 static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         return -EBADF;
 132 }
 133 
 134 static struct file_operations tty_fops = {
 135         tty_lseek,
 136         tty_read,
 137         tty_write,
 138         NULL,           /* tty_readdir */
 139         tty_select,
 140         tty_ioctl,
 141         NULL,           /* tty_mmap */
 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,           /* hung_up_tty_readdir */
 151         hung_up_tty_select,
 152         tty_ioctl,
 153         NULL,           /* hung_up_tty_mmap */
 154         tty_open,
 155         tty_release
 156 };
 157 
 158 void tty_hangup(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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  * Performs the back end of a vt switch
 192  */
 193 void complete_change_console(unsigned int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
 194 {
 195         unsigned char old_vc_mode;
 196 
 197         if (new_console == fg_console || new_console >= NR_CONSOLES)
 198                 return;
 199 
 200         /*
 201          * If we're switching, we could be going from KD_GRAPHICS to
 202          * KD_TEXT mode or vice versa, which means we need to blank or
 203          * unblank the screen later.
 204          */
 205         old_vc_mode = vt_cons[fg_console].vc_mode;
 206         update_screen(new_console);
 207 
 208         /*
 209          * If this new console is under process control, send it a signal
 210          * telling it that it has acquired. Also check if it has died and
 211          * clean up (similar to logic employed in change_console())
 212          */
 213         if (vt_cons[new_console].vt_mode.mode == VT_PROCESS)
 214         {
 215                 /*
 216                  * Send the signal as privileged - kill_proc() will
 217                  * tell us if the process has gone or something else
 218                  * is awry
 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                  * The controlling process has died, so we revert back to
 226                  * normal operation. In this case, we'll also change back
 227                  * to KD_TEXT mode. I'm not sure if this is strictly correct
 228                  * but it saves the agony when the X server dies and the screen
 229                  * remains blanked due to KD_GRAPHICS! It would be nice to do
 230                  * this outside of VT_PROCESS but there is no single process
 231                  * to account for and tracking tty count may be undesirable.
 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          * We do this here because the controlling process above may have
 247          * gone, and so there is now a new vc_mode
 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  * Performs the front-end of a vt switch
 265  */
 266 void change_console(unsigned int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
 267 {
 268         if (new_console == fg_console || new_console >= NR_CONSOLES)
 269                 return;
 270 
 271         /*
 272          * If this vt is in process mode, then we need to handshake with
 273          * that process before switching. Essentially, we store where that
 274          * vt wants to switch to and wait for it to tell us when it's done
 275          * (via VT_RELDISP ioctl).
 276          *
 277          * We also check to see if the controlling process still exists.
 278          * If it doesn't, we reset this vt to auto mode and continue.
 279          * This is a cheap way to track process control. The worst thing
 280          * that can happen is: we send a signal to a process, it dies, and
 281          * the switch gets "lost" waiting for a response; hopefully, the
 282          * user will try again, we'll detect the process is gone (unless
 283          * the user waits just the right amount of time :-) and revert the
 284          * vt to auto control.
 285          */
 286         if (vt_cons[fg_console].vt_mode.mode == VT_PROCESS)
 287         {
 288                 /*
 289                  * Send the signal as privileged - kill_proc() will
 290                  * tell us if the process has gone or something else
 291                  * is awry
 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                          * It worked. Mark the vt to switch to and
 299                          * return. The process needs to send us a
 300                          * VT_RELDISP ioctl to complete the switch.
 301                          */
 302                         vt_cons[fg_console].vt_newvt = new_console;
 303                         return;
 304                 }
 305 
 306                 /*
 307                  * The controlling process has died, so we revert back to
 308                  * normal operation. In this case, we'll also change back
 309                  * to KD_TEXT mode. I'm not sure if this is strictly correct
 310                  * but it saves the agony when the X server dies and the screen
 311                  * remains blanked due to KD_GRAPHICS! It would be nice to do
 312                  * this outside of VT_PROCESS but there is no single process
 313                  * to account for and tracking tty count may be undesirable.
 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                  * Fall through to normal (VT_AUTO) handling of the switch...
 326                  */
 327         }
 328 
 329         /*
 330          * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 339 {
 340         interruptible_sleep_on(&keypress_wait);
 341 }
 342 
 343 void copy_to_cooked(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                  * Check to see how much room we have left in the
 358                  * secondary queue.  Send a throttle command or abort
 359                  * if necessary.
 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                                 /* deal with killing the input line */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /* deal with packet mode:  First test for status change */
 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         /* now bump the buffer up one. */
 552         if (tty->packet) {
 553                 put_fs_byte (0,b++);
 554                 nr--;
 555                 /* this really shouldn't happen, but we need to 
 556                 put it here. */
 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                  * If there is enough space in the secondary queue
 582                  * now, let the low-level driver know.
 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         /* packet mode sticks in an extra 0.  If that's all we've got,
 612            we should count it a zero bytes. */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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  * tty_open and tty_release keep up the tty count that contains the
 787  * number of opens done on a tty. We cannot use the inode-count, as
 788  * different inodes might point to the same tty.
 789  *
 790  * Open-counting is needed for pty masters, as well as for keeping
 791  * track of serial lines: DTR is dropped when the last close happens.
 792  *
 793  * The termios state of a pty is reset on first open so that
 794  * settings don't persist across reuse.
 795  */
 796 static int tty_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 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  * There be race-conditions here... Lots of them. Careful now.
 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                          * Stop our allocation of tty if race
 821                          * condition detected.
 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++;                   /* bump count to preserve tty */
 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                                  * Stop our allocation of o_tty if race
 845                                  * condition detected.
 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         /* clean up the packet stuff. */
 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  * Note that releasing a pty master also releases the child, so
 903  * we have to make the redirection checks after that and on both
 904  * sides of a pty.
 905  */
 906 static void tty_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                  * Free the tty structure, being careful to avoid race conditions
 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                  * If this is a PTY, free the termios structure, being
 957                  * careful to avoid race conditions
 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          * Free the tty structure, being careful to avoid race conditions
 967          */
 968         free_tty_struct = (unsigned long) tty_table[dev];
 969         tty_table[dev] = 0;     
 970         free_page(free_tty_struct);
 971         /*
 972          * If this is a PTY, free the termios structure, being careful
 973          * to avoid race conditions
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                         /* see if the status byte can be read. */
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  * This implements the "Secure Attention Key" ---  the idea is to
1030  * prevent trojan horses by killing all processes associated with this
1031  * tty when the user hits the "Secure Attention Key".  Required for
1032  * super-paranoid applications --- see the Orange Book for more details.
1033  * 
1034  * This code could be nicer; ideally it should send a HUP, wait a few
1035  * seconds, then send a INT, and then a KILL signal.  But you then
1036  * have to coordinate with the init process, since all processes associated
1037  * with the current tty must be dead before the new getty is allowed
1038  * to spawn.
1039  */
1040 void do_SAK( struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
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  * This subroutine initializes a tty structure.  We have to set up
1071  * things correctly for each different type of tty.
1072  */
1073 static int initialize_tty_struct(struct tty_struct *tty, int line)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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 }

/* [previous][next][first][last][top][bottom][index][help] */