2010-06-15 19:02:28

by Howard Chu

[permalink] [raw]
Subject: [PATCH] tty: Add EXTPROC support for LINEMODE

This patch is against the 2.6.34 source.

Paraphrased from the 1989 BSD patch by David Borman @ cray.com:

These are the changes needed for the kernel to support
LINEMODE in the server.

There is a new bit in the termios local flag word, EXTPROC.
When this bit is set, several aspects of the terminal driver
are disabled. Input line editing, character echo, and mapping
of signals are all disabled. This allows the telnetd to turn
off these functions when in linemode, but still keep track of
what state the user wants the terminal to be in.

New ioctl:
TIOCSIG Generate a signal to processes in the
current process group of the pty.

There is a new mode for packet driver, the TIOCPKT_IOCTL bit.
When packet mode is turned on in the pty, and the EXTPROC bit
is set, then whenever the state of the pty is changed, the
next read on the master side of the pty will have the TIOCPKT_IOCTL
bit set, and the data will be the contents of a struct termios.
This allows the process on the server side of the pty to know
when the state of the terminal has changed, and what the new
state is.

Since the original BSD patches accompanied the source code for telnet I've
left that reference here, but obviously the feature is useful for any remote
terminal protocol, including ssh.

The corresponding feature has existed in the BSD tty driver since 1989. For
historical reference, a good copy of the relevant files can be found here:

http://anonsvn.mit.edu/viewvc/krb5/trunk/src/appl/telnet/?pathrev=17741

Signed-off-by: Howard Chu <[email protected]>

---
arch/alpha/include/asm/ioctls.h | 2 ++
arch/alpha/include/asm/termbits.h | 1 +
arch/arm/include/asm/ioctls.h | 2 ++
arch/arm/include/asm/termbits.h | 1 +
arch/avr32/include/asm/ioctls.h | 2 ++
arch/avr32/include/asm/termbits.h | 1 +
arch/cris/include/asm/ioctls.h | 2 ++
arch/cris/include/asm/termbits.h | 1 +
arch/frv/include/asm/ioctls.h | 2 ++
arch/frv/include/asm/termbits.h | 1 +
arch/h8300/include/asm/ioctls.h | 2 ++
arch/h8300/include/asm/termbits.h | 1 +
arch/ia64/include/asm/ioctls.h | 2 ++
arch/ia64/include/asm/termbits.h | 1 +
arch/m32r/include/asm/ioctls.h | 2 ++
arch/m32r/include/asm/termbits.h | 1 +
arch/m68k/include/asm/ioctls.h | 2 ++
arch/m68k/include/asm/termbits.h | 1 +
arch/mips/include/asm/ioctls.h | 3 ++-
arch/mips/include/asm/termbits.h | 1 +
arch/mn10300/include/asm/ioctls.h | 2 ++
arch/mn10300/include/asm/termbits.h | 1 +
arch/parisc/include/asm/ioctls.h | 2 ++
arch/parisc/include/asm/termbits.h | 1 +
arch/powerpc/include/asm/ioctls.h | 2 ++
arch/powerpc/include/asm/termbits.h | 1 +
arch/s390/include/asm/ioctls.h | 2 ++
arch/sh/include/asm/ioctls.h | 2 ++
arch/sparc/include/asm/ioctls.h | 2 ++
arch/sparc/include/asm/termbits.h | 1 +
arch/xtensa/include/asm/ioctls.h | 2 ++
arch/xtensa/include/asm/termbits.h | 1 +
drivers/char/n_tty.c | 25 ++++++++++++++++++++++---
drivers/char/pty.c | 13 +++++++++++++
drivers/char/tty_ioctl.c | 18 ++++++++++++------
fs/compat_ioctl.c | 1 +
include/asm-generic/ioctls.h | 2 ++
include/asm-generic/termbits.h | 1 +
include/linux/tty.h | 1 +
39 files changed, 101 insertions(+), 10 deletions(-)

diff --git a/arch/alpha/include/asm/ioctls.h b/arch/alpha/include/asm/ioctls.h
index 67bb9f6..8af5ee5 100644
--- a/arch/alpha/include/asm/ioctls.h
+++ b/arch/alpha/include/asm/ioctls.h
@@ -80,6 +80,7 @@
# define TIOCPKT_START 8
# define TIOCPKT_NOSTOP 16
# define TIOCPKT_DOSTOP 32
+# define TIOCPKT_IOCTL 64


#define TIOCNOTTY 0x5422
@@ -91,6 +92,7 @@
#define TIOCGSID 0x5429 /* Return the session ID of FD */
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454
diff --git a/arch/alpha/include/asm/termbits.h b/arch/alpha/include/asm/termbits.h
index ad854a4..879dd35 100644
--- a/arch/alpha/include/asm/termbits.h
+++ b/arch/alpha/include/asm/termbits.h
@@ -180,6 +180,7 @@ struct ktermios {
#define FLUSHO 0x00800000
#define PENDIN 0x20000000
#define IEXTEN 0x00000400
+#define EXTPROC 0x10000000

/* Values for the ACTION argument to `tcflow'. */
#define TCOOFF 0
diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h
index a91d8a1..e5e22cf 100644
--- a/arch/arm/include/asm/ioctls.h
+++ b/arch/arm/include/asm/ioctls.h
@@ -52,6 +52,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@@ -78,6 +79,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/arm/include/asm/termbits.h b/arch/arm/include/asm/termbits.h
index f784d11..704135d 100644
--- a/arch/arm/include/asm/termbits.h
+++ b/arch/arm/include/asm/termbits.h
@@ -177,6 +177,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000

/* tcflow() and TCXONC use these */
#define TCOOFF 0
diff --git a/arch/avr32/include/asm/ioctls.h b/arch/avr32/include/asm/ioctls.h
index 0cf2c0a..f947622 100644
--- a/arch/avr32/include/asm/ioctls.h
+++ b/arch/avr32/include/asm/ioctls.h
@@ -53,6 +53,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450
#define FIOCLEX 0x5451
@@ -81,6 +82,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/avr32/include/asm/termbits.h b/arch/avr32/include/asm/termbits.h
index db2daab..366adc5 100644
--- a/arch/avr32/include/asm/termbits.h
+++ b/arch/avr32/include/asm/termbits.h
@@ -175,6 +175,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000

/* tcflow() and TCXONC use these */
#define TCOOFF 0
diff --git a/arch/cris/include/asm/ioctls.h b/arch/cris/include/asm/ioctls.h
index 35bbc18..2569665 100644
--- a/arch/cris/include/asm/ioctls.h
+++ b/arch/cris/include/asm/ioctls.h
@@ -54,6 +54,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@@ -86,6 +87,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/cris/include/asm/termbits.h b/arch/cris/include/asm/termbits.h
index 66e1a74..1c43bc8 100644
--- a/arch/cris/include/asm/termbits.h
+++ b/arch/cris/include/asm/termbits.h
@@ -214,6 +214,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000

/* tcflow() and TCXONC use these */
#define TCOOFF 0
diff --git a/arch/frv/include/asm/ioctls.h b/arch/frv/include/asm/ioctls.h
index d0c30e3..a993e37 100644
--- a/arch/frv/include/asm/ioctls.h
+++ b/arch/frv/include/asm/ioctls.h
@@ -53,6 +53,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@@ -79,6 +80,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/frv/include/asm/termbits.h b/arch/frv/include/asm/termbits.h
index 5568492..7722e19 100644
--- a/arch/frv/include/asm/termbits.h
+++ b/arch/frv/include/asm/termbits.h
@@ -180,6 +180,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000


/* tcflow() and TCXONC use these */
diff --git a/arch/h8300/include/asm/ioctls.h b/arch/h8300/include/asm/ioctls.h
index 98a53d0..b6b249f 100644
--- a/arch/h8300/include/asm/ioctls.h
+++ b/arch/h8300/include/asm/ioctls.h
@@ -53,6 +53,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@@ -79,6 +80,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/h8300/include/asm/termbits.h b/arch/h8300/include/asm/termbits.h
index 31eca81..3287a62 100644
--- a/arch/h8300/include/asm/termbits.h
+++ b/arch/h8300/include/asm/termbits.h
@@ -179,6 +179,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000


/* tcflow() and TCXONC use these */
diff --git a/arch/ia64/include/asm/ioctls.h b/arch/ia64/include/asm/ioctls.h
index f41b636..a11af01 100644
--- a/arch/ia64/include/asm/ioctls.h
+++ b/arch/ia64/include/asm/ioctls.h
@@ -59,6 +59,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@@ -87,6 +88,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/ia64/include/asm/termbits.h b/arch/ia64/include/asm/termbits.h
index 9f162e0..c009b94 100644
--- a/arch/ia64/include/asm/termbits.h
+++ b/arch/ia64/include/asm/termbits.h
@@ -187,6 +187,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000

/* tcflow() and TCXONC use these */
#define TCOOFF 0
diff --git a/arch/m32r/include/asm/ioctls.h b/arch/m32r/include/asm/ioctls.h
index b9f54bb..366db76 100644
--- a/arch/m32r/include/asm/ioctls.h
+++ b/arch/m32r/include/asm/ioctls.h
@@ -53,6 +53,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450
#define FIOCLEX 0x5451
@@ -81,6 +82,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/m32r/include/asm/termbits.h b/arch/m32r/include/asm/termbits.h
index bc10400..957a3c6 100644
--- a/arch/m32r/include/asm/termbits.h
+++ b/arch/m32r/include/asm/termbits.h
@@ -179,6 +179,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000

/* tcflow() and TCXONC use these */
#define TCOOFF 0
diff --git a/arch/m68k/include/asm/ioctls.h b/arch/m68k/include/asm/ioctls.h
index b8d2f4b..91a57d6 100644
--- a/arch/m68k/include/asm/ioctls.h
+++ b/arch/m68k/include/asm/ioctls.h
@@ -52,6 +52,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@@ -78,6 +79,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/m68k/include/asm/termbits.h b/arch/m68k/include/asm/termbits.h
index 8c14170..aea1e37 100644
--- a/arch/m68k/include/asm/termbits.h
+++ b/arch/m68k/include/asm/termbits.h
@@ -179,6 +179,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000


/* tcflow() and TCXONC use these */
diff --git a/arch/mips/include/asm/ioctls.h b/arch/mips/include/asm/ioctls.h
index 3f04a99..767d196 100644
--- a/arch/mips/include/asm/ioctls.h
+++ b/arch/mips/include/asm/ioctls.h
@@ -41,7 +41,7 @@
#define TIOCPKT_START 0x08 /* start output */
#define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */
#define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */
-/* #define TIOCPKT_IOCTL 0x40 state change of pty driver */
+#define TIOCPKT_IOCTL 0x40 /* state change of pty driver */
#define TIOCSWINSZ _IOW('t', 103, struct winsize) /* set window size */
#define TIOCGWINSZ _IOR('t', 104, struct winsize) /* get window size */
#define TIOCNOTTY 0x5471 /* void tty association */
@@ -83,6 +83,7 @@
#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */

/* I hope the range from 0x5480 on is free ... */
#define TIOCSCTTY 0x5480 /* become controlling tty */
diff --git a/arch/mips/include/asm/termbits.h b/arch/mips/include/asm/termbits.h
index c83c684..76630b3 100644
--- a/arch/mips/include/asm/termbits.h
+++ b/arch/mips/include/asm/termbits.h
@@ -203,6 +203,7 @@ struct ktermios {
#define PENDIN 0040000 /* Retype pending input (state). */
#define TOSTOP 0100000 /* Send SIGTTOU for background output. */
#define ITOSTOP TOSTOP
+#define EXTPROC 0200000 /* External processing on pty */

/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
diff --git a/arch/mn10300/include/asm/ioctls.h b/arch/mn10300/include/asm/ioctls.h
index dcbfb45..c149fe1 100644
--- a/arch/mn10300/include/asm/ioctls.h
+++ b/arch/mn10300/include/asm/ioctls.h
@@ -54,6 +54,7 @@
#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number
* (of pty-mux device) */
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450
#define FIOCLEX 0x5451
@@ -82,6 +83,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/mn10300/include/asm/termbits.h b/arch/mn10300/include/asm/termbits.h
index eb2b0dc..130d424 100644
--- a/arch/mn10300/include/asm/termbits.h
+++ b/arch/mn10300/include/asm/termbits.h
@@ -180,6 +180,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000

/* tcflow() and TCXONC use these */
#define TCOOFF 0
diff --git a/arch/parisc/include/asm/ioctls.h b/arch/parisc/include/asm/ioctls.h
index 6747fad..bf73dbb 100644
--- a/arch/parisc/include/asm/ioctls.h
+++ b/arch/parisc/include/asm/ioctls.h
@@ -52,6 +52,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@@ -84,6 +85,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/parisc/include/asm/termbits.h b/arch/parisc/include/asm/termbits.h
index d8bbc73..d1ab921 100644
--- a/arch/parisc/include/asm/termbits.h
+++ b/arch/parisc/include/asm/termbits.h
@@ -180,6 +180,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000

/* tcflow() and TCXONC use these */
#define TCOOFF 0
diff --git a/arch/powerpc/include/asm/ioctls.h b/arch/powerpc/include/asm/ioctls.h
index 1842186..8519200 100644
--- a/arch/powerpc/include/asm/ioctls.h
+++ b/arch/powerpc/include/asm/ioctls.h
@@ -80,6 +80,7 @@
# define TIOCPKT_START 8
# define TIOCPKT_NOSTOP 16
# define TIOCPKT_DOSTOP 32
+# define TIOCPKT_IOCTL 64


#define TIOCNOTTY 0x5422
@@ -93,6 +94,7 @@
#define TIOCSRS485 0x542f
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454
diff --git a/arch/powerpc/include/asm/termbits.h b/arch/powerpc/include/asm/termbits.h
index 6698188..549d700 100644
--- a/arch/powerpc/include/asm/termbits.h
+++ b/arch/powerpc/include/asm/termbits.h
@@ -189,6 +189,7 @@ struct ktermios {
#define FLUSHO 0x00800000
#define PENDIN 0x20000000
#define IEXTEN 0x00000400
+#define EXTPROC 0x10000000

/* Values for the ACTION argument to `tcflow'. */
#define TCOOFF 0
diff --git a/arch/s390/include/asm/ioctls.h b/arch/s390/include/asm/ioctls.h
index 40e481b..2f3d873 100644
--- a/arch/s390/include/asm/ioctls.h
+++ b/arch/s390/include/asm/ioctls.h
@@ -60,6 +60,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@@ -86,6 +87,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/arch/sh/include/asm/ioctls.h b/arch/sh/include/asm/ioctls.h
index c212c37..eb6c4c6 100644
--- a/arch/sh/include/asm/ioctls.h
+++ b/arch/sh/include/asm/ioctls.h
@@ -69,6 +69,7 @@
# define TIOCPKT_START 8
# define TIOCPKT_NOSTOP 16
# define TIOCPKT_DOSTOP 32
+# define TIOCPKT_IOCTL 64


#define TIOCNOTTY _IO('T', 34) /* 0x5422 */
@@ -84,6 +85,7 @@
#define TCSETSF2 _IOW('T', 45, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */
#define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */
diff --git a/arch/sparc/include/asm/ioctls.h b/arch/sparc/include/asm/ioctls.h
index 1fe6855..53f4ee0 100644
--- a/arch/sparc/include/asm/ioctls.h
+++ b/arch/sparc/include/asm/ioctls.h
@@ -80,6 +80,7 @@
/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */
#define TIOCGPTN _IOR('t', 134, unsigned int) /* Get Pty Number */
#define TIOCSPTLCK _IOW('t', 135, int) /* Lock/unlock PTY */
+#define TIOCSIG _IOW('t', 136, int) /* Generate signal on Pty slave */

/* Little f */
#define FIOCLEX _IO('f', 1)
@@ -132,5 +133,6 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#endif /* !(_ASM_SPARC_IOCTLS_H) */
diff --git a/arch/sparc/include/asm/termbits.h b/arch/sparc/include/asm/termbits.h
index d72dfed..23b10ff 100644
--- a/arch/sparc/include/asm/termbits.h
+++ b/arch/sparc/include/asm/termbits.h
@@ -225,6 +225,7 @@ struct ktermios {
#define FLUSHO 0x00002000
#define PENDIN 0x00004000
#define IEXTEN 0x00008000
+#define EXTPROC 0x00010000

/* modem lines */
#define TIOCM_LE 0x001
diff --git a/arch/xtensa/include/asm/ioctls.h b/arch/xtensa/include/asm/ioctls.h
index 0ffa942..ab18000 100644
--- a/arch/xtensa/include/asm/ioctls.h
+++ b/arch/xtensa/include/asm/ioctls.h
@@ -81,6 +81,7 @@
# define TIOCPKT_START 8
# define TIOCPKT_NOSTOP 16
# define TIOCPKT_DOSTOP 32
+# define TIOCPKT_IOCTL 64


#define TIOCNOTTY _IO('T', 34)
@@ -97,6 +98,7 @@
#define TCSETSF2 _IOW('T', 45, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */

#define TIOCSERCONFIG _IO('T', 83)
#define TIOCSERGWILD _IOR('T', 84, int)
diff --git a/arch/xtensa/include/asm/termbits.h b/arch/xtensa/include/asm/termbits.h
index 85aa6a3..0d6c871 100644
--- a/arch/xtensa/include/asm/termbits.h
+++ b/arch/xtensa/include/asm/termbits.h
@@ -196,6 +196,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000

/* tcflow() and TCXONC use these */

diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index bdae832..67caa01 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -1102,6 +1102,11 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
if (I_IUCLC(tty) && L_IEXTEN(tty))
c = tolower(c);

+ if (L_EXTPROC(tty)) {
+ put_tty_queue(c, tty);
+ return;
+ }
+
if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) &&
c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) {
@@ -1409,7 +1414,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,

n_tty_set_room(tty);

- if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
+ if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
+ L_EXTPROC(tty)) {
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
wake_up_interruptible(&tty->read_wait);
@@ -1585,7 +1591,7 @@ static int n_tty_open(struct tty_struct *tty)
static inline int input_available_p(struct tty_struct *tty, int amt)
{
tty_flush_to_ldisc(tty);
- if (tty->icanon) {
+ if (tty->icanon && !L_EXTPROC(tty)) {
if (tty->canon_data)
return 1;
} else if (tty->read_cnt >= (amt ? amt : 1))
@@ -1632,6 +1638,11 @@ static int copy_from_read_buf(struct tty_struct *tty,
spin_lock_irqsave(&tty->read_lock, flags);
tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
tty->read_cnt -= n;
+ /* Check if last character is EOF */
+ if (L_EXTPROC(tty) && tty->icanon) {
+ if (!tty->read_cnt && *b[n-1] == EOF_CHAR(tty))
+ n--;
+ }
spin_unlock_irqrestore(&tty->read_lock, flags);
*b += n;
*nr -= n;
@@ -1767,6 +1778,14 @@ do_it_again:
break;
}
nr--;
+ if (cs & TIOCPKT_IOCTL) {
+ c = sizeof(struct termios);
+ if (c > nr)
+ c = nr;
+ copy_to_user(b, tty->link->termios, c);
+ nr -= c;
+ b += c;
+ }
break;
}
/* This statement must be first before checking for input
@@ -1812,7 +1831,7 @@ do_it_again:
nr--;
}

- if (tty->icanon) {
+ if (tty->icanon && !L_EXTPROC(tty)) {
/* N.B. avoid overrun if nr == 0 */
while (nr && tty->read_cnt) {
int eol;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index d83a431..c429e9f 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -171,6 +171,15 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg)
return 0;
}

+/* Send a signal to the slave */
+static int pty_signal(struct tty_struct *tty, int sig)
+{
+ if (tty->link) {
+ kill_pgrp(tty->link->pgrp, sig, 1);
+ }
+ return 0;
+}
+
static void pty_flush_buffer(struct tty_struct *tty)
{
struct tty_struct *to = tty->link;
@@ -321,6 +330,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
switch (cmd) {
case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
return pty_set_lock(tty, (int __user *) arg);
+ case TIOCSIG: /* Send signal to other side of pty */
+ return pty_signal(tty, (int) arg);
}
return -ENOIOCTLCMD;
}
@@ -476,6 +487,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
return pty_set_lock(tty, (int __user *)arg);
case TIOCGPTN: /* Get PT Number */
return put_user(tty->index, (unsigned int __user *)arg);
+ case TIOCSIG: /* Send signal to other side of pty */
+ return pty_signal(tty, (int) arg);
}

return -ENOIOCTLCMD;
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 6bd5f88..0c18899 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -517,19 +517,25 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)

/* See if packet mode change of state. */
if (tty->link && tty->link->packet) {
+ int extproc = (old_termios.c_lflag & EXTPROC) |
+ (tty->termios->c_lflag & EXTPROC);
int old_flow = ((old_termios.c_iflag & IXON) &&
(old_termios.c_cc[VSTOP] == '\023') &&
(old_termios.c_cc[VSTART] == '\021'));
int new_flow = (I_IXON(tty) &&
STOP_CHAR(tty) == '\023' &&
START_CHAR(tty) == '\021');
- if (old_flow != new_flow) {
+ if ((old_flow != new_flow) || extproc) {
spin_lock_irqsave(&tty->ctrl_lock, flags);
- tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
- if (new_flow)
- tty->ctrl_status |= TIOCPKT_DOSTOP;
- else
- tty->ctrl_status |= TIOCPKT_NOSTOP;
+ if (old_flow != new_flow) {
+ tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
+ if (new_flow)
+ tty->ctrl_status |= TIOCPKT_DOSTOP;
+ else
+ tty->ctrl_status |= TIOCPKT_NOSTOP;
+ }
+ if (extproc)
+ tty->ctrl_status |= TIOCPKT_IOCTL;
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
wake_up_interruptible(&tty->link->read_wait);
}
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 641640d..766636d 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -966,6 +966,7 @@ COMPATIBLE_IOCTL(TIOCGPGRP)
COMPATIBLE_IOCTL(TIOCGPTN)
COMPATIBLE_IOCTL(TIOCSPTLCK)
COMPATIBLE_IOCTL(TIOCSERGETLSR)
+COMPATIBLE_IOCTL(TIOCSIG)
#ifdef TCGETS2
COMPATIBLE_IOCTL(TCGETS2)
COMPATIBLE_IOCTL(TCSETS2)
diff --git a/include/asm-generic/ioctls.h b/include/asm-generic/ioctls.h
index a799e20..87661c8 100644
--- a/include/asm-generic/ioctls.h
+++ b/include/asm-generic/ioctls.h
@@ -69,6 +69,7 @@
#define TCSETX 0x5433
#define TCSETXF 0x5434
#define TCSETXW 0x5435
+#define TIOCSIG _IOW('T', 0x36, int) /* pty: generate signal */

#define FIONCLEX 0x5450
#define FIOCLEX 0x5451
@@ -104,6 +105,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64

#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

diff --git a/include/asm-generic/termbits.h b/include/asm-generic/termbits.h
index 1c9773d..232b478 100644
--- a/include/asm-generic/termbits.h
+++ b/include/asm-generic/termbits.h
@@ -178,6 +178,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
+#define EXTPROC 0200000

/* tcflow() and TCXONC use these */
#define TCOOFF 0
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 4409967..3cfe448 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -178,6 +178,7 @@ struct tty_bufhead {
#define L_FLUSHO(tty) _L_FLAG((tty), FLUSHO)
#define L_PENDIN(tty) _L_FLAG((tty), PENDIN)
#define L_IEXTEN(tty) _L_FLAG((tty), IEXTEN)
+#define L_EXTPROC(tty) _L_FLAG((tty), EXTPROC)

struct device;
struct signal_struct;
--
1.7.0.4

--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/


2010-06-15 19:26:16

by Alan

[permalink] [raw]
Subject: Re: [PATCH] tty: Add EXTPROC support for LINEMODE

> bit set, and the data will be the contents of a struct termios.
> This allows the process on the server side of the pty to know
> when the state of the terminal has changed, and what the new
> state is.

First problem - the kernel and user idea of struct termios don't match.


> diff --git a/arch/alpha/include/asm/termbits.h b/arch/alpha/include/asm/termbits.h
> index ad854a4..879dd35 100644
> --- a/arch/alpha/include/asm/termbits.h
> +++ b/arch/alpha/include/asm/termbits.h
> @@ -180,6 +180,7 @@ struct ktermios {
> #define FLUSHO 0x00800000
> #define PENDIN 0x20000000
> #define IEXTEN 0x00000400
> +#define EXTPROC 0x10000000

For Alpha this value should match OSF if possible.


> + if (cs & TIOCPKT_IOCTL) {
> + c = sizeof(struct termios);
> + if (c > nr)
> + c = nr;
> + copy_to_user(b, tty->link->termios, c);
> + nr -= c;
> + b += c;
> + }

This is where the wheels come off the bus.

The kernel use struct ktermios which is what tty->link->termios is

The C library presents this via struct termios which is a glibc invention
dependant on the C library and which is converted by libc from struct
termios or struct termios2 depending on your C library

How you fix that given a broken by design historic Unix interface which
pastes arbitary struct termios objects into the data stream is an
interesting question - doubly so when like most Unixen we have also have
extended terminal attributes as well (termiox)

Alan

2010-06-15 19:54:54

by Howard Chu

[permalink] [raw]
Subject: Re: [PATCH] tty: Add EXTPROC support for LINEMODE

Alan Cox wrote:
>> bit set, and the data will be the contents of a struct termios.
>> This allows the process on the server side of the pty to know
>> when the state of the terminal has changed, and what the new
>> state is.
>
> First problem - the kernel and user idea of struct termios don't match.

OK, since you mention it again down below I'll respond to this last.

>> diff --git a/arch/alpha/include/asm/termbits.h b/arch/alpha/include/asm/termbits.h
>> index ad854a4..879dd35 100644
>> --- a/arch/alpha/include/asm/termbits.h
>> +++ b/arch/alpha/include/asm/termbits.h
>> @@ -180,6 +180,7 @@ struct ktermios {
>> #define FLUSHO 0x00800000
>> #define PENDIN 0x20000000
>> #define IEXTEN 0x00000400
>> +#define EXTPROC 0x10000000
>
> For Alpha this value should match OSF if possible.

I'm grubbing around looking for a live Alpha system now, doesn't seem likely
that I'll find one. Not sure what needs to match here, it's also unlikely that
OSF/1 (or any other SVR4 platform) ever provided a definition for this bit.
Looking at the telnet README:
>>>>
This is a distribution of both client and server telnet. These programs
have been compiled on:
telnet telnetd
BSD 4.4 x x
BSD 4.3 Reno X X
UNICOS 8.0 X X
UNICOS 7.C X X
UNICOS 7.0 X X
UNICOS 6.1 X X
BSDI 1.0 X X
Solaris 2.2 x x (no linemode in server)
Solaris 2.3 x x (no linemode in server)
SunOs 4.1.3 X X (no linemode in server)
Ultrix 4.3 X X (no linemode in server)
DYNIX V3.0.17.9 X X (no linemode in server)
HP-UX 8.0 x x (no linemode in server)
<<<<

I doubt that anyone ever ported this feature over to those OSes.
>
>
>> + if (cs& TIOCPKT_IOCTL) {
>> + c = sizeof(struct termios);
>> + if (c> nr)
>> + c = nr;
>> + copy_to_user(b, tty->link->termios, c);
>> + nr -= c;
>> + b += c;
>> + }
>
> This is where the wheels come off the bus.
>
> The kernel use struct ktermios which is what tty->link->termios is
>
> The C library presents this via struct termios which is a glibc invention
> dependant on the C library and which is converted by libc from struct
> termios or struct termios2 depending on your C library
>
> How you fix that given a broken by design historic Unix interface which
> pastes arbitary struct termios objects into the data stream is an
> interesting question - doubly so when like most Unixen we have also have
> extended terminal attributes as well (termiox)

Are you suggesting that this is completely unfixable/unworkable? Would it be
sufficient to use kernel_termios_to_user_termios() ?

--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/

2010-06-15 20:23:52

by Howard Chu

[permalink] [raw]
Subject: Re: [PATCH] tty: Add EXTPROC support for LINEMODE

Howard Chu wrote:
>>> diff --git a/arch/alpha/include/asm/termbits.h b/arch/alpha/include/asm/termbits.h
>>> index ad854a4..879dd35 100644
>>> --- a/arch/alpha/include/asm/termbits.h
>>> +++ b/arch/alpha/include/asm/termbits.h
>>> @@ -180,6 +180,7 @@ struct ktermios {
>>> #define FLUSHO 0x00800000
>>> #define PENDIN 0x20000000
>>> #define IEXTEN 0x00000400
>>> +#define EXTPROC 0x10000000
>>
>> For Alpha this value should match OSF if possible.
>
> I'm grubbing around looking for a live Alpha system now, doesn't seem likely
> that I'll find one. Not sure what needs to match here, it's also unlikely that
> OSF/1 (or any other SVR4 platform) ever provided a definition for this bit.
> Looking at the telnet README:
> >>>>
> This is a distribution of both client and server telnet. These programs
> have been compiled on:
> telnet telnetd
> BSD 4.4 x x
> BSD 4.3 Reno X X
> UNICOS 8.0 X X
> UNICOS 7.C X X
> UNICOS 7.0 X X
> UNICOS 6.1 X X
> BSDI 1.0 X X
> Solaris 2.2 x x (no linemode in server)
> Solaris 2.3 x x (no linemode in server)
> SunOs 4.1.3 X X (no linemode in server)
> Ultrix 4.3 X X (no linemode in server)
> DYNIX V3.0.17.9 X X (no linemode in server)
> HP-UX 8.0 x x (no linemode in server)
> <<<<
>
> I doubt that anyone ever ported this feature over to those OSes.

Closest thing I've found so far is for HPUX 11i Version 2:
http://docs.hp.com/en/B2355-90848docs/B2355-90848docs.pdf

>>>>
TIOCREMOTE This ioctl puts the STREAMS pty in and out of Remote Mode. When
Remote Mode is on, input data will be flow-controlled and passed
through ldterm without any input processing regardless of the
terminal mode. When the pty master driver receives this ioctl,
it will send an M_CTL message downstream to ldterm via ptm, pts,
and ptem. The command in the M_CTL message is set to MC_NO_CANON
or MC_DO_CANON depending whether to turn on or off the Remote
Mode. The format of this ioctl is:
int ioctl(master_fd, TIOCREMOTE, argument)
where the argument is set to 1 to turn on Remote Mode and 0 to
turn it off. Remote Mode is normally used when doing remote line
editing in a window manager, or whenever flow-controlled input is
required. Each write to the master device produces a record
boundary for the process reading the slave devices. In normal
usage, a write of data is like the data typed as a line on the
terminal; a write of 0 (zero) bytes is like typing an EOF
(End-of-File) character.

TIOCSIGNAL This ioctl allows the master process to send a signal to the slave
process. The format of this ioctl is:


int ioctl(master_fd, TIOCSIGNAL, argument)
where the argument is the signal number as defined in the header
file <sys/signal.h>. For example the master process can send an
SIGINT signal to the slave process by doing:
ioctl(master_fd, TIOCSIGNAL, SIGINT)
<<<<

TIOCREMOTE seems to be the SVR4 analogue to TIOCPKT without any of the useful
parts; it doesn't include the prefix byte, so it doesn't provide any state
change information.

--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/

2010-06-16 01:24:57

by Chris Adams

[permalink] [raw]
Subject: Re: [PATCH] tty: Add EXTPROC support for LINEMODE

Once upon a time, Alan Cox <[email protected]> said:
>> +#define EXTPROC 0x10000000
>
>For Alpha this value should match OSF if possible.

Since I'm reading this on an Alpha right now, I figured I'd do my bit to
help out. As far as I can tell, Tru64 5.1B doesn't define this, nor
does the above value match any of the Tru64-defined local flags.
--
Chris Adams <[email protected]>
Systems and Network Administrator - HiWAAY Internet Services
I don't speak for anybody but myself - that's enough trouble.

2010-06-16 15:23:07

by Derek Fawcus

[permalink] [raw]
Subject: Re: [PATCH] tty: Add EXTPROC support for LINEMODE

On Tue, Jun 15, 2010 at 01:23:43PM -0700, Howard Chu wrote:
>
> Closest thing I've found so far is for HPUX 11i Version 2:
> http://docs.hp.com/en/B2355-90848docs/B2355-90848docs.pdf
>
> TIOCREMOTE This ioctl puts the STREAMS pty in and out of Remote Mode. When

> TIOCSIGNAL This ioctl allows the master process to send a signal to the slave

> <<<<
>
> TIOCREMOTE seems to be the SVR4 analogue to TIOCPKT without any of the useful parts; it doesn't include the prefix
> byte, so it doesn't provide any state change information.

TIOCREMOTE is also supported on BSDs.
A program I've been playing with on and off for a few years uses it (on solaris, FreeBSD, Darwin).

That in combination with turning off all output post processing, and then regularly sampling the
status of the pty for the following generally works:

static int
internal_get_modes (int fd, int *modep)
{
int modes = 0;

if (tcgetattr(fd, &tty_mode) < 0)
return 0;

if (tty_mode.c_lflag & ICANON)
modes |= MODE_CANON;
else if (tty_mode.c_lflag & ISIG)
modes |= MODE_CBREAK;
else
modes |= MODE_RAW;
if (tty_mode.c_lflag & ECHO)
modes |= MODE_ECHO;

if (tty_mode.c_cc[VINTR] != vdisable) modes |= MODE_INTR;
if (tty_mode.c_cc[VQUIT] != vdisable) modes |= MODE_QUIT;
if (tty_mode.c_cc[VSUSP] != vdisable) modes |= MODE_SUSP;

*modep = modes;

return 1;
}

There is obviously a race condition in detecting the change in the above, but usually this
is only an issue when starting/stopping certain curses apps, and can be handled by the various
app redraw command.

Currently for Linux, I disable echo before feeding characters to the pty, then restore it
to its previous state. So REMOTE mode would be useful.

Sending signals to the terminal group is different for BSD/solaris/Linux:

int master_signal_tcpgrp (int master_fd, unsigned signo) // BSD
{
return ioctl(master_fd, TIOCSIG, signo);
}

int master_signal_tcpgrp (int master_fd, unsigned signo) // Linux
{
pid_t tcpgrp;

tcpgrp = tcgetpgrp(master_fd);
if (tcpgrp == -1) {
return -1;
}

return kill(-tcpgrp, signo);
}

int master_signal_tcpgrp (int master_fd, unsigned signo) // SVR4
{
return ioctl(master_fd, TIOCSIGNAL, signo);
}

Now for a notification type packet mode extension, something which provided the
information extracted in the above set of MODE change indications would be useful,
since it would remove the race condition. i.e. a completely different interpretation
of the packet when supplying the control info.

DF

2010-06-17 20:03:08

by Howard Chu

[permalink] [raw]
Subject: Re: [PATCH] tty: Add EXTPROC support for LINEMODE

Ping, any further advice on these issues?

Howard Chu wrote:
> Alan Cox wrote:
>>> diff --git a/arch/alpha/include/asm/termbits.h b/arch/alpha/include/asm/termbits.h
>>> index ad854a4..879dd35 100644
>>> --- a/arch/alpha/include/asm/termbits.h
>>> +++ b/arch/alpha/include/asm/termbits.h
>>> @@ -180,6 +180,7 @@ struct ktermios {
>>> #define FLUSHO 0x00800000
>>> #define PENDIN 0x20000000
>>> #define IEXTEN 0x00000400
>>> +#define EXTPROC 0x10000000
>>
>> For Alpha this value should match OSF if possible.

OSF didn't define this flag, nor did it assign that particular bit to any
purpose. Is that good enough?

>>> + if (cs& TIOCPKT_IOCTL) {
>>> + c = sizeof(struct termios);
>>> + if (c> nr)
>>> + c = nr;
>>> + copy_to_user(b, tty->link->termios, c);
>>> + nr -= c;
>>> + b += c;
>>> + }
>>
>> This is where the wheels come off the bus.
>>
>> The kernel use struct ktermios which is what tty->link->termios is
>>
>> The C library presents this via struct termios which is a glibc invention
>> dependant on the C library and which is converted by libc from struct
>> termios or struct termios2 depending on your C library
>>
>> How you fix that given a broken by design historic Unix interface which
>> pastes arbitary struct termios objects into the data stream is an
>> interesting question - doubly so when like most Unixen we have also have
>> extended terminal attributes as well (termiox)
>
> Are you suggesting that this is completely unfixable/unworkable? Would it be
> sufficient to use kernel_termios_to_user_termios() ?
>
Actually using kernel_termios_to_user_termios_1(). In all supported
architectures this structure is basically aligned with but smaller than the
userland struct termios. As such it will leave any unused fields unwritten in
the user struct. This usually means it will leave c_ispeed and c_ospeed unset
in the user struct, but that's a don't-care anyway since we're only talking
about ptys here, and changing the speed (besides setting it to zero) is
irrelevant for ptys.

--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/

2010-06-17 20:45:40

by Alan

[permalink] [raw]
Subject: Re: [PATCH] tty: Add EXTPROC support for LINEMODE

> >> For Alpha this value should match OSF if possible.
>
> OSF didn't define this flag, nor did it assign that particular bit to any
> purpose. Is that good enough?

Fine

> > Are you suggesting that this is completely unfixable/unworkable? Would it be
> > sufficient to use kernel_termios_to_user_termios() ?

I don't see a way to fix it sanely

> >
> Actually using kernel_termios_to_user_termios_1(). In all supported
> architectures this structure is basically aligned with but smaller than the
> userland struct termios.

The relationship isn't quite so simple and it may change in the future,
so this seems to be a very bad idea. Besides which syscalls are *cheap*
so simply notifying someone to reread the terminal data they care about
should be fine. In that sense it seems SVR4 got it right.

Alan

2010-06-17 21:23:14

by Howard Chu

[permalink] [raw]
Subject: Re: [PATCH] tty: Add EXTPROC support for LINEMODE

Alan Cox wrote:
>>>> For Alpha this value should match OSF if possible.
>>
>> OSF didn't define this flag, nor did it assign that particular bit to any
>> purpose. Is that good enough?
>
> Fine
>
>>> Are you suggesting that this is completely unfixable/unworkable? Would it be
>>> sufficient to use kernel_termios_to_user_termios() ?
>
> I don't see a way to fix it sanely
>
>>>
>> Actually using kernel_termios_to_user_termios_1(). In all supported
>> architectures this structure is basically aligned with but smaller than the
>> userland struct termios.
>
> The relationship isn't quite so simple and it may change in the future,
> so this seems to be a very bad idea. Besides which syscalls are *cheap*
> so simply notifying someone to reread the terminal data they care about
> should be fine. In that sense it seems SVR4 got it right.

OK. I'm fine with only setting a bit in the packet header, and letting the
application do an ioctl/tcgetattr to discover the actual state. Next question
is, should this bit still be called TIOCPKT_IOCTL (which BSD uses) or should
it be called something else, since the behavior is not the same as BSD?

--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/

2010-06-17 23:43:09

by Howard Chu

[permalink] [raw]
Subject: Re: [PATCH] tty: Add EXTPROC support for LINEMODE

Howard Chu wrote:
> Alan Cox wrote:
>>>>> For Alpha this value should match OSF if possible.
>>>
>>> OSF didn't define this flag, nor did it assign that particular bit to any
>>> purpose. Is that good enough?
>>
>> Fine
>>
>>>> Are you suggesting that this is completely unfixable/unworkable? Would it be
>>>> sufficient to use kernel_termios_to_user_termios() ?
>>
>> I don't see a way to fix it sanely
>>
>>>>
>>> Actually using kernel_termios_to_user_termios_1(). In all supported
>>> architectures this structure is basically aligned with but smaller than the
>>> userland struct termios.
>>
>> The relationship isn't quite so simple and it may change in the future,
>> so this seems to be a very bad idea. Besides which syscalls are *cheap*
>> so simply notifying someone to reread the terminal data they care about
>> should be fine. In that sense it seems SVR4 got it right.

> OK. I'm fine with only setting a bit in the packet header, and letting the
> application do an ioctl/tcgetattr to discover the actual state.

Just deleting that part of the patch was simple enough. The TIOCPKT_IOCTL bit
still gets set in the packet header byte; userspace apps will just have to do
an ioctl to retrieve the state when the bit is set.

I've also added locking to the pty_signal() function. The check for tty->link
seems a bit paranoid, but a few other functions do it as well.

/* Send a signal to the slave */
static int pty_signal(struct tty_struct *tty, int sig)
{
unsigned long flags;
struct pid *pgrp;

if (tty->link) {
spin_lock_irqsave(&tty->link->ctrl_lock, flags);
pgrp = get_pid(tty->link->pgrp);
spin_unlock_irqrestore(&tty->link->ctrl_lock, flags);

kill_pgrp(pgrp, sig, 1);
put_pid(pgrp);
}
return 0;
}

That covers all the feedback so far. I'll be reposting the entire patch again
shortly, unless you have any additional thoughts.

--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/