root/drivers/char/tty_ioctl.c

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

DEFINITIONS

This source file includes following definitions.
  1. flush
  2. flush_input
  3. flush_output
  4. wait_until_sent
  5. do_get_ps_info
  6. unset_locked_termios
  7. get_termios
  8. check_change
  9. set_termios
  10. get_termio
  11. set_termio
  12. get_lcktrmios
  13. set_lcktrmios
  14. set_window_size
  15. get_window_size
  16. tty_set_ldisc
  17. tty_ioctl

   1 /*
   2  *  linux/kernel/chr_drv/tty_ioctl.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  *
   6  * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
   7  * which can be dynamically activated and de-activated by the line
   8  * discipline handling modules (like SLIP).
   9  */
  10 
  11 #include <linux/types.h>
  12 #include <linux/termios.h>
  13 #include <linux/errno.h>
  14 #include <linux/sched.h>
  15 #include <linux/config.h>
  16 #include <linux/kernel.h>
  17 #include <linux/major.h>
  18 #include <linux/tty.h>
  19 #include <linux/fcntl.h>
  20 
  21 #include <asm/io.h>
  22 #include <asm/segment.h>
  23 #include <asm/system.h>
  24 
  25 #undef  DEBUG
  26 #ifdef DEBUG
  27 # define        PRINTK(x)       printk (x)
  28 #else
  29 # define        PRINTK(x)       /**/
  30 #endif
  31 
  32 extern int session_of_pgrp(int pgrp);
  33 extern int do_screendump(int arg);
  34 extern int kill_pg(int pgrp, int sig, int priv);
  35 
  36 #ifdef CONFIG_SELECTION
  37 extern int set_selection(const int arg);
  38 extern int paste_selection(struct tty_struct *tty);
  39 #endif /* CONFIG_SELECTION */
  40 
  41 static int tty_set_ldisc(struct tty_struct *tty, int ldisc);
  42 
  43 static void flush(struct tty_queue * queue)
     /* [previous][next][first][last][top][bottom][index][help] */
  44 {
  45         if (queue) {
  46                 cli();
  47                 queue->head = queue->tail;
  48                 sti();
  49                 wake_up_interruptible(&queue->proc_list);
  50         }
  51 }
  52 
  53 void flush_input(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55         tty->ctrl_status |= TIOCPKT_FLUSHREAD;
  56         if (tty->link)
  57                 wake_up_interruptible(&tty->link->except_q);
  58         flush(&tty->read_q);
  59         wake_up_interruptible(&tty->read_q.proc_list);
  60         flush(&tty->secondary);
  61         tty->secondary.data = 0;
  62 
  63         if ((tty = tty->link) != NULL) {
  64                 flush(&tty->write_q);
  65                 wake_up_interruptible(&tty->write_q.proc_list);
  66         }
  67 }
  68 
  69 void flush_output(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71         tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
  72         if (tty->link)
  73                 wake_up_interruptible(&tty->link->except_q);
  74         flush(&tty->write_q);
  75         wake_up_interruptible(&tty->write_q.proc_list);
  76         if ((tty = tty->link) != NULL) {
  77                 flush(&tty->read_q);
  78                 wake_up_interruptible(&tty->read_q.proc_list);
  79                 flush(&tty->secondary);
  80                 tty->secondary.data = 0;
  81         }
  82 }
  83 
  84 void wait_until_sent(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         struct wait_queue wait = { current, NULL };
  87 
  88         TTY_WRITE_FLUSH(tty);
  89         if (EMPTY(&tty->write_q))
  90                 return;
  91         add_wait_queue(&tty->write_q.proc_list, &wait);
  92         current->counter = 0;   /* make us low-priority */
  93         while (1) {
  94                 current->state = TASK_INTERRUPTIBLE;
  95                 if (current->signal & ~current->blocked)
  96                         break;
  97                 TTY_WRITE_FLUSH(tty);
  98                 if (EMPTY(&tty->write_q))
  99                         break;
 100                 schedule();
 101         }
 102         current->state = TASK_RUNNING;
 103         remove_wait_queue(&tty->write_q.proc_list, &wait);
 104 }
 105 
 106 static int do_get_ps_info(int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108         struct tstruct {
 109                 int flag;
 110                 int present[NR_TASKS];
 111                 struct task_struct tasks[NR_TASKS];
 112         };
 113         struct tstruct *ts = (struct tstruct *)arg;
 114         struct task_struct **p;
 115         char *c, *d;
 116         int i, n = 0;
 117         
 118         i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct tstruct));
 119         if (i)
 120                 return i;
 121         for (p = &FIRST_TASK ; p <= &LAST_TASK ; p++, n++)
 122                 if (*p)
 123                 {
 124                         c = (char *)(*p);
 125                         d = (char *)(ts->tasks+n);
 126                         for (i=0 ; i<sizeof(struct task_struct) ; i++)
 127                                 put_fs_byte(*c++, d++);
 128                         put_fs_long(1, (unsigned long *)(ts->present+n));
 129                 }
 130                 else    
 131                         put_fs_long(0, (unsigned long *)(ts->present+n));
 132         return(0);                      
 133 }
 134 
 135 static void unset_locked_termios(struct termios *termios,
     /* [previous][next][first][last][top][bottom][index][help] */
 136                                  struct termios *old,
 137                                  struct termios *locked)
 138 {
 139         int     i;
 140         
 141 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
 142 
 143         if (!locked) {
 144                 printk("Warning?!? termios_locked is NULL.\n");
 145                 return;
 146         }
 147 
 148         NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
 149         NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
 150         NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
 151         NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
 152         termios->c_line = locked->c_line ? old->c_line : termios->c_line;
 153         for (i=0; i < NCCS; i++)
 154                 termios->c_cc[i] = locked->c_cc[i] ?
 155                         old->c_cc[i] : termios->c_cc[i];
 156 }
 157 
 158 static int get_termios(struct tty_struct * tty, struct termios * termios)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160         int i;
 161 
 162         i = verify_area(VERIFY_WRITE, termios, sizeof (*termios));
 163         if (i)
 164                 return i;
 165         for (i=0 ; i< (sizeof (*termios)) ; i++)
 166                 put_fs_byte( ((char *)tty->termios)[i] , i+(char *)termios );
 167         return 0;
 168 }
 169 
 170 static int check_change(struct tty_struct * tty, int channel)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172         /* If we try to set the state of terminal and we're not in the
 173            foreground, send a SIGTTOU.  If the signal is blocked or
 174            ignored, go ahead and perform the operation.  POSIX 7.2) */
 175         if (current->tty != channel)
 176                 return 0;
 177         if (tty->pgrp <= 0 || tty->pgrp == current->pgrp)
 178                 return 0;
 179         if (is_orphaned_pgrp(current->pgrp))
 180                 return -EIO;
 181         if (is_ignored(SIGTTOU))
 182                 return 0;
 183         (void) kill_pg(current->pgrp,SIGTTOU,1);
 184         return -ERESTARTSYS;
 185 }
 186 
 187 static int set_termios(struct tty_struct * tty, struct termios * termios,
     /* [previous][next][first][last][top][bottom][index][help] */
 188                         int channel)
 189 {
 190         int i, old_flow, new_flow;
 191         struct termios old_termios = *tty->termios;
 192 
 193         i = check_change(tty, channel);
 194         if (i)
 195                 return i;
 196         for (i=0 ; i< (sizeof (*termios)) ; i++)
 197                 ((char *)tty->termios)[i]=get_fs_byte(i+(char *)termios);
 198 
 199         /* see if packet mode change of state */
 200 
 201         old_flow = (old_termios.c_iflag & IXON) &&
 202               (old_termios.c_cc[VSTOP] == '\023') &&
 203               (old_termios.c_cc[VSTART] == '\021');
 204 
 205         new_flow = (tty->termios->c_iflag & IXON) &&
 206               (tty->termios->c_cc[VSTOP] == '\023') &&
 207               (tty->termios->c_cc[VSTART] == '\021');
 208 
 209         if (old_flow != new_flow) {
 210                 tty->ctrl_status &= ~(TIOCPKT_DOSTOP|TIOCPKT_NOSTOP);
 211                 if (new_flow)
 212                         tty->ctrl_status |= TIOCPKT_DOSTOP;
 213                 else
 214                         tty->ctrl_status |= TIOCPKT_NOSTOP;             
 215                 if (tty->link)
 216                         wake_up_interruptible(&tty->link->except_q);
 217         }
 218 
 219 #if 0
 220         /* puting mpty's into echo mode is very bad, and I think under
 221            some situations can cause the kernel to do nothing but
 222            copy characters back and forth. -RAB */
 223         /* This can no longer happen because a set_termios is redirected
 224            to the pty slave.  -- jrs */
 225         if (IS_A_PTY_MASTER(channel)) tty->termios->c_lflag &= ~ECHO;
 226 #endif
 227 
 228         unset_locked_termios(tty->termios, &old_termios,
 229                              termios_locked[tty->line]);
 230 
 231 #if 0
 232         retval = tty_set_ldisc(tty, tty->termios->c_line);
 233         if (retval)
 234                 return retval;
 235 #endif
 236 
 237         if (tty->set_termios)
 238                 (*tty->set_termios)(tty, &old_termios);
 239 
 240         return 0;
 241 }
 242 
 243 static int get_termio(struct tty_struct * tty, struct termio * termio)
     /* [previous][next][first][last][top][bottom][index][help] */
 244 {
 245         int i;
 246         struct termio tmp_termio;
 247 
 248         i = verify_area(VERIFY_WRITE, termio, sizeof (*termio));
 249         if (i)
 250                 return i;
 251         tmp_termio.c_iflag = tty->termios->c_iflag;
 252         tmp_termio.c_oflag = tty->termios->c_oflag;
 253         tmp_termio.c_cflag = tty->termios->c_cflag;
 254         tmp_termio.c_lflag = tty->termios->c_lflag;
 255         tmp_termio.c_line = tty->termios->c_line;
 256         for(i=0 ; i < NCC ; i++)
 257                 tmp_termio.c_cc[i] = tty->termios->c_cc[i];
 258         for (i=0 ; i< (sizeof (*termio)) ; i++)
 259                 put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
 260         return 0;
 261 }
 262 
 263 /*
 264  * This only works as the 386 is low-byte-first
 265  */
 266 static int set_termio(struct tty_struct * tty, struct termio * termio,
     /* [previous][next][first][last][top][bottom][index][help] */
 267                         int channel)
 268 {
 269         int i, old_flow, new_flow;
 270         struct termio tmp_termio;
 271         struct termios old_termios = *tty->termios;
 272 
 273         i = check_change(tty, channel);
 274         if (i)
 275                 return i;
 276         for (i=0 ; i< (sizeof (*termio)) ; i++)
 277                 ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
 278 
 279         *(unsigned short *)&tty->termios->c_iflag = tmp_termio.c_iflag;
 280         *(unsigned short *)&tty->termios->c_oflag = tmp_termio.c_oflag;
 281         *(unsigned short *)&tty->termios->c_cflag = tmp_termio.c_cflag;
 282         *(unsigned short *)&tty->termios->c_lflag = tmp_termio.c_lflag;
 283         for(i=0 ; i < NCC ; i++)
 284                 tty->termios->c_cc[i] = tmp_termio.c_cc[i];
 285 
 286         /* see if packet mode change of state */
 287 
 288         old_flow = (old_termios.c_iflag & IXON) &&
 289               (old_termios.c_cc[VSTOP] == '\023') &&
 290               (old_termios.c_cc[VSTART] == '\021');
 291 
 292         new_flow = (tty->termios->c_iflag & IXON) &&
 293               (tty->termios->c_cc[VSTOP] == '\023') &&
 294               (tty->termios->c_cc[VSTART] == '\021');
 295 
 296         if (old_flow != new_flow) {
 297                 tty->ctrl_status &= ~(TIOCPKT_DOSTOP|TIOCPKT_NOSTOP);
 298                 if (new_flow)
 299                         tty->ctrl_status |= TIOCPKT_DOSTOP;
 300                 else
 301                         tty->ctrl_status |= TIOCPKT_NOSTOP;             
 302                 if (tty->link)
 303                         wake_up_interruptible(&tty->link->except_q);
 304         }
 305 
 306         unset_locked_termios(tty->termios, &old_termios,
 307                              termios_locked[tty->line]);
 308 
 309 #if 0
 310         retval = tty_set_ldisc(tty, tmp_termio.c_line);
 311         if (retval)
 312                 return retval;
 313 #endif
 314 
 315         if (tty->set_termios)
 316                 (*tty->set_termios)(tty, &old_termios);
 317 
 318         return 0;
 319 }
 320 
 321 static int get_lcktrmios(struct tty_struct * tty, struct termios * termios,
     /* [previous][next][first][last][top][bottom][index][help] */
 322                          int channel)
 323 {
 324         int i;
 325 
 326         i = verify_area(VERIFY_WRITE, termios, sizeof (*termios));
 327         if (i)
 328                 return i;
 329         for (i=0 ; i< (sizeof (*termios)) ; i++)
 330                 put_fs_byte( ((char *)termios_locked[channel])[i],
 331                             i+(char *)termios);
 332         return 0;
 333 }
 334 
 335 static int set_lcktrmios(struct tty_struct * tty, struct termios * termios,
     /* [previous][next][first][last][top][bottom][index][help] */
 336                          int channel)
 337 {
 338         int i;
 339 
 340         if (!suser())
 341                 return -EPERM;
 342         for (i=0 ; i< (sizeof (*termios)) ; i++)
 343                 ((char *)termios_locked[channel])[i] =
 344                         get_fs_byte(i+(char *)termios);
 345 
 346         return 0;
 347 }
 348 
 349 static int set_window_size(struct tty_struct * tty, struct winsize * ws)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351         int i,changed;
 352         char c, * tmp;
 353 
 354         if (!ws)
 355                 return -EINVAL;
 356         tmp = (char *) &tty->winsize;
 357         changed = 0;
 358         for (i = 0; i < sizeof (*ws) ; i++,tmp++) {
 359                 c = get_fs_byte(i + (char *) ws);
 360                 if (c == *tmp)
 361                         continue;
 362                 changed = 1;
 363                 *tmp = c;
 364         }
 365         if (changed)
 366                 kill_pg(tty->pgrp, SIGWINCH, 1);
 367         return 0;
 368 }
 369 
 370 static int get_window_size(struct tty_struct * tty, struct winsize * ws)
     /* [previous][next][first][last][top][bottom][index][help] */
 371 {
 372         int i;
 373         char * tmp;
 374 
 375         if (!ws)
 376                 return -EINVAL;
 377         i = verify_area(VERIFY_WRITE, ws, sizeof (*ws));
 378         if (i)
 379                 return i;
 380         tmp = (char *) ws;
 381         for (i = 0; i < sizeof (struct winsize) ; i++,tmp++)
 382                 put_fs_byte(((char *) &tty->winsize)[i], tmp);
 383         return 0;
 384 }
 385 
 386 /* Set the discipline of a tty line. */
 387 static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
     /* [previous][next][first][last][top][bottom][index][help] */
 388 {
 389         if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS) ||
 390             !(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
 391                 return -EINVAL;
 392 
 393         if (tty->disc == ldisc)
 394                 return 0;       /* We are already in the desired discipline */
 395 
 396         /* Shutdown the current discipline. */
 397         wait_until_sent(tty);
 398         flush_input(tty);
 399         if (ldiscs[tty->disc].close)
 400                 ldiscs[tty->disc].close(tty);
 401 
 402         /* Now set up the new line discipline. */
 403         tty->disc = ldisc;
 404         tty->termios->c_line = ldisc;
 405         if (ldiscs[tty->disc].open)
 406                 return(ldiscs[tty->disc].open(tty));
 407         else
 408                 return 0;
 409 }
 410 
 411 
 412 int tty_ioctl(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 413         unsigned int cmd, unsigned long arg)
 414 {
 415         struct tty_struct * tty;
 416         struct tty_struct * other_tty;
 417         struct tty_struct * termios_tty;
 418         int pgrp;
 419         int dev;
 420         int termios_dev;
 421         int retval;
 422 
 423         if (MAJOR(file->f_rdev) != TTY_MAJOR) {
 424                 printk("tty_ioctl: tty pseudo-major != TTY_MAJOR\n");
 425                 return -EINVAL;
 426         }
 427         dev = MINOR(file->f_rdev);
 428         tty = TTY_TABLE(dev);
 429         if (!tty)
 430                 return -EINVAL;
 431         if (IS_A_PTY(dev))
 432                 other_tty = tty_table[PTY_OTHER(dev)];
 433         else
 434                 other_tty = NULL;
 435         termios_tty = tty;
 436         termios_dev = dev;
 437         if (IS_A_PTY_MASTER(dev)) {
 438                 termios_tty = other_tty;
 439                 termios_dev = PTY_OTHER(dev);
 440         }
 441         switch (cmd) {
 442                 case TCGETS:
 443                         return get_termios(termios_tty,(struct termios *) arg);
 444                 case TCSETSF:
 445                         flush_input(tty);
 446                 /* fallthrough */
 447                 case TCSETSW:
 448                         wait_until_sent(tty);
 449                 /* fallthrough */
 450                 case TCSETS:
 451                         return set_termios(termios_tty,(struct termios *) arg, termios_dev);
 452                 case TCGETA:
 453                         return get_termio(termios_tty,(struct termio *) arg);
 454                 case TCSETAF:
 455                         flush_input(tty);
 456                 /* fallthrough */
 457                 case TCSETAW:
 458                         wait_until_sent(tty); /* fallthrough */
 459                 case TCSETA:
 460                         return set_termio(termios_tty,(struct termio *) arg, termios_dev);
 461                 case TCXONC:
 462                         switch (arg) {
 463                         case TCOOFF:
 464                                 tty->stopped = 1;
 465                                 if (tty->stop)
 466                                         (tty->stop)(tty);
 467                                 TTY_WRITE_FLUSH(tty);
 468                                 return 0;
 469                         case TCOON:
 470                                 tty->stopped = 0;
 471                                 if (tty->start)
 472                                         (tty->start)(tty);
 473                                 TTY_WRITE_FLUSH(tty);
 474                                 return 0;
 475                         case TCIOFF:
 476                                 if (STOP_CHAR(tty))
 477                                         put_tty_queue(STOP_CHAR(tty),
 478                                                       &tty->write_q);
 479                                 return 0;
 480                         case TCION:
 481                                 if (START_CHAR(tty))
 482                                         put_tty_queue(START_CHAR(tty),
 483                                                       &tty->write_q);
 484                                 return 0;
 485                         }
 486                         return -EINVAL; /* not implemented */
 487                 case TCFLSH:
 488                         if (arg==0)
 489                                 flush_input(tty);
 490                         else if (arg==1)
 491                                 flush_output(tty);
 492                         else if (arg==2) {
 493                                 flush_input(tty);
 494                                 flush_output(tty);
 495                         } else
 496                                 return -EINVAL;
 497                         return 0;
 498                 case TIOCEXCL:
 499                         return -EINVAL; /* not implemented */
 500                 case TIOCNXCL:
 501                         return -EINVAL; /* not implemented */
 502                 case TIOCSCTTY:
 503                         if ((current->leader && current->tty < 0 &&
 504                              tty->session == 0) ||
 505                             (arg == 1 && suser())) {
 506                                 current->tty = dev;
 507                                 tty->session = current->session;
 508                                 tty->pgrp = current->pgrp;
 509                                 return 0;
 510                         }
 511                         return -EPERM;
 512                 case TIOCGPGRP:
 513                         retval = verify_area(VERIFY_WRITE, (void *) arg,4);
 514                         if (!retval)
 515                                 put_fs_long(termios_tty->pgrp,(unsigned long *) arg);
 516                         return retval;
 517                 case TIOCSPGRP:
 518                         if ((current->tty < 0) ||
 519                             (current->tty != termios_dev) ||
 520                             (termios_tty->session != current->session))
 521                                 return -ENOTTY;
 522                         pgrp=get_fs_long((unsigned long *) arg);
 523                         if (pgrp < 0)
 524                                 return -EINVAL;
 525                         if (session_of_pgrp(pgrp) != current->session)
 526                                 return -EPERM;
 527                         termios_tty->pgrp = pgrp;                       
 528                         return 0;
 529                 case TIOCOUTQ:
 530                         retval = verify_area(VERIFY_WRITE, (void *) arg,4);
 531                         if (!retval)
 532                                 put_fs_long(CHARS(&tty->write_q),
 533                                     (unsigned long *) arg);
 534                         return retval;
 535                 case TIOCINQ:
 536                         retval = verify_area(VERIFY_WRITE, (void *) arg,4);
 537                         if (retval)
 538                                 return retval;
 539                         if (L_CANON(tty) && !tty->secondary.data)
 540                                 put_fs_long(0, (unsigned long *) arg);
 541                         else
 542                                 put_fs_long(CHARS(&tty->secondary),
 543                                         (unsigned long *) arg);
 544                         return 0;
 545                 case TIOCSTI:
 546                         return -EINVAL; /* not implemented */
 547                 case TIOCGWINSZ:
 548                         return get_window_size(tty,(struct winsize *) arg);
 549                 case TIOCSWINSZ:
 550                         if (IS_A_PTY_MASTER(dev))
 551                                 set_window_size(other_tty,(struct winsize *) arg);
 552                         return set_window_size(tty,(struct winsize *) arg);
 553                 case TIOCGSOFTCAR:
 554                         return -EINVAL; /* not implemented */
 555                 case TIOCSSOFTCAR:
 556                         return -EINVAL; /* not implemented */
 557                 case TIOCLINUX:
 558                         switch (get_fs_byte((char *)arg))
 559                         {
 560                                 case 0: 
 561                                         return do_screendump(arg);
 562                                 case 1: 
 563                                         return do_get_ps_info(arg);
 564 #ifdef CONFIG_SELECTION
 565                                 case 2:
 566                                         return set_selection(arg);
 567                                 case 3:
 568                                         return paste_selection(tty);
 569 #endif /* CONFIG_SELECTION */
 570                                 default: 
 571                                         return -EINVAL;
 572                         }
 573                 case TIOCCONS:
 574                         if (IS_A_CONSOLE(dev)) {
 575                                 if (!suser())
 576                                         return -EPERM;
 577                                 redirect = NULL;
 578                                 return 0;
 579                         }
 580                         if (redirect)
 581                                 return -EBUSY;
 582                         if (!suser())
 583                                 return -EPERM;
 584                         if (IS_A_PTY_MASTER(dev))
 585                                 redirect = other_tty;
 586                         else if (IS_A_PTY_SLAVE(dev))
 587                                 redirect = tty;
 588                         else
 589                                 return -EINVAL;
 590                         return 0;
 591                 case FIONBIO:
 592                         arg = get_fs_long((unsigned long *) arg);
 593                         if (arg)
 594                                 file->f_flags |= O_NONBLOCK;
 595                         else
 596                                 file->f_flags &= ~O_NONBLOCK;
 597                         return 0;
 598                 case TIOCNOTTY:
 599                         if (MINOR(file->f_rdev) != current->tty)
 600                                 return -EINVAL;
 601                         current->tty = -1;
 602                         if (current->leader) {
 603                                 if (tty->pgrp > 0)
 604                                         kill_pg(tty->pgrp, SIGHUP, 0);
 605                                 tty->pgrp = -1;
 606                                 tty->session = 0;
 607                         }
 608                         return 0;
 609                 case TIOCGETD:
 610                         retval = verify_area(VERIFY_WRITE, (void *) arg,4);
 611                         if (!retval)
 612                                 put_fs_long(tty->disc, (unsigned long *) arg);
 613                         return retval;
 614                 case TIOCSETD:
 615                         arg = get_fs_long((unsigned long *) arg);
 616                         return tty_set_ldisc(tty, arg);
 617                 case TIOCGLCKTRMIOS:
 618                         arg = get_fs_long((unsigned long *) arg);
 619                         return get_lcktrmios(tty, (struct termios *) arg,
 620                                              termios_dev);
 621                 case TIOCSLCKTRMIOS:
 622                         arg = get_fs_long((unsigned long *) arg);
 623                         return set_lcktrmios(tty, (struct termios *) arg,
 624                                              termios_dev);
 625                 case TIOCPKT:
 626                         if (!IS_A_PTY_MASTER(dev))
 627                                 return -EINVAL;
 628                         retval = verify_area(VERIFY_READ,
 629                                 (unsigned long *)arg, sizeof (unsigned long));
 630                         if (retval)
 631                                 return retval;
 632                         tty->packet = (get_fs_long ((unsigned long *)arg) != 0);
 633                         return 0;
 634                 case TCSBRK: case TCSBRKP:
 635                         wait_until_sent(tty);
 636                         if (!tty->ioctl)
 637                                 return 0;
 638                         tty->ioctl(tty, file, cmd, arg);
 639                         return 0;
 640                 default:
 641                         if (tty->ioctl) {
 642                                 retval = (tty->ioctl)(tty, file, cmd, arg);
 643                                 if (retval != -EINVAL)
 644                                         return retval;
 645                         }
 646                         if (ldiscs[tty->disc].ioctl) {
 647                                 retval = (ldiscs[tty->disc].ioctl)
 648                                         (tty, file, cmd, arg);
 649                                 return retval;
 650                         }
 651                         return -EINVAL;
 652         }
 653 }

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