Inserting flow-control chars with an mpsafetty kernel

Jilles Tjoelker jilles at
Thu Aug 28 22:58:42 UTC 2008

On Tue, Aug 26, 2008 at 06:01:44PM +0200, Ed Schouten wrote:
> There is indeed a small problem w.r.t. ^S/^Q characters with the MPSAFE
> TTY code, but it is not so directly involved in the handling of the
> actual characters, but a shortcoming of the pts(4) driver.

> There is this way a PTY (master device) can be configured to use `packet
> mode' (TIOCPKT). When this mode is enabled, all data that is read() by
> screen is prepended by a single byte, containing a bit mask of events.
> These events include flush events, but also flags indicating tcsetattr()
> has been called and has toggled VSTART/VSTOP.

> When I implemented the pts(4) driver, I thought the idea behind TIOCPKT
> is quite vague, because there is no real reason for pts(4) consumers to
> know this information. They just receive the raw data and inject
> keyboard actions. The pts(4) driver that lives in SVN now is a little
> broken, because it never returns any special events. It just prepends
> the data with a zero-byte, to keep the consumers happy.

> Screen(1) is a fairly moronic written application, which uses packet
> mode for no sensible reason at all. If you just comment out TIOCPKT in
> /usr/include/sys/ttycom.h and recompile screen(1), your problems are
> gone, right?

Packet mode seems intended to improve response time to some control
characters. rlogin/rlogind use it as follows:
- the server sends any nonzero event mask as TCP out of band data,
  additionally it may flush some outgoing data if TIOCPKT_FLUSHWRITE is
- the client disables local ^S/^Q handling on TIOCPKT_NOSTOP, enables
  local ^S/^Q handling on TIOCPKT_DOSTOP and flushes terminal input
  (both in the TCP stream before the OOB byte and in the kernel's output
  queue for the tty) on TIOCPKT_FLUSHWRITE

The effect is that ^S/^Q are handled locally (if possible) and that a
flush (e.g. after ^C) happens faster.

telnetd (both the regular and the heimdal kerberos one) seems to use
packet mode for a similar purpose, and also to allow canonical (ICANON)
input processing in the client (TIOCPKT_IOCTL and EXTPROC lflag). The
latter functionality is also known as LINEMODE.

sshd does not use packet mode.

screen(1) uses TIOCPKT_NOSTOP and TIOCPKT_DOSTOP only. This is described
under FLOW-CONTROL in the man page; it is similar to what rlogind does.

usr.bin/window uses TIOCPKT_STOP and TIOCPKT_START (as well as
TIOCPKT_FLUSHWRITE); I don't know why.

> There are three ways ways to fix this problem:

> - Implement a real packet mode which properly returns the TIOCPKT_*
>   flags. Unlike the previous TTY layer, it is a lot harder to do this
>   with MPSAFE TTY, because it turns the generic TTY code into more
>   bloat.

>   The new TTY layer has been designed to be a real front-end for the
>   device driver. There aren't any driver hooks (yet) to detect the
>   events supported by TIOCPKT, because `normal drivers' don't need these
>   event notifications anyway.

> - Remove TIOCPKT and TIOCPKT_* to <sys/ioctl_compat.h> and leave it
>   there to die. While there, also move definitions of other awkward
>   commands to this header.

> - Both.

> I was planning to prepare a changeset soonish, which removes the (in my
> opinion) deprecated ioctl()'s from our header files, so I can let the
> ports folks run a tinderbox to see how much breaks. This should give us
> a good estimation of the best approach.

The faster response to ^C/^S/^Q can probably be lived without.

EXTPROC and TIOCPKT_IOCTL were useful when canonical mode was used more,
e.g. with real csh(1) that pushed canonical mode to its limit. Nowadays,
though, almost all tty programs have either a curses-like or a
readline-like interface.

Screen's usage of TIOCPKT seems to clutter up the code for little
benefit. It is only somewhat useful in that it makes ^S/^Q respond
faster when running ssh over a slow link.

window(1) seems an abandoned piece of software; screen and tmux are nicer.

Binaries compiled for old versions will continue to use TIOCPKT. telnetd
seems to cope with TIOCEXT not setting EXTPROC. TIOCPKT failures usually
cause the program to abort. A slightly better stub TIOCPKT mode could
start off with a TIOCPKT_NOSTOP so that ^S/^Q are never treated
specially and never generate any of the others.

The linuxulator does not seem to translate linux's TIOCPKT, so such a
change probably would not break running linux rlogind/telnetd/screen any
more than it is already broken (most programs that use TIOCPKT allow
compiling without it defined, but abort if it is defined but fails).

Jilles Tjoelker

More information about the freebsd-current mailing list