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

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