1 // SPDX-License-Identifier: GPL-2.0
3 * proc_tty.c -- handles /proc/tty
5 * Copyright 1997, Theodore Ts'o
8 #include <linux/uaccess.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/errno.h>
12 #include <linux/time.h>
13 #include <linux/proc_fs.h>
14 #include <linux/stat.h>
15 #include <linux/tty.h>
16 #include <linux/seq_file.h>
17 #include <linux/bitops.h>
21 * The /proc/tty directory inodes...
23 static struct proc_dir_entry
*proc_tty_driver
;
26 * This is the handler for /proc/tty/drivers
28 static void show_tty_range(struct seq_file
*m
, struct tty_driver
*p
,
31 seq_printf(m
, "%-20s ", p
->driver_name
? p
->driver_name
: "unknown");
32 seq_printf(m
, "/dev/%-8s ", p
->name
);
34 seq_printf(m
, "%3d %d-%d ", MAJOR(from
), MINOR(from
),
35 MINOR(from
) + num
- 1);
37 seq_printf(m
, "%3d %7d ", MAJOR(from
), MINOR(from
));
40 case TTY_DRIVER_TYPE_SYSTEM
:
41 seq_puts(m
, "system");
42 if (p
->subtype
== SYSTEM_TYPE_TTY
)
43 seq_puts(m
, ":/dev/tty");
44 else if (p
->subtype
== SYSTEM_TYPE_SYSCONS
)
45 seq_puts(m
, ":console");
46 else if (p
->subtype
== SYSTEM_TYPE_CONSOLE
)
47 seq_puts(m
, ":vtmaster");
49 case TTY_DRIVER_TYPE_CONSOLE
:
50 seq_puts(m
, "console");
52 case TTY_DRIVER_TYPE_SERIAL
:
53 seq_puts(m
, "serial");
55 case TTY_DRIVER_TYPE_PTY
:
56 if (p
->subtype
== PTY_TYPE_MASTER
)
57 seq_puts(m
, "pty:master");
58 else if (p
->subtype
== PTY_TYPE_SLAVE
)
59 seq_puts(m
, "pty:slave");
64 seq_printf(m
, "type:%d.%d", p
->type
, p
->subtype
);
69 static int show_tty_driver(struct seq_file
*m
, void *v
)
71 struct tty_driver
*p
= list_entry(v
, struct tty_driver
, tty_drivers
);
72 dev_t from
= MKDEV(p
->major
, p
->minor_start
);
73 dev_t to
= from
+ p
->num
;
75 if (&p
->tty_drivers
== tty_drivers
.next
) {
76 /* pseudo-drivers first */
77 seq_printf(m
, "%-20s /dev/%-8s ", "/dev/tty", "tty");
78 seq_printf(m
, "%3d %7d ", TTYAUX_MAJOR
, 0);
79 seq_puts(m
, "system:/dev/tty\n");
80 seq_printf(m
, "%-20s /dev/%-8s ", "/dev/console", "console");
81 seq_printf(m
, "%3d %7d ", TTYAUX_MAJOR
, 1);
82 seq_puts(m
, "system:console\n");
83 #ifdef CONFIG_UNIX98_PTYS
84 seq_printf(m
, "%-20s /dev/%-8s ", "/dev/ptmx", "ptmx");
85 seq_printf(m
, "%3d %7d ", TTYAUX_MAJOR
, 2);
86 seq_puts(m
, "system\n");
89 seq_printf(m
, "%-20s /dev/%-8s ", "/dev/vc/0", "vc/0");
90 seq_printf(m
, "%3d %7d ", TTY_MAJOR
, 0);
91 seq_puts(m
, "system:vtmaster\n");
95 while (MAJOR(from
) < MAJOR(to
)) {
96 dev_t next
= MKDEV(MAJOR(from
)+1, 0);
97 show_tty_range(m
, p
, from
, next
- from
);
101 show_tty_range(m
, p
, from
, to
- from
);
106 static void *t_start(struct seq_file
*m
, loff_t
*pos
)
108 mutex_lock(&tty_mutex
);
109 return seq_list_start(&tty_drivers
, *pos
);
112 static void *t_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
114 return seq_list_next(v
, &tty_drivers
, pos
);
117 static void t_stop(struct seq_file
*m
, void *v
)
119 mutex_unlock(&tty_mutex
);
122 static const struct seq_operations tty_drivers_op
= {
126 .show
= show_tty_driver
130 * This function is called by tty_register_driver() to handle
131 * registering the driver's /proc handler into /proc/tty/driver/<foo>
133 void proc_tty_register_driver(struct tty_driver
*driver
)
135 struct proc_dir_entry
*ent
;
137 if (!driver
->driver_name
|| driver
->proc_entry
||
138 !driver
->ops
->proc_show
)
141 ent
= proc_create_single_data(driver
->driver_name
, 0, proc_tty_driver
,
142 driver
->ops
->proc_show
, driver
);
143 driver
->proc_entry
= ent
;
147 * This function is called by tty_unregister_driver()
149 void proc_tty_unregister_driver(struct tty_driver
*driver
)
151 struct proc_dir_entry
*ent
;
153 ent
= driver
->proc_entry
;
157 remove_proc_entry(ent
->name
, proc_tty_driver
);
159 driver
->proc_entry
= NULL
;
163 * Called by proc_root_init() to initialize the /proc/tty subtree
165 void __init
proc_tty_init(void)
167 if (!proc_mkdir("tty", NULL
))
169 proc_mkdir("tty/ldisc", NULL
); /* Preserved: it's userspace visible */
171 * /proc/tty/driver/serial reveals the exact character counts for
172 * serial links which is just too easy to abuse for inferring
173 * password lengths and inter-keystroke timings during password
176 proc_tty_driver
= proc_mkdir_mode("tty/driver", S_IRUSR
|S_IXUSR
, NULL
);
177 proc_create_seq("tty/ldiscs", 0, NULL
, &tty_ldiscs_seq_ops
);
178 proc_create_seq("tty/drivers", 0, NULL
, &tty_drivers_op
);