source "drivers/serial/Kconfig"
config UNIX98_PTYS
- bool "Unix98 PTY support"
+ bool "Unix98 PTY support" if EMBEDDED
+ default y
---help---
A pseudo terminal (PTY) is a software device consisting of two
halves: a master and a slave. The slave device behaves identical to
terminal slave can be accessed as /dev/pts/<number>. What was
traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
- The entries in /dev/pts/ are created on the fly by a virtual
- file system; therefore, if you say Y here you should say Y to
- "/dev/pts file system for Unix98 PTYs" as well.
+ All modern Linux systems use the Unix98 ptys. Say Y unless
+ you're on an embedded system and want to conserve memory.
- If you want to say Y here, you need to have the C library glibc 2.1
- or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*").
- Read the instructions in <file:Documentation/Changes> pertaining to
- pseudo terminals. It's safe to say N.
+config LEGACY_PTYS
+ bool "Legacy (BSD) PTY support"
+ default y
+ ---help---
+ A pseudo terminal (PTY) is a software device consisting of two
+ halves: a master and a slave. The slave device behaves identical to
+ a physical terminal; the master device is used by a process to
+ read data from and write data to the slave, thereby emulating a
+ terminal. Typical programs for the master side are telnet servers
+ and xterms.
+
+ Linux has traditionally used the BSD-like names /dev/ptyxx
+ for masters and /dev/ttyxx for slaves of pseudo
+ terminals. This scheme has a number of problems, including
+ security. This option enables these legacy devices; on most
+ systems, it is safe to say N.
-config UNIX98_PTY_COUNT
- int "Maximum number of Unix98 PTYs in use (0-2048)"
- depends on UNIX98_PTYS
+
+config LEGACY_PTY_COUNT
+ int "Maximum number of legacy PTY in use"
+ depends on LEGACY_PTYS
default "256"
- help
- The maximum number of Unix98 PTYs that can be used at any one time.
- The default is 256, and should be enough for desktop systems. Server
- machines which support incoming telnet/rlogin/ssh connections and/or
- serve several X terminals may want to increase this: every incoming
- connection and every xterm uses up one PTY.
+ ---help---
+ The maximum number of legacy PTYs that can be used at any one time.
+ The default is 256, and should be more than enough. Embedded
+ systems may want to reduce this to save memory.
- When not in use, each additional set of 256 PTYs occupy
- approximately 8 KB of kernel memory on 32-bit architectures.
+ When not in use, each legacy PTY occupies 12 bytes on 32-bit
+ architectures and 24 bytes on 64-bit architectures.
config PRINTER
tristate "Parallel printer support"
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/sysctl.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <linux/devpts_fs.h>
+#if defined(CONFIG_LEGACY_PTYS) || defined(CONFIG_UNIX98_PTYS)
+
+#ifdef CONFIG_LEGACY_PTYS
static struct tty_driver *pty_driver, *pty_slave_driver;
+#endif
-#ifdef CONFIG_UNIX98_PTYS
/* These are global because they are accessed in tty_io.c */
+#ifdef CONFIG_UNIX98_PTYS
struct tty_driver *ptm_driver;
struct tty_driver *pts_driver;
#endif
return 0;
}
+#ifdef CONFIG_LEGACY_PTYS
static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
if (!tty) {
printk("pty_ioctl called with NULL tty!\n");
}
return -ENOIOCTLCMD;
}
+#endif
#ifdef CONFIG_UNIX98_PTYS
static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
return -EIO;
}
switch(cmd) {
+ case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
+ return pty_set_lock(tty, (int *)arg);
case TIOCGPTN: /* Get PT Number */
return pty_get_device_number(tty, (unsigned int *)arg);
}
- return pty_bsd_ioctl(tty,file,cmd,arg);
+ return -ENOIOCTLCMD;
}
#endif
.set_termios = pty_set_termios,
};
+/* sysctl support for setting limits on the number of Unix98 ptys allocated.
+ Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. */
+#ifdef CONFIG_UNIX98_PTYS
+int pty_limit = NR_UNIX98_PTY_DEFAULT;
+static int pty_limit_min = 0;
+static int pty_limit_max = NR_UNIX98_PTY_MAX;
+
+ctl_table pty_table[] = {
+ {
+ .ctl_name = PTY_MAX,
+ .procname = "max",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .data = &pty_limit,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &pty_limit_min,
+ .extra2 = &pty_limit_max,
+ }, {
+ .ctl_name = PTY_NR,
+ .procname = "nr",
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ }, {
+ .ctl_name = 0
+ }
+};
+#endif
+
+/* Initialization */
+
static int __init pty_init(void)
{
+#ifdef CONFIG_LEGACY_PTYS
/* Traditional BSD devices */
pty_driver = alloc_tty_driver(NR_PTYS);
if (tty_register_driver(pty_slave_driver))
panic("Couldn't register pty slave driver");
+#endif /* CONFIG_LEGACY_PTYS */
- /* Unix98 devices */
#ifdef CONFIG_UNIX98_PTYS
+ /* Unix98 devices */
devfs_mk_dir("pts");
- printk("pty: %d Unix98 ptys configured\n", UNIX98_NR_MAJORS*NR_PTYS);
- ptm_driver = alloc_tty_driver(UNIX98_NR_MAJORS * NR_PTYS);
+ ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
if (!ptm_driver)
panic("Couldn't allocate Unix98 ptm driver");
- pts_driver = alloc_tty_driver(UNIX98_NR_MAJORS * NR_PTYS);
+ pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
if (!pts_driver)
panic("Couldn't allocate Unix98 pts driver");
ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
ptm_driver->init_termios.c_lflag = 0;
ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_NO_DEVFS;
+ TTY_DRIVER_NO_DEVFS | TTY_DRIVER_DEVPTS_MEM;
ptm_driver->other = pts_driver;
tty_set_operations(ptm_driver, &pty_ops);
ptm_driver->ioctl = pty_unix98_ioctl;
pts_driver->subtype = PTY_TYPE_SLAVE;
pts_driver->init_termios = tty_std_termios;
pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
- pts_driver->flags = TTY_DRIVER_RESET_TERMIOS |
- TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+ pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_NO_DEVFS | TTY_DRIVER_DEVPTS_MEM;
pts_driver->other = ptm_driver;
tty_set_operations(pts_driver, &pty_ops);
panic("Couldn't register Unix98 ptm driver");
if (tty_register_driver(pts_driver))
panic("Couldn't register Unix98 pts driver");
-#endif
+
+ pty_table[1].data = &ptm_driver->refcount;
+#endif /* CONFIG_UNIX98_PTYS */
+
return 0;
}
module_init(pty_init);
+
+#endif /* CONFIG_LEGACY_PTYS || CONFIG_UNIX98_PTYS */
#ifdef CONFIG_UNIX98_PTYS
extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */
-extern struct tty_driver *pts_driver; /* Unix98 pty slaves; for /dev/ptmx */
+extern int pty_limit; /* Config limit on Unix98 ptys */
#endif
extern void disable_early_printk(void);
down_tty_sem(idx);
/* check whether we're reopening an existing tty */
- tty = driver->ttys[idx];
+ if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
+ tty = devpts_get_tty(idx);
+ if (tty && driver->subtype == PTY_TYPE_MASTER)
+ tty = tty->link;
+ } else {
+ tty = driver->ttys[idx];
+ }
if (tty) goto fast_track;
/*
tty->index = idx;
tty_line_name(driver, idx, tty->name);
- tp_loc = &driver->termios[idx];
+ if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
+ tp_loc = &tty->termios;
+ ltp_loc = &tty->termios_locked;
+ } else {
+ tp_loc = &driver->termios[idx];
+ ltp_loc = &driver->termios_locked[idx];
+ }
+
if (!*tp_loc) {
tp = (struct termios *) kmalloc(sizeof(struct termios),
GFP_KERNEL);
*tp = driver->init_termios;
}
- ltp_loc = &driver->termios_locked[idx];
if (!*ltp_loc) {
ltp = (struct termios *) kmalloc(sizeof(struct termios),
GFP_KERNEL);
o_tty->index = idx;
tty_line_name(driver->other, idx, o_tty->name);
- o_tp_loc = &driver->other->termios[idx];
+ if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
+ o_tp_loc = &o_tty->termios;
+ o_ltp_loc = &o_tty->termios_locked;
+ } else {
+ o_tp_loc = &driver->other->termios[idx];
+ o_ltp_loc = &driver->other->termios_locked[idx];
+ }
+
if (!*o_tp_loc) {
o_tp = (struct termios *)
kmalloc(sizeof(struct termios), GFP_KERNEL);
*o_tp = driver->other->init_termios;
}
- o_ltp_loc = &driver->other->termios_locked[idx];
if (!*o_ltp_loc) {
o_ltp = (struct termios *)
kmalloc(sizeof(struct termios), GFP_KERNEL);
/*
* Everything allocated ... set up the o_tty structure.
*/
- driver->other->ttys[idx] = o_tty;
+ if (!(driver->other->flags & TTY_DRIVER_DEVPTS_MEM)) {
+ driver->other->ttys[idx] = o_tty;
+ }
if (!*o_tp_loc)
*o_tp_loc = o_tp;
if (!*o_ltp_loc)
* Failures after this point use release_mem to clean up, so
* there's no need to null out the local pointers.
*/
- driver->ttys[idx] = tty;
+ if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
+ driver->ttys[idx] = tty;
+ }
if (!*tp_loc)
*tp_loc = tp;
{
struct tty_struct *o_tty;
struct termios *tp;
+ int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
if ((o_tty = tty->link) != NULL) {
- o_tty->driver->ttys[idx] = NULL;
+ if (!devpts)
+ o_tty->driver->ttys[idx] = NULL;
if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- tp = o_tty->driver->termios[idx];
- o_tty->driver->termios[idx] = NULL;
+ tp = o_tty->termios;
+ if (!devpts)
+ o_tty->driver->termios[idx] = NULL;
+ kfree(tp);
+
+ tp = o_tty->termios_locked;
+ if (!devpts)
+ o_tty->driver->termios_locked[idx] = NULL;
kfree(tp);
}
o_tty->magic = 0;
free_tty_struct(o_tty);
}
- tty->driver->ttys[idx] = NULL;
+ if (!devpts)
+ tty->driver->ttys[idx] = NULL;
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- tp = tty->driver->termios[idx];
- tty->driver->termios[idx] = NULL;
+ tp = tty->termios;
+ if (!devpts)
+ tty->driver->termios[idx] = NULL;
+ kfree(tp);
+
+ tp = tty->termios_locked;
+ if (!devpts)
+ tty->driver->termios_locked[idx] = NULL;
kfree(tp);
}
+
tty->magic = 0;
tty->driver->refcount--;
file_list_lock();
"free (%s)\n", tty->name);
return;
}
- if (tty != tty->driver->ttys[idx]) {
- printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
- "for (%s)\n", idx, tty->name);
- return;
- }
- if (tty->termios != tty->driver->termios[idx]) {
- printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios "
- "for (%s)\n",
- idx, tty->name);
- return;
- }
- if (tty->termios_locked != tty->driver->termios_locked[idx]) {
- printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not "
- "termios_locked for (%s)\n",
- idx, tty->name);
- return;
+ if (!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
+ if (tty != tty->driver->ttys[idx]) {
+ printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
+ "for (%s)\n", idx, tty->name);
+ return;
+ }
+ if (tty->termios != tty->driver->termios[idx]) {
+ printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios "
+ "for (%s)\n",
+ idx, tty->name);
+ return;
+ }
+ if (tty->termios_locked != tty->driver->termios_locked[idx]) {
+ printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not "
+ "termios_locked for (%s)\n",
+ idx, tty->name);
+ return;
+ }
}
#endif
#endif
#ifdef TTY_PARANOIA_CHECK
- if (tty->driver->other) {
+ if (tty->driver->other &&
+ !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
if (o_tty != tty->driver->other->ttys[idx]) {
printk(KERN_DEBUG "release_dev: other->table[%d] "
"not o_tty for (%s)\n",
return -ENODEV;
}
- if (device == MKDEV(TTYAUX_MAJOR,2)) {
#ifdef CONFIG_UNIX98_PTYS
+ if (device == MKDEV(TTYAUX_MAJOR,2)) {
/* find a device that is not in use. */
+ static int next_ptmx_dev = 0;
retval = -1;
driver = ptm_driver;
- for (index = 0; index < driver->num ; index++)
+ while (driver->refcount < pty_limit) {
+ index = next_ptmx_dev;
+ next_ptmx_dev = (next_ptmx_dev+1) % driver->num;
if (!init_dev(driver, index, &tty))
goto ptmx_found; /* ok! */
+ }
return -EIO; /* no free ptys */
ptmx_found:
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
- devpts_pty_new(index, MKDEV(pts_driver->major, pts_driver->minor_start) + index);
+ if (devpts_pty_new(tty->link)) {
+ /* BADNESS - need to destroy both ptm and pts! */
+ return -ENOMEM;
+ }
noctty = 1;
-#else
- return -ENODEV;
-#endif /* CONFIG_UNIX_98_PTYS */
- } else {
+ } else
+#endif
+ {
driver = get_tty_driver(device, &index);
if (!driver)
return -ENODEV;
int i;
dev_t dev;
char *s;
- void **p;
+ void **p = NULL;
if (driver->flags & TTY_DRIVER_INSTALLED)
return 0;
- p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
- memset(p, 0, driver->num * 3 * sizeof(void *));
+ if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
+ p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+ memset(p, 0, driver->num * 3 * sizeof(void *));
+ }
if (!driver->major) {
error = alloc_chrdev_region(&dev, driver->minor_start, driver->num,
return error;
}
- driver->ttys = (struct tty_struct **)p;
- driver->termios = (struct termios **)(p + driver->num);
- driver->termios_locked = (struct termios **)(p + driver->num * 2);
+ if (p) {
+ driver->ttys = (struct tty_struct **)p;
+ driver->termios = (struct termios **)(p + driver->num);
+ driver->termios_locked = (struct termios **)(p + driver->num * 2);
+ } else {
+ driver->ttys = NULL;
+ driver->termios = NULL;
+ driver->termios_locked = NULL;
+ }
driver->cdev.kobj.parent = &tty_kobj;
strcpy(driver->cdev.kobj.name, driver->name);
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif
-
+
#ifdef CONFIG_VT
strcpy(vc0_cdev.kobj.name, "dev.vc0");
cdev_init(&vc0_cdev, &console_fops);
the file README there.
Note that devfs no longer manages /dev/pts! If you are using UNIX98
- ptys, you will also need to enable (and mount) the /dev/pts
- filesystem (CONFIG_DEVPTS_FS).
+ ptys, you will also need to mount the /dev/pts filesystem (devpts).
Note that devfs has been obsoleted by udev,
<http://www.kernel.org/pub/linux/utils/kernel/hotplug/>.
If unsure, say N.
-config DEVPTS_FS
-# It compiles as a module for testing only. It should not be used
-# as a module in general. If we make this "tristate", a bunch of people
-# who don't know what they are doing turn it on and complain when it
-# breaks.
- bool "/dev/pts file system for Unix98 PTYs"
- depends on UNIX98_PTYS
- ---help---
- You should say Y here if you said Y to "Unix98 PTY support" above.
- You'll then get a virtual file system which can be mounted on
- /dev/pts with "mount -t devpts". This, together with the pseudo
- terminal master multiplexer /dev/ptmx, is used for pseudo terminal
- support as described in The Open Group's Unix98 standard: in order
- to acquire a pseudo terminal, a process opens /dev/ptmx; the number
- of the pseudo terminal is then made available to the process and the
- pseudo terminal slave can be accessed as /dev/pts/<number>. What was
- traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
- The GNU C library glibc 2.1 contains the requisite support for this
- mode of operation; you also need client programs that use the Unix98
- API. Please read <file:Documentation/Changes> for more information
- about the Unix98 pty devices.
-
config DEVPTS_FS_XATTR
bool "/dev/pts Extended Attributes"
- depends on DEVPTS_FS
+ depends on UNIX98_PTYS
help
Extended attributes are name:value pairs associated with inodes by
the kernel or by users (see the attr(5) manual page, or visit
# Makefile for the Linux /dev/pts virtual filesystem.
#
-obj-$(CONFIG_DEVPTS_FS) += devpts.o
+obj-$(CONFIG_UNIX98_PTYS) += devpts.o
-devpts-y := inode.o
+devpts-$(CONFIG_UNIX98_PTYS) := inode.o
devpts-$(CONFIG_DEVPTS_FS_XATTR) += xattr.o
devpts-$(CONFIG_DEVPTS_FS_SECURITY) += xattr_security.o
*
* linux/fs/devpts/inode.c
*
- * Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ * Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
#include <linux/sched.h>
#include <linux/namei.h>
#include <linux/mount.h>
+#include <linux/tty.h>
+#include <linux/devpts_fs.h>
#include "xattr.h"
#define DEVPTS_SUPER_MAGIC 0x1cd1
static struct dentry *get_node(int num)
{
- char s[10];
+ char s[12];
struct dentry *root = devpts_root;
down(&root->d_inode->i_sem);
return lookup_one_len(s, root, sprintf(s, "%d", num));
.removexattr = devpts_removexattr,
};
-void devpts_pty_new(int number, dev_t device)
+int devpts_pty_new(struct tty_struct *tty)
{
+ int number = tty->index;
+ struct tty_driver *driver = tty->driver;
+ dev_t device = MKDEV(driver->major, driver->minor_start+number);
struct dentry *dentry;
struct inode *inode = new_inode(devpts_mnt->mnt_sb);
+
+ /* We're supposed to be given the slave end of a pty */
+ BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY);
+ BUG_ON(driver->subtype != PTY_TYPE_SLAVE);
+
if (!inode)
- return;
+ return -ENOMEM;
+
inode->i_ino = number+2;
inode->i_blksize = 1024;
inode->i_uid = config.setuid ? config.uid : current->fsuid;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
init_special_inode(inode, S_IFCHR|config.mode, device);
inode->i_op = &devpts_file_inode_operations;
+ inode->u.generic_ip = tty;
dentry = get_node(number);
if (!IS_ERR(dentry) && !dentry->d_inode)
d_instantiate(dentry, inode);
+
+ up(&devpts_root->d_inode->i_sem);
+
+ return 0;
+}
+
+struct tty_struct *devpts_get_tty(int number)
+{
+ struct dentry *dentry = get_node(number);
+ struct tty_struct *tty;
+
+ tty = (IS_ERR(dentry) || !dentry->d_inode) ? NULL :
+ dentry->d_inode->u.generic_ip;
+
up(&devpts_root->d_inode->i_sem);
+
+ return tty;
}
void devpts_pty_kill(int number)
*
* linux/include/linux/devpts_fs.h
*
- * Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ * Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
#ifndef _LINUX_DEVPTS_FS_H
#define _LINUX_DEVPTS_FS_H 1
-#ifdef CONFIG_DEVPTS_FS
+#include <linux/errno.h>
-void devpts_pty_new(int, dev_t); /* mknod in devpts */
-void devpts_pty_kill(int); /* unlink */
+#if CONFIG_UNIX98_PTYS
-#else
+int devpts_pty_new(struct tty_struct *); /* mknod in devpts */
+struct tty_struct *devpts_get_tty(int); /* get tty structure */
+void devpts_pty_kill(int); /* unlink */
-static inline void devpts_pty_new(int line, dev_t device)
-{
-}
+#else
-static inline void devpts_pty_kill(int line)
-{
-}
+/* Dummy stubs in the no-pty case */
+static inline int devpts_pty_new(struct tty_struct *) { return -EINVAL; }
+static inline struct tty_struct *devpts_get_tty(int) { return NULL; }
+static inline void devpts_pty_kill(int) { }
#endif
+
#endif /* _LINUX_DEVPTS_FS_H */
KERN_HPPA_UNALIGNED=59, /* int: hppa unaligned-trap enable */
KERN_PRINTK_RATELIMIT=60, /* int: tune printk ratelimiting */
KERN_PRINTK_RATELIMIT_BURST=61, /* int: tune printk ratelimiting */
+ KERN_PTY=62, /* dir: pty driver */
};
RANDOM_UUID=6
};
+/* /proc/sys/kernel/pty */
+enum
+{
+ PTY_MAX=1,
+ PTY_NR=2
+};
+
/* /proc/sys/bus/isa */
enum
{
/*
- * Note: don't mess with NR_PTYS until you understand the tty minor
- * number allocation game...
* (Note: the *_driver.minor_start values 1, 64, 128, 192 are
* hardcoded at present.)
*/
-#define NR_PTYS 256 /* ptys/major */
-#define NR_LDISCS 16
-
-/*
- * Unix98 PTY's can be defined as any multiple of NR_PTYS up to
- * UNIX98_PTY_MAJOR_COUNT; this section defines what we need from the
- * config options
- */
-#ifdef CONFIG_UNIX98_PTYS
-# define UNIX98_NR_MAJORS ((CONFIG_UNIX98_PTY_COUNT+NR_PTYS-1)/NR_PTYS)
-# if UNIX98_NR_MAJORS <= 0
-# undef CONFIG_UNIX98_PTYS
-# elif UNIX98_NR_MAJORS > UNIX98_PTY_MAJOR_COUNT
-# error Too many Unix98 ptys defined
-# undef UNIX98_NR_MAJORS
-# define UNIX98_NR_MAJORS UNIX98_PTY_MAJOR_COUNT
-# endif
-#endif
+#define NR_PTYS CONFIG_LEGACY_PTY_COUNT /* Number of legacy ptys */
+#define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */
+#define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */
+#define NR_LDISCS 16
/*
* These are set up by the setup-routine at boot-time:
const char *devfs_name;
const char *name;
int name_base; /* offset of printed name */
- short major; /* major device number */
- short minor_start; /* start of minor device number*/
- short num; /* number of devices */
+ int major; /* major device number */
+ int minor_start; /* start of minor device number */
+ int minor_num; /* number of *possible* devices */
+ int num; /* number of devices allocated */
short type; /* type of tty driver */
short subtype; /* subtype of tty driver */
struct termios init_termios; /* Initial termios */
* TTY_DRIVER_NO_DEVFS --- if set, do not create devfs entries. This
* is only used by tty_register_driver().
*
+ * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead
+ * use dynamic memory keyed through the devpts filesystem. This
+ * is only applicable to the pty driver.
*/
#define TTY_DRIVER_INSTALLED 0x0001
#define TTY_DRIVER_RESET_TERMIOS 0x0002
#define TTY_DRIVER_REAL_RAW 0x0004
#define TTY_DRIVER_NO_DEVFS 0x0008
+#define TTY_DRIVER_DEVPTS_MEM 0x0010
/* tty driver types */
#define TTY_DRIVER_TYPE_SYSTEM 0x0001
static ctl_table debug_table[];
static ctl_table dev_table[];
extern ctl_table random_table[];
+#ifdef CONFIG_UNIX98_PTYS
+extern ctl_table pty_table[];
+#endif
/* /proc declarations: */
.mode = 0555,
.child = random_table,
},
+#ifdef CONFIG_UNIX98_PTYS
+ {
+ .ctl_name = KERN_PTY,
+ .procname = "pty",
+ .mode = 0555,
+ .child = pty_table,
+ },
+#endif
{
.ctl_name = KERN_OVERFLOWUID,
.procname = "overflowuid",