#include <linux/kmod.h>
-#define IS_CONSOLE_DEV(dev) (kdev_val(dev) == __mkdev(TTY_MAJOR,0))
-#define IS_TTY_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,0))
-#define IS_SYSCONS_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1))
-#define IS_PTMX_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,2))
-
#undef TTY_DEBUG_HANGUP
#define TTY_PARANOIA_CHECK 1
static ssize_t tty_read(struct file *, char *, size_t, loff_t *);
static ssize_t tty_write(struct file *, const char *, size_t, loff_t *);
+ssize_t redirected_tty_write(struct file *, const char *, size_t, loff_t *);
static unsigned int tty_poll(struct file *, poll_table *);
static int tty_open(struct inode *, struct file *);
static int tty_release(struct inode *, struct file *);
.fasync = tty_fasync,
};
+static struct file_operations console_fops = {
+ .llseek = no_llseek,
+ .read = tty_read,
+ .write = redirected_tty_write,
+ .poll = tty_poll,
+ .ioctl = tty_ioctl,
+ .open = tty_open,
+ .release = tty_release,
+ .fasync = tty_fasync,
+};
+
static struct file_operations hung_up_tty_fops = {
.llseek = no_llseek,
.read = hung_up_tty_read,
check_tty_count(tty, "do_tty_hangup");
file_list_lock();
list_for_each_entry(filp, &tty->tty_files, f_list) {
- if (IS_CONSOLE_DEV(filp->f_dentry->d_inode->i_rdev) ||
- IS_SYSCONS_DEV(filp->f_dentry->d_inode->i_rdev)) {
+ if (filp->f_op->write == redirected_tty_write)
cons_filp = filp;
- continue;
- }
- if (filp->f_op != &tty_fops)
+ if (filp->f_op->write != tty_write)
continue;
closecount++;
tty_fasync(-1, filp, 0); /* can't block */
if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
return -EIO;
- /* This check not only needs to be done before reading, but also
- whenever read_chan() gets woken up after sleeping, so I've
- moved it to there. This should only be done for the N_TTY
- line discipline, anyway. Same goes for write_chan(). -- jlc. */
-#if 0
- if (!IS_CONSOLE_DEV(inode->i_rdev) && /* don't stop on /dev/console */
- (tty->pgrp > 0) &&
- (current->tty == tty) &&
- (tty->pgrp != current->pgrp))
- if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
- return -EIO;
- else {
- (void) kill_pg(current->pgrp, SIGTTIN, 1);
- return -ERESTARTSYS;
- }
-#endif
lock_kernel();
if (tty->ldisc.read)
i = (tty->ldisc.read)(tty,file,buf,count);
static ssize_t tty_write(struct file * file, const char * buf, size_t count,
loff_t *ppos)
{
- int is_console;
struct tty_struct * tty;
struct inode *inode = file->f_dentry->d_inode;
- /*
- * For now, we redirect writes from /dev/console as
- * well as /dev/tty0.
- */
- is_console = IS_SYSCONS_DEV(inode->i_rdev) ||
- IS_CONSOLE_DEV(inode->i_rdev);
/* Can't seek (pwrite) on ttys. */
if (ppos != &file->f_pos)
return -ESPIPE;
- if (is_console) {
- struct file *p = NULL;
-
- spin_lock(&redirect_lock);
- if (redirect) {
- get_file(redirect);
- p = redirect;
- }
- spin_unlock(&redirect_lock);
-
- if (p) {
- ssize_t res = vfs_write(p, buf, count, &p->f_pos);
- fput(p);
- return res;
- }
- }
-
tty = (struct tty_struct *)file->private_data;
if (tty_paranoia_check(tty, inode, "tty_write"))
return -EIO;
(const unsigned char *)buf, count);
}
+ssize_t redirected_tty_write(struct file * file, const char * buf, size_t count,
+ loff_t *ppos)
+{
+ struct file *p = NULL;
+
+ spin_lock(&redirect_lock);
+ if (redirect) {
+ get_file(redirect);
+ p = redirect;
+ }
+ spin_unlock(&redirect_lock);
+
+ if (p) {
+ ssize_t res;
+ /* Can't seek (pwrite) on ttys. */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+ res = vfs_write(p, buf, count, &p->f_pos);
+ fput(p);
+ return res;
+ }
+
+ return tty_write(file, buf, count, ppos);
+}
+
/* Semaphore to protect creating and releasing a tty */
static DECLARE_MUTEX(tty_sem);
int noctty, retval;
struct tty_driver *driver;
int index;
- kdev_t device;
- unsigned short saved_flags;
-
- saved_flags = filp->f_flags;
+ dev_t device = kdev_t_to_nr(inode->i_rdev);
+ unsigned short saved_flags = filp->f_flags;
retry_open:
noctty = filp->f_flags & O_NOCTTY;
- device = inode->i_rdev;
- if (IS_TTY_DEV(device)) {
+ if (device == MKDEV(TTYAUX_MAJOR,0)) {
if (!current->tty)
return -ENXIO;
driver = current->tty->driver;
goto got_driver;
}
#ifdef CONFIG_VT
- if (IS_CONSOLE_DEV(device)) {
+ if (device == MKDEV(TTY_MAJOR,0)) {
extern int fg_console;
extern struct tty_driver *console_driver;
driver = console_driver;
goto got_driver;
}
#endif
- if (IS_SYSCONS_DEV(device)) {
+ if (device == MKDEV(TTYAUX_MAJOR,1)) {
struct console *c = console_drivers;
for (c = console_drivers; c; c = c->next) {
if (!c->device)
return -ENODEV;
}
- if (IS_PTMX_DEV(device)) {
+ if (device == MKDEV(TTYAUX_MAJOR,2)) {
#ifdef CONFIG_UNIX98_PTYS
/* find a device that is not in use. */
retval = -1;
return -ENODEV;
#endif /* CONFIG_UNIX_98_PTYS */
} else {
- driver = get_tty_driver(kdev_t_to_nr(device), &index);
+ driver = get_tty_driver(device, &index);
if (!driver)
return -ENODEV;
got_driver:
/*
* Need to reset f_op in case a hangup happened.
*/
- filp->f_op = &tty_fops;
+ if (filp->f_op == &hung_up_tty_fops)
+ filp->f_op = &tty_fops;
goto retry_open;
}
if (!noctty &&
return 0;
}
-static int tioccons(struct inode *inode, struct file *file)
+static int tioccons(struct file *file)
{
- if (IS_SYSCONS_DEV(inode->i_rdev) ||
- IS_CONSOLE_DEV(inode->i_rdev)) {
+ if (file->f_op->write == redirected_tty_write) {
struct file *f;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
case TIOCSWINSZ:
return tiocswinsz(tty, real_tty, (struct winsize *) arg);
case TIOCCONS:
- return real_tty!=tty ? -EINVAL : tioccons(inode, file);
+ return real_tty!=tty ? -EINVAL : tioccons(file);
case FIONBIO:
return fionbio(file, (int *) arg);
case TIOCEXCL:
spin_lock(&p->files->file_lock);
for (i=0; i < p->files->max_fds; i++) {
filp = fcheck_files(p->files, i);
- if (filp && (filp->f_op == &tty_fops) &&
- (filp->private_data == tty)) {
+ if (!filp)
+ continue;
+ if (filp->f_op->read == tty_read &&
+ filp->private_data == tty) {
printk(KERN_NOTICE "SAK: killed process %d"
" (%s): fd#%d opened to the tty\n",
p->pid, p->comm, i);
tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL);
strcpy(console_cdev.kobj.name, "dev.console");
- cdev_init(&console_cdev, &tty_fops);
+ cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
#ifdef CONFIG_VT
strcpy(vc0_cdev.kobj.name, "dev.vc0");
- cdev_init(&vc0_cdev, &tty_fops);
+ cdev_init(&vc0_cdev, &console_fops);
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");