>From f1c9b9a6d589dfdf85961fe3f8db4cdc9600dc4b Mon Sep 17 00:00:00 2001 From: Werner Fink Date: Wed, 27 Oct 2010 13:25:26 +0200 Subject: [PATCH] tty: Add a new file /proc/tty/consoles Add a new file /proc/tty/consoles to be able to determine the registered system console lines. If the reading process holds /dev/console open at the regular standard input stream the active device will be marked by an asterisk. Show possible operations and also decode the used flags of the of the listed console lines. Signed-off-by: Werner Fink diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 9fb6cbe..eeee8d9 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1074,6 +1074,7 @@ Table 1-11: Files in /proc/tty drivers list of drivers and their usage ldiscs registered line disciplines driver/serial usage statistic and status of single tty lines + consoles registered system console lines .............................................................................. To see which tty's are currently in use, you can simply look into the file @@ -1092,6 +1093,38 @@ To see which tty's are currently in use, you can simply look into the file /dev/tty /dev/tty 5 0 system:/dev/tty unknown /dev/tty 4 1-63 console +To see which character device lines are currently used for the system console +/dev/console, you may simply look into the file /proc/tty/consoles: + + > cat /proc/tty/consoles + tty0 -WU (ECp) 4:7 + ttyS0 -W- (Ep) 4:64 + +The columns are: + + device name of the device + operations R = can do read operations + W = can do write operations + U = can do unblank + flags E = it is enabled + C = it is prefered console + B = it is primary boot console + p = it is used for printk buffer + b = it is not a TTY but a Braille device + a = it is safe to use when cpu is offline + * = it is tty line of the reading process + + = it is controlling tty of the reading process + major:minor major and minor number of the device separated by a colon + +If the reading process holds /dev/console open at the regular standard input +stream the active device will be marked by an asterisk: + + > cat /proc/tty/consoles < /dev/console + tty0 -WU (ECp*) 4:7 + ttyS0 -W- (Ep) 4:64 + > tty + /dev/pts/3 + 1.8 Miscellaneous kernel statistics in /proc/stat ------------------------------------------------- diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index 83adcc8..5a6798c 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c @@ -12,7 +12,10 @@ #include #include #include +#include +#include #include +#include #include /* @@ -137,6 +140,170 @@ static const struct file_operations proc_tty_drivers_operations = { }; /* + * The device ID of file descriptor 0 of the current reading + * task if a character device... + */ +struct proc_tty_private { + dev_t tty_device; + unsigned int on_console:1; +}; + +/* + * This is the handler for /proc/tty/consoles + */ +static int show_console_dev(struct seq_file *m, void *v) +{ + struct console *con; + int index, len; + char flags[10]; + dev_t dev = 0; + + con = v; + if (!con) + return 0; + + if (con->device) { + const struct tty_driver *driver; + driver = con->device(con, &index); + if (driver) { + dev = MKDEV(driver->major, driver->minor_start); + dev += index; + } + } + + index = 0; + if (con->flags & CON_ENABLED) + flags[index++] = 'E'; + if (con->flags & CON_CONSDEV) + flags[index++] = 'C'; + if (con->flags & CON_BOOT) + flags[index++] = 'B'; + if (con->flags & CON_PRINTBUFFER) + flags[index++] = 'p'; + if (con->flags & CON_BRL) + flags[index++] = 'b'; + if (con->flags & CON_ANYTIME) + flags[index++] = 'a'; + if (m->private) { + const struct proc_tty_private *priv = m->private; + if (priv->on_console && (con->flags & CON_CONSDEV)) + flags[index++] = '*'; + if (dev && priv->tty_device == dev) + flags[index++] = '+'; + } + flags[index] = 0; + + seq_printf(m, "%s%d%n", con->name, con->index, &len); + len = 21 - len; + if (len < 1) + len = 1; + seq_printf(m, "%*c", len, ' '); + seq_printf(m, "%c%c%c (%s)%n", con->read ? 'R' : '-', + con->write ? 'W' : '-', con->unblank ? 'U' : '-', + flags, &len); + if (dev) { + len = 13 - len; + if (len < 1) + len = 1; + seq_printf(m, "%*c%4d:%d\n", len, ' ', MAJOR(dev), MINOR(dev)); + } + + return 0; +} + +/* + * Determine terminal device of standard input of current task. + */ +static void current_console_device(struct proc_tty_private *priv) +{ + struct files_struct *files = get_files_struct(current); + const struct file *filp; + unsigned long flags; + + if (!files) + return; + + spin_lock(&files->file_lock); + filp = fcheck_files(files, 0); + if (filp) { + const struct inode *inode; + dget(filp->f_dentry); + inode = filp->f_dentry->d_inode; + if (inode->i_rdev == MKDEV(TTYAUX_MAJOR, 1)) + priv->on_console = 1; + dput(filp->f_dentry); + } + spin_unlock(&files->file_lock); + put_files_struct(files); + + if (lock_task_sighand(current, &flags)) { + struct signal_struct *sig = current->signal; + if (sig->tty) + priv->tty_device = tty_devnum(sig->tty); + unlock_task_sighand(current, &flags); + } +} + +static void *c_start(struct seq_file *m, loff_t *pos) +{ + struct proc_tty_private *priv; + struct console *con; + loff_t off = 0; + + m->private = NULL; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (priv) { + current_console_device(priv); + m->private = priv; + } + + acquire_console_sem(); + for (con = console_drivers; con; con = con->next) { + if (off++ == *pos) + break; + } + return con; +} + +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct console *con = v; + con = con->next; + if (con) + ++*pos; + return con; +} + +static void c_stop(struct seq_file *m, void *v) +{ + release_console_sem(); + kfree(m->private); +} + +static const struct seq_operations tty_consoles_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_console_dev +}; + +/* iterator for consoles */ +/* + * Used for open /proc/tty/consoles. + */ +static int tty_consoles_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &tty_consoles_op); +} + +static const struct file_operations proc_tty_consoles_operations = { + .open = tty_consoles_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +/* * This function is called by tty_register_driver() to handle * registering the driver's /proc handler into /proc/tty/driver/ */ @@ -186,4 +353,5 @@ void __init proc_tty_init(void) proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL); proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops); proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations); + proc_create("tty/consoles", 0, NULL, &proc_tty_consoles_operations); } -- 1.6.0.2