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 static int set_termio(struct tty_struct * tty, struct termio * termio,
     /* [previous][next][first][last][top][bottom][index][help] */
 264                         int channel)
 265 {
 266         int i, old_flow, new_flow;
 267         struct termio tmp_termio;
 268         struct termios old_termios = *tty->termios;
 269 
 270 #define SET_LOW_BITS(x,y)       ((x) = (0xffff0000 & (x)) | (y))
 271 
 272         i = check_change(tty, channel);
 273         if (i)
 274                 return i;
 275         memcpy_fromfs(&tmp_termio, termio, sizeof(*termio));
 276 
 277         SET_LOW_BITS(tty->termios->c_iflag, tmp_termio.c_iflag);
 278         SET_LOW_BITS(tty->termios->c_oflag, tmp_termio.c_oflag);
 279         SET_LOW_BITS(tty->termios->c_cflag, tmp_termio.c_cflag);
 280         SET_LOW_BITS(tty->termios->c_lflag, tmp_termio.c_lflag);
 281         memcpy(tty->termios->c_cc, tmp_termio.c_cc, NCC);
 282 
 283         /* see if packet mode change of state */
 284 
 285         old_flow = (old_termios.c_iflag & IXON) &&
 286               (old_termios.c_cc[VSTOP] == '\023') &&
 287               (old_termios.c_cc[VSTART] == '\021');
 288 
 289         new_flow = (tty->termios->c_iflag & IXON) &&
 290               (tty->termios->c_cc[VSTOP] == '\023') &&
 291               (tty->termios->c_cc[VSTART] == '\021');
 292 
 293         if (old_flow != new_flow) {
 294                 tty->ctrl_status &= ~(TIOCPKT_DOSTOP|TIOCPKT_NOSTOP);
 295                 if (new_flow)
 296                         tty->ctrl_status |= TIOCPKT_DOSTOP;
 297                 else
 298                         tty->ctrl_status |= TIOCPKT_NOSTOP;             
 299                 if (tty->link)
 300                         wake_up_interruptible(&tty->link->except_q);
 301         }
 302 
 303         unset_locked_termios(tty->termios, &old_termios,
 304                              termios_locked[tty->line]);
 305 
 306 #if 0
 307         retval = tty_set_ldisc(tty, tmp_termio.c_line);
 308         if (retval)
 309                 return retval;
 310 #endif
 311 
 312         if (tty->set_termios)
 313                 (*tty->set_termios)(tty, &old_termios);
 314 
 315         return 0;
 316 }
 317 
 318 static int get_lcktrmios(struct tty_struct * tty, struct termios * termios,
     /* [previous][next][first][last][top][bottom][index][help] */
 319                          int channel)
 320 {
 321         int i;
 322 
 323         i = verify_area(VERIFY_WRITE, termios, sizeof (*termios));
 324         if (i)
 325                 return i;
 326         for (i=0 ; i< (sizeof (*termios)) ; i++)
 327                 put_fs_byte( ((char *)termios_locked[channel])[i],
 328                             i+(char *)termios);
 329         return 0;
 330 }
 331 
 332 static int set_lcktrmios(struct tty_struct * tty, struct termios * termios,
     /* [previous][next][first][last][top][bottom][index][help] */
 333                          int channel)
 334 {
 335         int i;
 336 
 337         if (!suser())
 338                 return -EPERM;
 339         for (i=0 ; i< (sizeof (*termios)) ; i++)
 340                 ((char *)termios_locked[channel])[i] =
 341                         get_fs_byte(i+(char *)termios);
 342 
 343         return 0;
 344 }
 345 
 346 static int set_window_size(struct tty_struct * tty, struct winsize * ws)
     /* [previous][next][first][last][top][bottom][index][help] */
 347 {
 348         int i,changed;
 349         char c, * tmp;
 350 
 351         if (!ws)
 352                 return -EINVAL;
 353         tmp = (char *) &tty->winsize;
 354         changed = 0;
 355         for (i = 0; i < sizeof (*ws) ; i++,tmp++) {
 356                 c = get_fs_byte(i + (char *) ws);
 357                 if (c == *tmp)
 358                         continue;
 359                 changed = 1;
 360                 *tmp = c;
 361         }
 362         if (changed)
 363                 kill_pg(tty->pgrp, SIGWINCH, 1);
 364         return 0;
 365 }
 366 
 367 static int get_window_size(struct tty_struct * tty, struct winsize * ws)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369         int i;
 370         char * tmp;
 371 
 372         if (!ws)
 373                 return -EINVAL;
 374         i = verify_area(VERIFY_WRITE, ws, sizeof (*ws));
 375         if (i)
 376                 return i;
 377         tmp = (char *) ws;
 378         for (i = 0; i < sizeof (struct winsize) ; i++,tmp++)
 379                 put_fs_byte(((char *) &tty->winsize)[i], tmp);
 380         return 0;
 381 }
 382 
 383 /* Set the discipline of a tty line. */
 384 static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386         if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS) ||
 387             !(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
 388                 return -EINVAL;
 389 
 390         if (tty->disc == ldisc)
 391                 return 0;       /* We are already in the desired discipline */
 392 
 393         /* Shutdown the current discipline. */
 394         wait_until_sent(tty);
 395         flush_input(tty);
 396         if (ldiscs[tty->disc].close)
 397                 ldiscs[tty->disc].close(tty);
 398 
 399         /* Now set up the new line discipline. */
 400         tty->disc = ldisc;
 401         tty->termios->c_line = ldisc;
 402         if (ldiscs[tty->disc].open)
 403                 return(ldiscs[tty->disc].open(tty));
 404         else
 405                 return 0;
 406 }
 407 
 408 
 409 int tty_ioctl(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 410         unsigned int cmd, unsigned long arg)
 411 {
 412         struct tty_struct * tty;
 413         struct tty_struct * other_tty;
 414         struct tty_struct * termios_tty;
 415         int pgrp;
 416         int dev;
 417         int termios_dev;
 418         int retval;
 419 
 420         if (MAJOR(file->f_rdev) != TTY_MAJOR) {
 421                 printk("tty_ioctl: tty pseudo-major != TTY_MAJOR\n");
 422                 return -EINVAL;
 423         }
 424         dev = MINOR(file->f_rdev);
 425         tty = TTY_TABLE(dev);
 426         if (!tty)
 427                 return -EINVAL;
 428         if (IS_A_PTY(dev))
 429                 other_tty = tty_table[PTY_OTHER(dev)];
 430         else
 431                 other_tty = NULL;
 432         termios_tty = tty;
 433         termios_dev = dev;
 434         if (IS_A_PTY_MASTER(dev)) {
 435                 termios_tty = other_tty;
 436                 termios_dev = PTY_OTHER(dev);
 437         }
 438         switch (cmd) {
 439                 case TCGETS:
 440                         return get_termios(termios_tty,(struct termios *) arg);
 441                 case TCSETSF:
 442                         flush_input(tty);
 443                 /* fallthrough */
 444                 case TCSETSW:
 445                         wait_until_sent(tty);
 446                 /* fallthrough */
 447                 case TCSETS:
 448                         return set_termios(termios_tty,(struct termios *) arg, termios_dev);
 449                 case TCGETA:
 450                         return get_termio(termios_tty,(struct termio *) arg);
 451                 case TCSETAF:
 452                         flush_input(tty);
 453                 /* fallthrough */
 454                 case TCSETAW:
 455                         wait_until_sent(tty); /* fallthrough */
 456                 case TCSETA:
 457                         return set_termio(termios_tty,(struct termio *) arg, termios_dev);
 458                 case TCXONC:
 459                         switch (arg) {
 460                         case TCOOFF:
 461                                 tty->stopped = 1;
 462                                 if (tty->stop)
 463                                         (tty->stop)(tty);
 464                                 TTY_WRITE_FLUSH(tty);
 465                                 return 0;
 466                         case TCOON:
 467                                 tty->stopped = 0;
 468                                 if (tty->start)
 469                                         (tty->start)(tty);
 470                                 TTY_WRITE_FLUSH(tty);
 471                                 return 0;
 472                         case TCIOFF:
 473                                 if (STOP_CHAR(tty))
 474                                         put_tty_queue(STOP_CHAR(tty),
 475                                                       &tty->write_q);
 476                                 return 0;
 477                         case TCION:
 478                                 if (START_CHAR(tty))
 479                                         put_tty_queue(START_CHAR(tty),
 480                                                       &tty->write_q);
 481                                 return 0;
 482                         }
 483                         return -EINVAL; /* not implemented */
 484                 case TCFLSH:
 485                         if (arg==0)
 486                                 flush_input(tty);
 487                         else if (arg==1)
 488                                 flush_output(tty);
 489                         else if (arg==2) {
 490                                 flush_input(tty);
 491                                 flush_output(tty);
 492                         } else
 493                                 return -EINVAL;
 494                         return 0;
 495                 case TIOCEXCL:
 496                         return -EINVAL; /* not implemented */
 497                 case TIOCNXCL:
 498                         return -EINVAL; /* not implemented */
 499                 case TIOCSCTTY:
 500                         if ((current->leader && current->tty < 0 &&
 501                              tty->session == 0) ||
 502                             (arg == 1 && suser())) {
 503                                 current->tty = dev;
 504                                 tty->session = current->session;
 505                                 tty->pgrp = current->pgrp;
 506                                 return 0;
 507                         }
 508                         return -EPERM;
 509                 case TIOCGPGRP:
 510                         retval = verify_area(VERIFY_WRITE, (void *) arg,4);
 511                         if (!retval)
 512                                 put_fs_long(termios_tty->pgrp,(unsigned long *) arg);
 513                         return retval;
 514                 case TIOCSPGRP:
 515                         if ((current->tty < 0) ||
 516                             (current->tty != termios_dev) ||
 517                             (termios_tty->session != current->session))
 518                                 return -ENOTTY;
 519                         pgrp=get_fs_long((unsigned long *) arg);
 520                         if (pgrp < 0)
 521                                 return -EINVAL;
 522                         if (session_of_pgrp(pgrp) != current->session)
 523                                 return -EPERM;
 524                         termios_tty->pgrp = pgrp;                       
 525                         return 0;
 526                 case TIOCOUTQ:
 527                         retval = verify_area(VERIFY_WRITE, (void *) arg,4);
 528                         if (!retval)
 529                                 put_fs_long(CHARS(&tty->write_q),
 530                                     (unsigned long *) arg);
 531                         return retval;
 532                 case TIOCINQ:
 533                         retval = verify_area(VERIFY_WRITE, (void *) arg,4);
 534                         if (retval)
 535                                 return retval;
 536                         if (L_CANON(tty) && !tty->secondary.data)
 537                                 put_fs_long(0, (unsigned long *) arg);
 538                         else
 539                                 put_fs_long(CHARS(&tty->secondary),
 540                                         (unsigned long *) arg);
 541                         return 0;
 542                 case TIOCSTI:
 543                         return -EINVAL; /* not implemented */
 544                 case TIOCGWINSZ:
 545                         return get_window_size(tty,(struct winsize *) arg);
 546                 case TIOCSWINSZ:
 547                         if (IS_A_PTY_MASTER(dev))
 548                                 set_window_size(other_tty,(struct winsize *) arg);
 549                         return set_window_size(tty,(struct winsize *) arg);
 550                 case TIOCGSOFTCAR:
 551                         return -EINVAL; /* not implemented */
 552                 case TIOCSSOFTCAR:
 553                         return -EINVAL; /* not implemented */
 554                 case TIOCLINUX:
 555                         switch (get_fs_byte((char *)arg))
 556                         {
 557                                 case 0: 
 558                                         return do_screendump(arg);
 559                                 case 1: 
 560                                         return do_get_ps_info(arg);
 561 #ifdef CONFIG_SELECTION
 562                                 case 2:
 563                                         return set_selection(arg);
 564                                 case 3:
 565                                         return paste_selection(tty);
 566 #endif /* CONFIG_SELECTION */
 567                                 default: 
 568                                         return -EINVAL;
 569                         }
 570                 case TIOCCONS:
 571                         if (IS_A_CONSOLE(dev)) {
 572                                 if (!suser())
 573                                         return -EPERM;
 574                                 redirect = NULL;
 575                                 return 0;
 576                         }
 577                         if (redirect)
 578                                 return -EBUSY;
 579                         if (!suser())
 580                                 return -EPERM;
 581                         if (IS_A_PTY_MASTER(dev))
 582                                 redirect = other_tty;
 583                         else if (IS_A_PTY_SLAVE(dev))
 584                                 redirect = tty;
 585                         else
 586                                 return -EINVAL;
 587                         return 0;
 588                 case FIONBIO:
 589                         arg = get_fs_long((unsigned long *) arg);
 590                         if (arg)
 591                                 file->f_flags |= O_NONBLOCK;
 592                         else
 593                                 file->f_flags &= ~O_NONBLOCK;
 594                         return 0;
 595                 case TIOCNOTTY:
 596                         if (MINOR(file->f_rdev) != current->tty)
 597                                 return -EINVAL;
 598                         current->tty = -1;
 599                         if (current->leader) {
 600                                 if (tty->pgrp > 0)
 601                                         kill_pg(tty->pgrp, SIGHUP, 0);
 602                                 tty->pgrp = -1;
 603                                 tty->session = 0;
 604                         }
 605                         return 0;
 606                 case TIOCGETD:
 607                         retval = verify_area(VERIFY_WRITE, (void *) arg,4);
 608                         if (!retval)
 609                                 put_fs_long(tty->disc, (unsigned long *) arg);
 610                         return retval;
 611                 case TIOCSETD:
 612                         arg = get_fs_long((unsigned long *) arg);
 613                         return tty_set_ldisc(tty, arg);
 614                 case TIOCGLCKTRMIOS:
 615                         arg = get_fs_long((unsigned long *) arg);
 616                         return get_lcktrmios(tty, (struct termios *) arg,
 617                                              termios_dev);
 618                 case TIOCSLCKTRMIOS:
 619                         arg = get_fs_long((unsigned long *) arg);
 620                         return set_lcktrmios(tty, (struct termios *) arg,
 621                                              termios_dev);
 622                 case TIOCPKT:
 623                         if (!IS_A_PTY_MASTER(dev))
 624                                 return -EINVAL;
 625                         retval = verify_area(VERIFY_READ,
 626                                 (unsigned long *)arg, sizeof (unsigned long));
 627                         if (retval)
 628                                 return retval;
 629                         tty->packet = (get_fs_long ((unsigned long *)arg) != 0);
 630                         return 0;
 631                 case TCSBRK: case TCSBRKP:
 632                         wait_until_sent(tty);
 633                         if (!tty->ioctl)
 634                                 return 0;
 635                         tty->ioctl(tty, file, cmd, arg);
 636                         return 0;
 637                 default:
 638                         if (tty->ioctl) {
 639                                 retval = (tty->ioctl)(tty, file, cmd, arg);
 640                                 if (retval != -EINVAL)
 641                                         return retval;
 642                         }
 643                         if (ldiscs[tty->disc].ioctl) {
 644                                 retval = (ldiscs[tty->disc].ioctl)
 645                                         (tty, file, cmd, arg);
 646                                 return retval;
 647                         }
 648                         return -EINVAL;
 649         }
 650 }

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