aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorDr. Werner Fink <werner@suse.de>2010-09-22 06:45:40 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-22 13:20:05 -0400
commitf4a3e0bceb57466c31757f25e4e0ed108d1299ec (patch)
treec08eda0100e97ebd1fe4ab90b5d8eb142e505673 /fs/proc
parenta9e2e06015201c32c43d3615c9bf5e0d4efb4302 (diff)
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 listed console lines. Signed-off-by: Werner Fink <werner@suse.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/proc_tty.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index 83adcc869437..dc44f94022f1 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -12,7 +12,10 @@
12#include <linux/proc_fs.h> 12#include <linux/proc_fs.h>
13#include <linux/stat.h> 13#include <linux/stat.h>
14#include <linux/tty.h> 14#include <linux/tty.h>
15#include <linux/tty_driver.h>
16#include <linux/console.h>
15#include <linux/seq_file.h> 17#include <linux/seq_file.h>
18#include <linux/fdtable.h>
16#include <linux/bitops.h> 19#include <linux/bitops.h>
17 20
18/* 21/*
@@ -137,6 +140,160 @@ static const struct file_operations proc_tty_drivers_operations = {
137}; 140};
138 141
139/* 142/*
143 * The device ID of file descriptor 0 of the current reading
144 * task if a character device...
145 */
146static dev_t current_dev;
147
148/*
149 * This is the handler for /proc/tty/consoles
150 */
151static int show_console_dev(struct seq_file *m, void *v)
152{
153 const struct tty_driver *driver;
154 struct console *con;
155 int index, len;
156 char flags[10];
157 dev_t dev;
158
159 if (v == SEQ_START_TOKEN)
160 return 0;
161 con = (struct console *)v;
162 if (!con)
163 return 0;
164 driver = con->device(con, &index);
165 if (!driver)
166 return 0;
167 dev = MKDEV(driver->major, driver->minor_start) + index;
168
169 index = 0;
170 if (con->flags & CON_ENABLED)
171 flags[index++] = 'E';
172 if (con->flags & CON_CONSDEV)
173 flags[index++] = 'C';
174 if (con->flags & CON_BOOT)
175 flags[index++] = 'B';
176 if (con->flags & CON_PRINTBUFFER)
177 flags[index++] = 'p';
178 if (con->flags & CON_BRL)
179 flags[index++] = 'b';
180 if (con->flags & CON_ANYTIME)
181 flags[index++] = 'a';
182 if (current_dev == dev)
183 flags[index++] = '*';
184 flags[index] = 0;
185
186 seq_printf(m, "%s%d%n", con->name, con->index, &len);
187 len = 21 - len;
188 if (len < 1)
189 len = 1;
190 seq_printf(m, "%*c", len, ' ');
191 seq_printf(m, "%c%c%c (%s)%n", con->read ? 'R' : '-',
192 con->write ? 'W' : '-', con->unblank ? 'U' : '-',
193 flags, &len);
194 len = 13 - len;
195 if (len < 1)
196 len = 1;
197 seq_printf(m, "%*c%4d:%d\n", len, ' ', MAJOR(dev), MINOR(dev));
198
199 return 0;
200}
201
202/* iterator for consoles */
203static void *c_start(struct seq_file *m, loff_t *pos)
204{
205 struct console *con;
206 loff_t off = 0;
207
208 if (*pos == 0)
209 return SEQ_START_TOKEN;
210
211 acquire_console_sem();
212 for (con = console_drivers; con; con = con->next) {
213 if (!con->device)
214 continue;
215 if (++off == *pos)
216 break;
217 }
218 release_console_sem();
219
220 return con;
221}
222
223static void *c_next(struct seq_file *m, void *v, loff_t *pos)
224{
225 struct console *con;
226
227 acquire_console_sem();
228 if (v == SEQ_START_TOKEN)
229 con = console_drivers;
230 else
231 con = ((struct console *)v)->next;
232 for (; con; con = con->next) {
233 if (!con->device)
234 continue;
235 ++*pos;
236 break;
237 }
238 release_console_sem();
239
240 return con;
241}
242
243static void c_stop(struct seq_file *m, void *v)
244{
245}
246
247static const struct seq_operations tty_consoles_op = {
248 .start = c_start,
249 .next = c_next,
250 .stop = c_stop,
251 .show = show_console_dev
252};
253
254/*
255 * Used for open /proc/tty/consoles. Before this detect
256 * the device ID of file descriptor 0 of the current
257 * reading task if a character device...
258 */
259static int tty_consoles_open(struct inode *inode, struct file *file)
260{
261 struct files_struct *curfiles;
262
263 current_dev = 0;
264 curfiles = get_files_struct(current);
265 if (curfiles) {
266 const struct file *curfp;
267 spin_lock(&curfiles->file_lock);
268 curfp = fcheck_files(curfiles, 0);
269 if (curfp && curfp->private_data) {
270 const struct inode *inode;
271 dget(curfp->f_dentry);
272 inode = curfp->f_dentry->d_inode;
273 if (S_ISCHR(inode->i_mode)) {
274 struct tty_struct *tty;
275 tty = (struct tty_struct *)curfp->private_data;
276 if (tty && tty->magic == TTY_MAGIC) {
277 tty = tty_pair_get_tty(tty);
278 current_dev = tty_devnum(tty);
279 }
280 }
281 dput(curfp->f_dentry);
282 }
283 spin_unlock(&curfiles->file_lock);
284 put_files_struct(curfiles);
285 }
286 return seq_open(file, &tty_consoles_op);
287}
288
289static const struct file_operations proc_tty_consoles_operations = {
290 .open = tty_consoles_open,
291 .read = seq_read,
292 .llseek = seq_lseek,
293 .release = seq_release,
294};
295
296/*
140 * This function is called by tty_register_driver() to handle 297 * This function is called by tty_register_driver() to handle
141 * registering the driver's /proc handler into /proc/tty/driver/<foo> 298 * registering the driver's /proc handler into /proc/tty/driver/<foo>
142 */ 299 */
@@ -186,4 +343,5 @@ void __init proc_tty_init(void)
186 proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL); 343 proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);
187 proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops); 344 proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);
188 proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations); 345 proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations);
346 proc_create("tty/consoles", 0, NULL, &proc_tty_consoles_operations);
189} 347}