Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 73274
b: refs/heads/master
c: 0fc00e2
h: refs/heads/master
v: v3
  • Loading branch information
Alan Cox authored and David S. Miller committed Nov 7, 2007
1 parent 5988273 commit 5ab14aa
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 68 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 543821c6f5dea5221426eaf1eac98b100249c7ac
refs/heads/master: 0fc00e2440b717e19bab1ae0015f03936bdf7967
170 changes: 104 additions & 66 deletions trunk/drivers/char/tty_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,13 +730,23 @@ static int send_prio_char(struct tty_struct *tty, char ch)
return 0;
}

int n_tty_ioctl(struct tty_struct * tty, struct file * file,
unsigned int cmd, unsigned long arg)
/**
* tty_mode_ioctl - mode related ioctls
* @tty: tty for the ioctl
* @file: file pointer for the tty
* @cmd: command
* @arg: ioctl argument
*
* Perform non line discipline specific mode control ioctls. This
* is designed to be called by line disciplines to ensure they provide
* consistent mode setting.
*/

int tty_mode_ioctl(struct tty_struct * tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct tty_struct * real_tty;
void __user *p = (void __user *)arg;
int retval;
struct tty_ldisc *ld;

if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
Expand Down Expand Up @@ -799,6 +809,93 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
case TCSETA:
return set_termios(real_tty, p, TERMIOS_TERMIO);
#ifndef TCGETS2
case TIOCGLCKTRMIOS:
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT;
return 0;

case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
return -EFAULT;
return 0;
#else
case TIOCGLCKTRMIOS:
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT;
return 0;

case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
return -EFAULT;
return 0;
#endif
case TIOCGSOFTCAR:
return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
case TIOCSSOFTCAR:
if (get_user(arg, (unsigned int __user *) arg))
return -EFAULT;
mutex_lock(&tty->termios_mutex);
tty->termios->c_cflag =
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
mutex_unlock(&tty->termios_mutex);
return 0;
default:
return -ENOIOCTLCMD;
}
}

EXPORT_SYMBOL_GPL(tty_mode_ioctl);

int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
{
struct tty_ldisc *ld;
int retval = tty_check_change(tty);
if (retval)
return retval;

ld = tty_ldisc_ref(tty);
switch (arg) {
case TCIFLUSH:
if (ld && ld->flush_buffer)
ld->flush_buffer(tty);
break;
case TCIOFLUSH:
if (ld && ld->flush_buffer)
ld->flush_buffer(tty);
/* fall through */
case TCOFLUSH:
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
break;
default:
tty_ldisc_deref(ld);
return -EINVAL;
}
tty_ldisc_deref(ld);
return 0;
}

EXPORT_SYMBOL_GPL(tty_perform_flush);

int n_tty_ioctl(struct tty_struct * tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct tty_struct * real_tty;
int retval;

if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
real_tty = tty->link;
else
real_tty = tty;

switch (cmd) {
case TCXONC:
retval = tty_check_change(tty);
if (retval)
Expand Down Expand Up @@ -829,30 +926,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
}
return 0;
case TCFLSH:
retval = tty_check_change(tty);
if (retval)
return retval;

ld = tty_ldisc_ref(tty);
switch (arg) {
case TCIFLUSH:
if (ld && ld->flush_buffer)
ld->flush_buffer(tty);
break;
case TCIOFLUSH:
if (ld && ld->flush_buffer)
ld->flush_buffer(tty);
/* fall through */
case TCOFLUSH:
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
break;
default:
tty_ldisc_deref(ld);
return -EINVAL;
}
tty_ldisc_deref(ld);
return 0;
return tty_perform_flush(tty, arg);
case TIOCOUTQ:
return put_user(tty->driver->chars_in_buffer ?
tty->driver->chars_in_buffer(tty) : 0,
Expand All @@ -862,32 +936,6 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
if (L_ICANON(tty))
retval = inq_canon(tty);
return put_user(retval, (unsigned int __user *) arg);
#ifndef TCGETS2
case TIOCGLCKTRMIOS:
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT;
return 0;

case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
return -EFAULT;
return 0;
#else
case TIOCGLCKTRMIOS:
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT;
return 0;

case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
return -EFAULT;
return 0;
#endif

case TIOCPKT:
{
int pktmode;
Expand All @@ -906,19 +954,9 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
tty->packet = 0;
return 0;
}
case TIOCGSOFTCAR:
return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
case TIOCSSOFTCAR:
if (get_user(arg, (unsigned int __user *) arg))
return -EFAULT;
mutex_lock(&tty->termios_mutex);
tty->termios->c_cflag =
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
mutex_unlock(&tty->termios_mutex);
return 0;
default:
return -ENOIOCTLCMD;
/* Try the mode commands */
return tty_mode_ioctl(tty, file, cmd, arg);
}
}

Expand Down
4 changes: 3 additions & 1 deletion trunk/include/linux/tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,9 @@ extern void tty_ldisc_flush(struct tty_struct *tty);

extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg);

extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
extern dev_t tty_devnum(struct tty_struct *tty);
extern void proc_clear_tty(struct task_struct *p);
extern struct tty_struct *get_current_tty(void);
Expand Down

0 comments on commit 5ab14aa

Please sign in to comment.