LTP GCOV extension - code coverage report
Current view: directory - drivers/char - tty_ioctl.c
Test: 2.6.14_rebootonly_gcov.info
Date: 2006-05-22 Instrumented lines: 202
Code covered: 45.0 % Executed lines: 91

       1                 : /*
       2                 :  *  linux/drivers/char/tty_ioctl.c
       3                 :  *
       4                 :  *  Copyright (C) 1991, 1992, 1993, 1994  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/kernel.h>
      16                 : #include <linux/major.h>
      17                 : #include <linux/tty.h>
      18                 : #include <linux/fcntl.h>
      19                 : #include <linux/string.h>
      20                 : #include <linux/mm.h>
      21                 : #include <linux/module.h>
      22                 : #include <linux/bitops.h>
      23                 : 
      24                 : #include <asm/io.h>
      25                 : #include <asm/uaccess.h>
      26                 : #include <asm/system.h>
      27                 : 
      28                 : #undef TTY_DEBUG_WAIT_UNTIL_SENT
      29                 : 
      30                 : #undef  DEBUG
      31                 : 
      32                 : /*
      33                 :  * Internal flag options for termios setting behavior
      34                 :  */
      35                 : #define TERMIOS_FLUSH   1
      36                 : #define TERMIOS_WAIT    2
      37                 : #define TERMIOS_TERMIO  4
      38                 : 
      39                 : void tty_wait_until_sent(struct tty_struct * tty, long timeout)
      40              34 : {
      41              34 :         DECLARE_WAITQUEUE(wait, current);
      42                 : 
      43                 : #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
      44                 :         char buf[64];
      45                 :         
      46                 :         printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
      47                 : #endif
      48              34 :         if (!tty->driver->chars_in_buffer)
      49              34 :                 return;
      50              34 :         add_wait_queue(&tty->write_wait, &wait);
      51              34 :         if (!timeout)
      52              30 :                 timeout = MAX_SCHEDULE_TIMEOUT;
      53              34 :         do {
      54                 : #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
      55                 :                 printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf),
      56                 :                        tty->driver->chars_in_buffer(tty));
      57                 : #endif
      58              34 :                 set_current_state(TASK_INTERRUPTIBLE);
      59              34 :                 if (signal_pending(current))
      60              34 :                         goto stop_waiting;
      61              34 :                 if (!tty->driver->chars_in_buffer(tty))
      62               0 :                         break;
      63               0 :                 timeout = schedule_timeout(timeout);
      64               0 :         } while (timeout);
      65              34 :         if (tty->driver->wait_until_sent)
      66               4 :                 tty->driver->wait_until_sent(tty, timeout);
      67                 : stop_waiting:
      68              34 :         set_current_state(TASK_RUNNING);
      69              34 :         remove_wait_queue(&tty->write_wait, &wait);
      70                 : }
      71                 : 
      72                 : EXPORT_SYMBOL(tty_wait_until_sent);
      73                 : 
      74                 : static void unset_locked_termios(struct termios *termios,
      75                 :                                  struct termios *old,
      76                 :                                  struct termios *locked)
      77              40 : {
      78              40 :         int     i;
      79                 :         
      80                 : #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
      81                 : 
      82              40 :         if (!locked) {
      83               0 :                 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
      84              40 :                 return;
      85                 :         }
      86                 : 
      87              40 :         NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
      88              40 :         NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
      89              40 :         NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
      90              40 :         NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
      91              40 :         termios->c_line = locked->c_line ? old->c_line : termios->c_line;
      92             800 :         for (i=0; i < NCCS; i++)
      93             760 :                 termios->c_cc[i] = locked->c_cc[i] ?
      94                 :                         old->c_cc[i] : termios->c_cc[i];
      95                 : }
      96                 : 
      97                 : static void change_termios(struct tty_struct * tty, struct termios * new_termios)
      98              40 : {
      99              40 :         int canon_change;
     100              40 :         struct termios old_termios = *tty->termios;
     101              40 :         struct tty_ldisc *ld;
     102                 :         
     103                 :         /*
     104                 :          *      Perform the actual termios internal changes under lock.
     105                 :          */
     106                 :          
     107                 : 
     108                 :         /* FIXME: we need to decide on some locking/ordering semantics
     109                 :            for the set_termios notification eventually */
     110              40 :         down(&tty->termios_sem);
     111                 : 
     112              40 :         *tty->termios = *new_termios;
     113              40 :         unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
     114              40 :         canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
     115              40 :         if (canon_change) {
     116              17 :                 memset(&tty->read_flags, 0, sizeof tty->read_flags);
     117              17 :                 tty->canon_head = tty->read_tail;
     118              17 :                 tty->canon_data = 0;
     119              17 :                 tty->erasing = 0;
     120                 :         }
     121                 :         
     122                 :         
     123              17 :         if (canon_change && !L_ICANON(tty) && tty->read_cnt)
     124                 :                 /* Get characters left over from canonical mode. */
     125               0 :                 wake_up_interruptible(&tty->read_wait);
     126                 : 
     127                 :         /* See if packet mode change of state. */
     128                 : 
     129              40 :         if (tty->link && tty->link->packet) {
     130               0 :                 int old_flow = ((old_termios.c_iflag & IXON) &&
     131                 :                                 (old_termios.c_cc[VSTOP] == '\023') &&
     132               0 :                                 (old_termios.c_cc[VSTART] == '\021'));
     133               0 :                 int new_flow = (I_IXON(tty) &&
     134                 :                                 STOP_CHAR(tty) == '\023' &&
     135               0 :                                 START_CHAR(tty) == '\021');
     136               0 :                 if (old_flow != new_flow) {
     137               0 :                         tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
     138               0 :                         if (new_flow)
     139               0 :                                 tty->ctrl_status |= TIOCPKT_DOSTOP;
     140                 :                         else
     141               0 :                                 tty->ctrl_status |= TIOCPKT_NOSTOP;
     142               0 :                         wake_up_interruptible(&tty->link->read_wait);
     143                 :                 }
     144                 :         }
     145                 :            
     146              40 :         if (tty->driver->set_termios)
     147               0 :                 (*tty->driver->set_termios)(tty, &old_termios);
     148                 : 
     149              40 :         ld = tty_ldisc_ref(tty);
     150              40 :         if (ld != NULL) {
     151              40 :                 if (ld->set_termios)
     152              40 :                         (ld->set_termios)(tty, &old_termios);
     153              40 :                 tty_ldisc_deref(ld);
     154                 :         }
     155              40 :         up(&tty->termios_sem);
     156                 : }
     157                 : 
     158                 : static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
     159              40 : {
     160              40 :         struct termios tmp_termios;
     161              40 :         struct tty_ldisc *ld;
     162              40 :         int retval = tty_check_change(tty);
     163                 : 
     164              40 :         if (retval)
     165               0 :                 return retval;
     166                 : 
     167              40 :         if (opt & TERMIOS_TERMIO) {
     168               0 :                 memcpy(&tmp_termios, tty->termios, sizeof(struct termios));
     169               0 :                 if (user_termio_to_kernel_termios(&tmp_termios,
     170                 :                                                 (struct termio __user *)arg))
     171               0 :                         return -EFAULT;
     172                 :         } else {
     173              40 :                 if (user_termios_to_kernel_termios(&tmp_termios,
     174                 :                                                 (struct termios __user *)arg))
     175               0 :                         return -EFAULT;
     176                 :         }
     177                 : 
     178              40 :         ld = tty_ldisc_ref(tty);
     179                 :         
     180              40 :         if (ld != NULL) {
     181              40 :                 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
     182               4 :                         ld->flush_buffer(tty);
     183              40 :                 tty_ldisc_deref(ld);
     184                 :         }
     185                 :         
     186              40 :         if (opt & TERMIOS_WAIT) {
     187              30 :                 tty_wait_until_sent(tty, 0);
     188              30 :                 if (signal_pending(current))
     189               0 :                         return -EINTR;
     190                 :         }
     191                 : 
     192              40 :         change_termios(tty, &tmp_termios);
     193              40 :         return 0;
     194                 : }
     195                 : 
     196                 : static int get_termio(struct tty_struct * tty, struct termio __user * termio)
     197               0 : {
     198               0 :         if (kernel_termios_to_user_termio(termio, tty->termios))
     199               0 :                 return -EFAULT;
     200               0 :         return 0;
     201                 : }
     202                 : 
     203                 : static unsigned long inq_canon(struct tty_struct * tty)
     204               0 : {
     205               0 :         int nr, head, tail;
     206                 : 
     207               0 :         if (!tty->canon_data || !tty->read_buf)
     208               0 :                 return 0;
     209               0 :         head = tty->canon_head;
     210               0 :         tail = tty->read_tail;
     211               0 :         nr = (head - tail) & (N_TTY_BUF_SIZE-1);
     212                 :         /* Skip EOF-chars.. */
     213               0 :         while (head != tail) {
     214               0 :                 if (test_bit(tail, tty->read_flags) &&
     215                 :                     tty->read_buf[tail] == __DISABLED_CHAR)
     216               0 :                         nr--;
     217               0 :                 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
     218                 :         }
     219               0 :         return nr;
     220                 : }
     221                 : 
     222                 : #ifdef TIOCGETP
     223                 : /*
     224                 :  * These are deprecated, but there is limited support..
     225                 :  *
     226                 :  * The "sg_flags" translation is a joke..
     227                 :  */
     228                 : static int get_sgflags(struct tty_struct * tty)
     229                 : {
     230                 :         int flags = 0;
     231                 : 
     232                 :         if (!(tty->termios->c_lflag & ICANON)) {
     233                 :                 if (tty->termios->c_lflag & ISIG)
     234                 :                         flags |= 0x02;          /* cbreak */
     235                 :                 else
     236                 :                         flags |= 0x20;          /* raw */
     237                 :         }
     238                 :         if (tty->termios->c_lflag & ECHO)
     239                 :                 flags |= 0x08;                  /* echo */
     240                 :         if (tty->termios->c_oflag & OPOST)
     241                 :                 if (tty->termios->c_oflag & ONLCR)
     242                 :                         flags |= 0x10;          /* crmod */
     243                 :         return flags;
     244                 : }
     245                 : 
     246                 : static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
     247                 : {
     248                 :         struct sgttyb tmp;
     249                 : 
     250                 :         down(&tty->termios_sem);
     251                 :         tmp.sg_ispeed = 0;
     252                 :         tmp.sg_ospeed = 0;
     253                 :         tmp.sg_erase = tty->termios->c_cc[VERASE];
     254                 :         tmp.sg_kill = tty->termios->c_cc[VKILL];
     255                 :         tmp.sg_flags = get_sgflags(tty);
     256                 :         up(&tty->termios_sem);
     257                 :         
     258                 :         return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
     259                 : }
     260                 : 
     261                 : static void set_sgflags(struct termios * termios, int flags)
     262                 : {
     263                 :         termios->c_iflag = ICRNL | IXON;
     264                 :         termios->c_oflag = 0;
     265                 :         termios->c_lflag = ISIG | ICANON;
     266                 :         if (flags & 0x02) { /* cbreak */
     267                 :                 termios->c_iflag = 0;
     268                 :                 termios->c_lflag &= ~ICANON;
     269                 :         }
     270                 :         if (flags & 0x08) {         /* echo */
     271                 :                 termios->c_lflag |= ECHO | ECHOE | ECHOK |
     272                 :                                     ECHOCTL | ECHOKE | IEXTEN;
     273                 :         }
     274                 :         if (flags & 0x10) {         /* crmod */
     275                 :                 termios->c_oflag |= OPOST | ONLCR;
     276                 :         }
     277                 :         if (flags & 0x20) { /* raw */
     278                 :                 termios->c_iflag = 0;
     279                 :                 termios->c_lflag &= ~(ISIG | ICANON);
     280                 :         }
     281                 :         if (!(termios->c_lflag & ICANON)) {
     282                 :                 termios->c_cc[VMIN] = 1;
     283                 :                 termios->c_cc[VTIME] = 0;
     284                 :         }
     285                 : }
     286                 : 
     287                 : static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
     288                 : {
     289                 :         int retval;
     290                 :         struct sgttyb tmp;
     291                 :         struct termios termios;
     292                 : 
     293                 :         retval = tty_check_change(tty);
     294                 :         if (retval)
     295                 :                 return retval;
     296                 :         
     297                 :         if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
     298                 :                 return -EFAULT;
     299                 : 
     300                 :         down(&tty->termios_sem);         
     301                 :         termios =  *tty->termios;
     302                 :         termios.c_cc[VERASE] = tmp.sg_erase;
     303                 :         termios.c_cc[VKILL] = tmp.sg_kill;
     304                 :         set_sgflags(&termios, tmp.sg_flags);
     305                 :         up(&tty->termios_sem);
     306                 :         change_termios(tty, &termios);
     307                 :         return 0;
     308                 : }
     309                 : #endif
     310                 : 
     311                 : #ifdef TIOCGETC
     312                 : static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
     313                 : {
     314                 :         struct tchars tmp;
     315                 : 
     316                 :         tmp.t_intrc = tty->termios->c_cc[VINTR];
     317                 :         tmp.t_quitc = tty->termios->c_cc[VQUIT];
     318                 :         tmp.t_startc = tty->termios->c_cc[VSTART];
     319                 :         tmp.t_stopc = tty->termios->c_cc[VSTOP];
     320                 :         tmp.t_eofc = tty->termios->c_cc[VEOF];
     321                 :         tmp.t_brkc = tty->termios->c_cc[VEOL2];   /* what is brkc anyway? */
     322                 :         return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
     323                 : }
     324                 : 
     325                 : static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
     326                 : {
     327                 :         struct tchars tmp;
     328                 : 
     329                 :         if (copy_from_user(&tmp, tchars, sizeof(tmp)))
     330                 :                 return -EFAULT;
     331                 :         tty->termios->c_cc[VINTR] = tmp.t_intrc;
     332                 :         tty->termios->c_cc[VQUIT] = tmp.t_quitc;
     333                 :         tty->termios->c_cc[VSTART] = tmp.t_startc;
     334                 :         tty->termios->c_cc[VSTOP] = tmp.t_stopc;
     335                 :         tty->termios->c_cc[VEOF] = tmp.t_eofc;
     336                 :         tty->termios->c_cc[VEOL2] = tmp.t_brkc;   /* what is brkc anyway? */
     337                 :         return 0;
     338                 : }
     339                 : #endif
     340                 : 
     341                 : #ifdef TIOCGLTC
     342                 : static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
     343                 : {
     344                 :         struct ltchars tmp;
     345                 : 
     346                 :         tmp.t_suspc = tty->termios->c_cc[VSUSP];
     347                 :         tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */
     348                 :         tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
     349                 :         tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */
     350                 :         tmp.t_werasc = tty->termios->c_cc[VWERASE];
     351                 :         tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
     352                 :         return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
     353                 : }
     354                 : 
     355                 : static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
     356                 : {
     357                 :         struct ltchars tmp;
     358                 : 
     359                 :         if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
     360                 :                 return -EFAULT;
     361                 : 
     362                 :         tty->termios->c_cc[VSUSP] = tmp.t_suspc;
     363                 :         tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */
     364                 :         tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
     365                 :         tty->termios->c_cc[VEOL2] = tmp.t_flushc; /* what is flushc anyway? */
     366                 :         tty->termios->c_cc[VWERASE] = tmp.t_werasc;
     367                 :         tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
     368                 :         return 0;
     369                 : }
     370                 : #endif
     371                 : 
     372                 : /*
     373                 :  * Send a high priority character to the tty.
     374                 :  */
     375                 : static void send_prio_char(struct tty_struct *tty, char ch)
     376               0 : {
     377               0 :         int     was_stopped = tty->stopped;
     378                 : 
     379               0 :         if (tty->driver->send_xchar) {
     380               0 :                 tty->driver->send_xchar(tty, ch);
     381               0 :                 return;
     382                 :         }
     383               0 :         if (was_stopped)
     384               0 :                 start_tty(tty);
     385               0 :         tty->driver->write(tty, &ch, 1);
     386               0 :         if (was_stopped)
     387               0 :                 stop_tty(tty);
     388                 : }
     389                 : 
     390                 : int n_tty_ioctl(struct tty_struct * tty, struct file * file,
     391                 :                        unsigned int cmd, unsigned long arg)
     392             165 : {
     393             165 :         struct tty_struct * real_tty;
     394             165 :         void __user *p = (void __user *)arg;
     395             165 :         int retval;
     396             165 :         struct tty_ldisc *ld;
     397                 : 
     398             165 :         if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
     399                 :             tty->driver->subtype == PTY_TYPE_MASTER)
     400               0 :                 real_tty = tty->link;
     401                 :         else
     402             165 :                 real_tty = tty;
     403                 : 
     404             165 :         switch (cmd) {
     405                 : #ifdef TIOCGETP
     406                 :                 case TIOCGETP:
     407                 :                         return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
     408                 :                 case TIOCSETP:
     409                 :                 case TIOCSETN:
     410                 :                         return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
     411                 : #endif
     412                 : #ifdef TIOCGETC
     413                 :                 case TIOCGETC:
     414                 :                         return get_tchars(real_tty, p);
     415                 :                 case TIOCSETC:
     416                 :                         return set_tchars(real_tty, p);
     417                 : #endif
     418                 : #ifdef TIOCGLTC
     419                 :                 case TIOCGLTC:
     420                 :                         return get_ltchars(real_tty, p);
     421                 :                 case TIOCSLTC:
     422                 :                         return set_ltchars(real_tty, p);
     423                 : #endif
     424                 :                 case TCGETS:
     425             110 :                         if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
     426               0 :                                 return -EFAULT;
     427             110 :                         return 0;
     428                 :                 case TCSETSF:
     429               4 :                         return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
     430                 :                 case TCSETSW:
     431              26 :                         return set_termios(real_tty, p, TERMIOS_WAIT);
     432                 :                 case TCSETS:
     433              10 :                         return set_termios(real_tty, p, 0);
     434                 :                 case TCGETA:
     435               0 :                         return get_termio(real_tty, p);
     436                 :                 case TCSETAF:
     437               0 :                         return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
     438                 :                 case TCSETAW:
     439               0 :                         return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
     440                 :                 case TCSETA:
     441               0 :                         return set_termios(real_tty, p, TERMIOS_TERMIO);
     442                 :                 case TCXONC:
     443               0 :                         retval = tty_check_change(tty);
     444               0 :                         if (retval)
     445               0 :                                 return retval;
     446               0 :                         switch (arg) {
     447                 :                         case TCOOFF:
     448               0 :                                 if (!tty->flow_stopped) {
     449               0 :                                         tty->flow_stopped = 1;
     450               0 :                                         stop_tty(tty);
     451                 :                                 }
     452               0 :                                 break;
     453                 :                         case TCOON:
     454               0 :                                 if (tty->flow_stopped) {
     455               0 :                                         tty->flow_stopped = 0;
     456               0 :                                         start_tty(tty);
     457                 :                                 }
     458               0 :                                 break;
     459                 :                         case TCIOFF:
     460               0 :                                 if (STOP_CHAR(tty) != __DISABLED_CHAR)
     461               0 :                                         send_prio_char(tty, STOP_CHAR(tty));
     462               0 :                                 break;
     463                 :                         case TCION:
     464               0 :                                 if (START_CHAR(tty) != __DISABLED_CHAR)
     465               0 :                                         send_prio_char(tty, START_CHAR(tty));
     466               0 :                                 break;
     467                 :                         default:
     468               0 :                                 return -EINVAL;
     469                 :                         }
     470               0 :                         return 0;
     471                 :                 case TCFLSH:
     472              15 :                         retval = tty_check_change(tty);
     473              15 :                         if (retval)
     474               0 :                                 return retval;
     475                 :                                 
     476              15 :                         ld = tty_ldisc_ref(tty);
     477              15 :                         switch (arg) {
     478                 :                         case TCIFLUSH:
     479               6 :                                 if (ld && ld->flush_buffer)
     480               6 :                                         ld->flush_buffer(tty);
     481               6 :                                 break;
     482                 :                         case TCIOFLUSH:
     483               9 :                                 if (ld && ld->flush_buffer)
     484               9 :                                         ld->flush_buffer(tty);
     485                 :                                 /* fall through */
     486                 :                         case TCOFLUSH:
     487               9 :                                 if (tty->driver->flush_buffer)
     488               0 :                                         tty->driver->flush_buffer(tty);
     489               0 :                                 break;
     490                 :                         default:
     491               0 :                                 tty_ldisc_deref(ld);
     492               0 :                                 return -EINVAL;
     493                 :                         }
     494              15 :                         tty_ldisc_deref(ld);
     495              15 :                         return 0;
     496                 :                 case TIOCOUTQ:
     497               0 :                         return put_user(tty->driver->chars_in_buffer ?
     498                 :                                         tty->driver->chars_in_buffer(tty) : 0,
     499                 :                                         (int __user *) arg);
     500                 :                 case TIOCINQ:
     501               0 :                         retval = tty->read_cnt;
     502               0 :                         if (L_ICANON(tty))
     503               0 :                                 retval = inq_canon(tty);
     504               0 :                         return put_user(retval, (unsigned int __user *) arg);
     505                 :                 case TIOCGLCKTRMIOS:
     506               0 :                         if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
     507               0 :                                 return -EFAULT;
     508               0 :                         return 0;
     509                 : 
     510                 :                 case TIOCSLCKTRMIOS:
     511               0 :                         if (!capable(CAP_SYS_ADMIN))
     512               0 :                                 return -EPERM;
     513               0 :                         if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
     514               0 :                                 return -EFAULT;
     515               0 :                         return 0;
     516                 : 
     517                 :                 case TIOCPKT:
     518                 :                 {
     519               0 :                         int pktmode;
     520                 : 
     521               0 :                         if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
     522                 :                             tty->driver->subtype != PTY_TYPE_MASTER)
     523               0 :                                 return -ENOTTY;
     524               0 :                         if (get_user(pktmode, (int __user *) arg))
     525               0 :                                 return -EFAULT;
     526               0 :                         if (pktmode) {
     527               0 :                                 if (!tty->packet) {
     528               0 :                                         tty->packet = 1;
     529               0 :                                         tty->link->ctrl_status = 0;
     530                 :                                 }
     531                 :                         } else
     532               0 :                                 tty->packet = 0;
     533               0 :                         return 0;
     534                 :                 }
     535                 :                 case TIOCGSOFTCAR:
     536               0 :                         return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
     537                 :                 case TIOCSSOFTCAR:
     538               0 :                         if (get_user(arg, (unsigned int __user *) arg))
     539               0 :                                 return -EFAULT;
     540               0 :                         down(&tty->termios_sem);
     541               0 :                         tty->termios->c_cflag =
     542                 :                                 ((tty->termios->c_cflag & ~CLOCAL) |
     543                 :                                  (arg ? CLOCAL : 0));
     544               0 :                         up(&tty->termios_sem);
     545               0 :                         return 0;
     546                 :                 default:
     547               0 :                         return -ENOIOCTLCMD;
     548                 :                 }
     549                 : }
     550                 : 
     551                 : EXPORT_SYMBOL(n_tty_ioctl);

Generated by: LTP GCOV extension version 1.4