misc/163871: 'script' save endline as ^M

Bruce Evans brde at optusnet.com.au
Sat Jan 7 08:30:14 UTC 2012

The following reply was made to PR bin/163871; it has been noted by GNATS.

From: Bruce Evans <brde at optusnet.com.au>
To: Bruce Evans <brde at optusnet.com.au>
Cc: Eugen Konkov <kes-kes at yandex.ru>, freebsd-gnats-submit at FreeBSD.org,
        freebsd-bugs at FreeBSD.org
Subject: Re: misc/163871: 'script' save endline as ^M
Date: Sat, 7 Jan 2012 19:24:15 +1100 (EST)

 On Sat, 7 Jan 2012, Bruce Evans wrote:
 > ...
 > watch(8) probably works better for input too.  Someone recently tried to
 > fix EOF handling in script(1) and had problems using VEOF since this gives
 > input processing unless the default echo mode is turned off.  Perhaps
 > watch(8) can handle this better too.  But watch doesn't understand EOF at
 > all, and is hard to terminate (the old version that I'm testing with
 > is terminated by ^G which generates a SIGINT, but it dumps core instead
 > of catching this signal as intended, and all versions have an unsafe
 > SIGINT handler which asks for core dumps).
 The core dump is because watch(8) tries to shoot its foot off, but only
 I notice because only my tty driver has been fixed to do the shooting.
 watch(8) sets both VINTR and VQUIT to ^G.  This should (*) result in ^G
 generating both a SIGINT and a SIGQUIT, and the SIGQUIT must terminate
 watch(8) since watch(8) only catches SIGINT.  But the unfixed tty
 driver only generates SIGINT.  The same bug affects VSUSP matching either
 VINTR or VSUSP, bu I didn't fix that.
 (*) POSIX doesn't seem to say what happens when control characters are
 equal, but it is hard to read its general specification of them as
 allowing the bugs.  From POSIX.1-2001-draft7 (the 2007 draft is similar):
 % 6722              INTR       Special character on input, which is recognized if the ISIG flag is set. Generates a
 % 6723                         SIGINT signal which is sent to all processes in the foreground process group for which
 % 6724                         the terminal is the controlling terminal. If ISIG is set, the INTR character shall be
 % 6725                         discarded when processed.
 % 6726              QUIT       Special character on input, which is recognized if the ISIG flag is set. Generates a
 % 6727                         SIGQUIT signal which is sent to all processes in the foreground process group for
 % 6728                         which the terminal is the controlling terminal. If ISIG is set, the QUIT character shall be
 % 6729                         discarded when processed.
 % 6747              SUSP       If the ISIG flag is set, receipt of the SUSP character shall cause a SIGTSTP signal to be
 % 6748                         sent to all processes in the foreground process group for which the terminal is the
 % 6749                         controlling terminal, and the SUSP character shall be discarded when processed.
 This says that these special characters are "recognized" and the
 corresponding signal is sent whenever ISIG is set.  The characters are
 discarded after processing them.  It takes a weaselish reading to allow
 the bug: we have to discard the characters after processing them just
 enough to generate a signal for them after processing them as another
 type of control character.  But I believe the discarding wasn't meant
 to do that.  It is just to keep these characters out of the final
 FreeBSD's termios(4) has essentially the same wording for this.
 % ...
 % 7019           If ISIG is set, each input character shall be checked against the special control characters INTR,
 % 7020           QUIT, and SUSP. If an input character matches one of these control characters, the function
 % 7021           associated with that character shall be performed. If ISIG is not set, no checking shall be done.
 This specifies what must be done if an input character matches "one" of
 the control characters.  If it matches more than one, then it certainly
 matches just one, so this can be read as requiring the action to be performed
 for all matches.  "one" can be read as "only one", but I think this is
 reading too much uniqueness into "one".  And if "only one" is meant, the
 precedence becomes important, but nothing is said about precedence.
 Anyway, the behaviour when some V characters are identical is very
 unportable, so they should never be be identical, and applications
 should not make some identical by changing only some and accidentally
 matching others.  watch(8) is setting VQUIT because it doesn't want
 to get SIGQUIT.  It is only accidental that setting it to the same as
 VINTR normally avoids the SIGQUIT (because VINTR has precedence, and
 the bug prevents getting both signals).  It should be setting VQUIT
 to _POSIX_VDISABLE to avoid SIGQUIT (it must do something, since the
 user might already have set it to ^G, in which case setting only VINTR
 to ^G would create the ambiguiuty).  Before _POSIX_VDISABLE existed,
 the only way to kill a control characted was to set it to a harmless
 value.  The null character may have been most harmless, and VQUIT =
 VINTR was apparently harmless too since most tty drivers had the bug.
 Maybe POSIX requires the bug somewhere, for historical incompatibility,
 although with _POSIX_VDISABLE it doesn't need this hack.  VQUIT is
 set by remarkably few applications in /usr/src (especially to a
 hard-coded value), so watch(8) is the main example of this.  Newer
 code tends to use _POSIX_VDISABLE.
 "stty sane" doesn't change control characters, so after watch(8)
 didn't restore the state, I saw much further weirdness from VINTR =
 VQUIT.  Most applications catch neither signal, and so they get
 killed normally by SIGINT for ^G instead of ^C.  Others tend to
 catch both SIGINT and ignore SIGQUIT, so they don't get killed like

More information about the freebsd-bugs mailing list