PATCH: Unix98 pty support.

C. Scott Ananian (cananian@lcs.mit.edu)
Wed, 21 Jan 1998 00:12:09 -0500 (EST)


Attached is the latest version of my pty patch for linux kernel
2.1.{78,79,80}. Only changes from previous versions are in comments and
the symbolic name of the new ioctl, which has been changed from
TIOCPTSNAME to the more-standard TIOCGPTN.

No additional functionality is needed to implement Unix98 ptys in
the linux kernel. Work is progressing on integrating this support into
glibc. The device number {5,2} has been allocated by the linux device
list maintainer for /dev/ptmx.
--Scott
@ @
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-oOO-(_)-OOo-=-=-=-=-=
C. Scott Ananian: cananian@lcs.mit.edu / Declare the Truth boldly and
Laboratory for Computer Science/Crypto / without hindrance.
Massachusetts Institute of Technology /META-PARRESIAS AKOLUTOS:Acts 28:31
-.-. .-.. .. ..-. ..-. --- .-. -.. ... -.-. --- - - .- -. .- -. .. .- -.
PGP key available via finger and from http://www.pdos.lcs.mit.edu/~cananian

diff -ruHpN -X badboys linux-2.1.78-orig/CREDITS linux/CREDITS
--- linux-2.1.78-orig/CREDITS Wed Jan 14 00:02:50 1998
+++ linux/CREDITS Tue Jan 13 21:22:49 1998
@@ -33,6 +33,15 @@ S: Klaproosstraat 72 c 10
S: B-2610 Wilrijk-Antwerpen
S: Belgium

+N: C. Scott Ananian
+E: cananian@alumni.princeton.edu
+W: http://www.pdos.lcs.mit.edu/~cananian
+P: 1024/85AD9EED AD C0 49 08 91 67 DF D7 FA 04 1A EE 09 E8 44 B0
+D: pty improvements.
+S: 322 N. Riverside Dr.
+S: Neptune, NJ 07753
+S: USA
+
N: Erik Andersen
E: andersee@debian.org
W: http://www.inconnect.com/~andersen
diff -ruHpN -X badboys linux-2.1.78-orig/drivers/char/pty.c linux/drivers/char/pty.c
--- linux-2.1.78-orig/drivers/char/pty.c Mon Jan 12 16:36:05 1998
+++ linux/drivers/char/pty.c Thu Jan 15 00:09:08 1998
@@ -2,6 +2,9 @@
* linux/drivers/char/pty.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * Added support for a Unix98-style ptmx device.
+ * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
*/

#include <linux/errno.h>
@@ -191,6 +194,30 @@ static int pty_chars_in_buffer(struct tt
return ((count < N_TTY_BUF_SIZE/2) ? 0 : count);
}

+/*
+ * Return the minor device number of a given pty. This lets us
+ * open a master pty with the multi-headed ptmx device, then
+ * find out which one we got after it is open, with an ioctl.
+ */
+static int pty_get_device_minor(struct tty_struct *tty, unsigned int *value)
+{
+ unsigned int result = MINOR(tty->device);
+ return put_user(result, value);
+}
+
+static int pty_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ if (!tty) {
+ printk("pty_ioctl called with NULL tty!\n");
+ return -EIO;
+ }
+ if (cmd==TIOCGPTN) /* Get PT Number */
+ return pty_get_device_minor(tty, (unsigned int *)arg);
+
+ return -ENOIOCTLCMD;
+}
+
static void pty_flush_buffer(struct tty_struct *tty)
{
struct tty_struct *to = tty->link;
@@ -304,6 +331,12 @@ __initfunc(int pty_init(void))
old_pty_slave_driver.minor_start = 192;
old_pty_slave_driver.num = (NR_PTYS > 64) ? 64 : NR_PTYS;
old_pty_slave_driver.other = &old_pty_driver;
+
+ /* only the master pty gets this ioctl (which is why we
+ * assign it here, instead of up with the rest of the
+ * pty_driver initialization. <cananian@alumni.princeton.edu>
+ */
+ pty_driver.ioctl = pty_ioctl;

if (tty_register_driver(&pty_driver))
panic("Couldn't register pty driver");
diff -ruHpN -X badboys linux-2.1.78-orig/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- linux-2.1.78-orig/drivers/char/tty_io.c Mon Jan 12 16:36:05 1998
+++ linux/drivers/char/tty_io.c Wed Jan 14 19:47:41 1998
@@ -51,6 +51,9 @@
*
* Rewrote init_dev and release_dev to eliminate races.
* -- Bill Hawes <whawes@star.net>, June 97
+ *
+ * Added support for a Unix98-style ptmx device.
+ * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
*/

#include <linux/config.h>
@@ -91,6 +94,7 @@
#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
#define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
#define SYSCONS_DEV MKDEV(TTYAUX_MAJOR,1)
+#define PTMX_DEV MKDEV(TTYAUX_MAJOR,2)

#undef TTY_DEBUG_HANGUP

@@ -1171,7 +1175,6 @@ static void release_dev(struct file * fi
static int tty_open(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
- int minor;
int noctty, retval;
kdev_t device;
unsigned short saved_flags;
@@ -1203,12 +1206,38 @@ retry_open:
device = c->device(c);
noctty = 1;
}
- minor = MINOR(device);
+ if (device == PTMX_DEV) {
+ /* find a free pty. */
+ struct tty_driver *driver = tty_drivers;
+ int minor;
+
+ /* find the pty driver */
+ for (driver=tty_drivers; driver; driver=driver->next)
+ if (driver->major == PTY_MASTER_MAJOR)
+ break;
+ if (!driver) return -ENODEV;
+
+ /* find a minor device that is not in use. */
+ for (minor=driver->minor_start;
+ minor<driver->minor_start+driver->num;
+ minor++) {
+ device = MKDEV(driver->major, minor);
+ retval = init_dev(device, &tty);
+ if (retval==0) break; /* success! */
+ }
+ if (minor==driver->minor_start+driver->num) /* no success */
+ return -EIO; /* no free ptys */

+ noctty = 1;
+ goto init_dev_done;
+ }
+
retval = init_dev(device, &tty);
if (retval)
return retval;
+
/* N.B. this error exit may leave filp->f_flags with O_NONBLOCK set */
+init_dev_done:
filp->private_data = tty;
check_tty_count(tty, "tty_open");
if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
@@ -1932,7 +1961,7 @@ long console_init(long kmem_start, long
}

static struct tty_driver dev_tty_driver, dev_console_driver,
- dev_syscons_driver;
+ dev_syscons_driver, dev_ptmx_driver;

/*
* Ok, now we can initialize the rest of the tty devices and can count
@@ -1973,6 +2002,17 @@ __initfunc(int tty_init(void))

if (tty_register_driver(&dev_syscons_driver))
panic("Couldn't register /dev/console driver\n");
+
+ dev_ptmx_driver = dev_tty_driver;
+ dev_ptmx_driver.driver_name = "/dev/ptmx";
+ dev_ptmx_driver.name = dev_ptmx_driver.driver_name + 5;
+ dev_ptmx_driver.major= MAJOR(PTMX_DEV);
+ dev_ptmx_driver.minor_start = MINOR(PTMX_DEV);
+ dev_ptmx_driver.type = TTY_DRIVER_TYPE_SYSTEM;
+ dev_ptmx_driver.subtype = SYSTEM_TYPE_SYSPTMX;
+
+ if (tty_register_driver(&dev_ptmx_driver))
+ panic("Couldn't register /dev/ptmx driver\n");

#ifdef CONFIG_VT
dev_console_driver = dev_tty_driver;
diff -ruHpN -X badboys linux-2.1.78-orig/include/asm-alpha/ioctls.h linux/include/asm-alpha/ioctls.h
--- linux-2.1.78-orig/include/asm-alpha/ioctls.h Mon Jan 12 16:34:42 1998
+++ linux/include/asm-alpha/ioctls.h Wed Jan 14 23:50:14 1998
@@ -86,6 +86,7 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TIOCGPTN 0x5430 /* Get minor device of a pty master's FD */

#define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454
diff -ruHpN -X badboys linux-2.1.78-orig/include/asm-i386/ioctls.h linux/include/asm-i386/ioctls.h
--- linux-2.1.78-orig/include/asm-i386/ioctls.h Mon Jan 12 16:34:34 1998
+++ linux/include/asm-i386/ioctls.h Wed Jan 14 23:50:17 1998
@@ -47,6 +47,7 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TIOCGPTN 0x5430 /* Get minor device of a pty master's FD */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
diff -ruHpN -X badboys linux-2.1.78-orig/include/asm-m68k/ioctls.h linux/include/asm-m68k/ioctls.h
--- linux-2.1.78-orig/include/asm-m68k/ioctls.h Mon Jan 12 16:34:42 1998
+++ linux/include/asm-m68k/ioctls.h Wed Jan 14 23:50:49 1998
@@ -47,6 +47,7 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TIOCGPTN 0x5430 /* Get minor device of a pty master's FD */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
diff -ruHpN -X badboys linux-2.1.78-orig/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h
--- linux-2.1.78-orig/include/asm-mips/ioctls.h Mon Jan 12 16:34:40 1998
+++ linux/include/asm-mips/ioctls.h Wed Jan 14 23:52:10 1998
@@ -98,6 +98,8 @@
#define TIOCTTYGSTRUCT 0x5487 /* For debugging only */
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
+ /* Do we need TIOCGSID here? */
+#define TIOCGPTN 0x5430 /* Get minor device of a pty master's FD */

#define TIOCSERCONFIG 0x5488
#define TIOCSERGWILD 0x5489
diff -ruHpN -X badboys linux-2.1.78-orig/include/asm-ppc/ioctls.h linux/include/asm-ppc/ioctls.h
--- linux-2.1.78-orig/include/asm-ppc/ioctls.h Mon Jan 12 16:34:56 1998
+++ linux/include/asm-ppc/ioctls.h Wed Jan 14 23:52:29 1998
@@ -86,6 +86,7 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TIOCGPTN 0x5430 /* Get minor device of a pty master's FD */

#define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454
diff -ruHpN -X badboys linux-2.1.78-orig/include/asm-sparc/ioctls.h linux/include/asm-sparc/ioctls.h
--- linux-2.1.78-orig/include/asm-sparc/ioctls.h Mon Jan 12 16:34:43 1998
+++ linux/include/asm-sparc/ioctls.h Wed Jan 14 23:54:57 1998
@@ -75,6 +75,8 @@
#define TIOCGPGRP _IOR('t', 131, int)
#define TIOCSCTTY _IO('t', 132)
#define TIOCGSID _IOR('t', 133, int)
+/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */
+#define TIOCGPTN _IOR('t', 134, int)

/* Little f */
#define FIOCLEX _IO('f', 1)
diff -ruHpN -X badboys linux-2.1.78-orig/include/asm-sparc64/ioctls.h linux/include/asm-sparc64/ioctls.h
--- linux-2.1.78-orig/include/asm-sparc64/ioctls.h Mon Jan 12 16:34:57 1998
+++ linux/include/asm-sparc64/ioctls.h Wed Jan 14 23:54:55 1998
@@ -76,6 +76,8 @@
#define TIOCGPGRP _IOR('t', 131, int)
#define TIOCSCTTY _IO('t', 132)
#define TIOCGSID _IOR('t', 133, int)
+/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */
+#define TIOCGPTN _IOR('t', 134, int)

/* Little f */
#define FIOCLEX _IO('f', 1)
diff -ruHpN -X badboys linux-2.1.78-orig/include/linux/tty_driver.h linux/include/linux/tty_driver.h
--- linux-2.1.78-orig/include/linux/tty_driver.h Mon Jan 12 16:34:23 1998
+++ linux/include/linux/tty_driver.h Wed Jan 14 19:40:35 1998
@@ -213,6 +213,7 @@ struct tty_driver {
#define SYSTEM_TYPE_TTY 0x0001
#define SYSTEM_TYPE_CONSOLE 0x0002
#define SYSTEM_TYPE_SYSCONS 0x0003
+#define SYSTEM_TYPE_SYSPTMX 0x0004

/* pty subtypes (magic, used by tty_io.c) */
#define PTY_TYPE_MASTER 0x0001