summaryrefslogtreecommitdiff
path: root/fs/proc
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2010-11-04 18:20:24 +0300
committerGreg Kroah-Hartman <gregkh@suse.de>2010-11-16 23:50:17 +0300
commit23308ba54dcdb54481163bfb07dd8aeca76a7a2e (patch)
tree3c96c14ee801188978dd2e2c3c84f9ed7535660e /fs/proc
parent281e66057757ddf32ffe679a08f9634fa9f70a7a (diff)
downloadlinux-23308ba54dcdb54481163bfb07dd8aeca76a7a2e.tar.xz
console: add /proc/consoles
It allows users to see what consoles are currently known to the system and with what flags. It is based on Werner's patch, the part about traversing fds was removed, the code was moved to kernel/printk.c, where consoles are handled and it makes more sense to me. Signed-off-by: Jiri Slaby <jslaby@suse.cz> [cleanups] Signed-off-by: "Dr. Werner Fink" <werner@suse.de> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/Makefile1
-rw-r--r--fs/proc/proc_console.c114
2 files changed, 115 insertions, 0 deletions
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 2758e2afc518..288a49e098bf 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -15,6 +15,7 @@ proc-y += devices.o
proc-y += interrupts.o
proc-y += loadavg.o
proc-y += meminfo.o
+proc-y += proc_console.o
proc-y += stat.o
proc-y += uptime.o
proc-y += version.o
diff --git a/fs/proc/proc_console.c b/fs/proc/proc_console.c
new file mode 100644
index 000000000000..8a707609f528
--- /dev/null
+++ b/fs/proc/proc_console.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2010 Werner Fink, Jiri Slaby
+ *
+ * Licensed under GPLv2
+ */
+
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/tty_driver.h>
+
+/*
+ * This is handler for /proc/consoles
+ */
+static int show_console_dev(struct seq_file *m, void *v)
+{
+ static const struct {
+ short flag;
+ char name;
+ } con_flags[] = {
+ { CON_ENABLED, 'E' },
+ { CON_CONSDEV, 'C' },
+ { CON_BOOT, 'B' },
+ { CON_PRINTBUFFER, 'p' },
+ { CON_BRL, 'b' },
+ { CON_ANYTIME, 'a' },
+ };
+ char flags[ARRAY_SIZE(con_flags) + 1];
+ struct console *con = v;
+ unsigned int a;
+ int len;
+ dev_t dev = 0;
+
+ if (con->device) {
+ const struct tty_driver *driver;
+ int index;
+ driver = con->device(con, &index);
+ if (driver) {
+ dev = MKDEV(driver->major, driver->minor_start);
+ dev += index;
+ }
+ }
+
+ for (a = 0; a < ARRAY_SIZE(con_flags); a++)
+ flags[a] = (con->flags & con_flags[a].flag) ?
+ con_flags[a].name : ' ';
+ flags[a] = 0;
+
+ seq_printf(m, "%s%d%n", con->name, con->index, &len);
+ len = 21 - len;
+ if (len < 1)
+ len = 1;
+ seq_printf(m, "%*c%c%c%c (%s)", len, ' ', con->read ? 'R' : '-',
+ con->write ? 'W' : '-', con->unblank ? 'U' : '-',
+ flags);
+ if (dev)
+ seq_printf(m, " %4d:%d", MAJOR(dev), MINOR(dev));
+
+ seq_printf(m, "\n");
+
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ struct console *con;
+ loff_t off = 0;
+
+ acquire_console_sem();
+ for_each_console(con)
+ if (off++ == *pos)
+ break;
+
+ return con;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ struct console *con = v;
+ ++*pos;
+ return con->next;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+ release_console_sem();
+}
+
+static const struct seq_operations consoles_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_console_dev
+};
+
+static int consoles_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &consoles_op);
+}
+
+static const struct file_operations proc_consoles_operations = {
+ .open = consoles_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int register_proc_consoles(void)
+{
+ proc_create("consoles", 0, NULL, &proc_consoles_operations);
+ return 0;
+}
+module_init(register_proc_consoles);