Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0001532 [Issue 8 drafts] Shell and Utilities Objection Error 2021-11-03 14:15 2022-02-24 11:52
Reporter stephane View Status public  
Assigned To
Priority normal Resolution Accepted As Marked  
Status Applied   Product Version Draft 2.1
Name Stephane Chazelas
Organization
User Reference 0001053
Section stty utility
Page Number
Line Number
Final Accepted Text Note: 0005655
Summary 0001532: "stty -g" output should not have to be split
Description The resolution of 0001053, about the specification of "stty -g" changes:

-g

    Write to standard output all the current settings in an
    unspecified form that can be used as arguments to another
    invocation of the stty utility on the same system. The form
    used shall not contain any characters that would require
    quoting to avoid word expansion by the shell; see Section
    2.6 (on page 2353).

to:

-g

    Write to standard output all the current settings,
    optionally excluding the terminal window size, in an
    unspecified form that, when used as arguments to another
    invocation of the stty utility on the same system, attempts
    to apply those settings to the terminal. The form used shall
    not contain any sequence that would form an Informational
    Query, nor any characters that would require quoting to
    avoid word expansions, other than field splitting, by the
    shell; see Section 2.6 (on page 2353).

While the 2018 edition had:

-g
    Write to standard output all the current settings in an
    unspecified form that can be used as arguments to another
    invocation of the stty utility on the same system. The form
    used shall not contain any characters that would require
    quoting to avoid word expansion by the shell; see wordexp.

It's one stream of bytes that applications send to standard output.

For that stream of bytes to be "used as argument*S* to another
invocation of the stty utility", it implies that that output should
somehow be split into a list of arguments (and also implies the
result fits in the ARG_MAX limit and doesn't contain NUL bytes).

The reference to 2.6 suggests maybe "sh" should be involved to
perform that splitting. It almost suggests that the output
should be appended to "stty ", or possibly "stty -- " and fed to
sh as in (printf "stty -- "; stty -g) | sh

AFAIK, stty -g was introduced in SysIII circa 1980. It was
outputting on word on one line made of a ":"-separated of alnums
from the portable charset and followed by a newline character.
After it was specified by POSIX, it was also added to BSDs (some
4.3 variant), with "=" in the list of characters that may occur
(not in leading position) in the ":"-delimited list.
GNU stty has used a format similar to SysIII from at least as
far back as 1990.

The way to save and restore it was always to store that output
without the trailing newline characters, which in a shell can be
done with:

saveterm=$(stty -g)

And to restore it:

stty "$saveterm"

The "--" being unnecessary because the output of stty -g never
starts with "-" and with some (including GNU stty) not allowed.

All the documentations of stty I've seen talk of *one* (an)
argument to be passed to stty. They don't say the output may
(let alone should) be split in any way to be passed as several
arguments to stty.

In the unlikely event that there are indeed stty implementations
that require the output of stty -g to be split into arguments
before being fed back to stty, we'd need to specify how those
are meant to be split.
Desired Action Change the description of the -g option to something like:

-g

    Write to standard output all the current settings,
    optionally excluding the terminal window size, in an
    unspecified form that, when stripped of trailing newline
    characters, and used as the one and only argument to another
    invocation of the stty utility on the same system, attempts
    to apply those settings to the terminal. The form used shall
    consist of one line of text consisting of only printable
    characters from the portable character set, excluding
    whitespace characters, NUL, and all characters that are
    special in the syntax of the sh language
    (`"$&*()[]{};'#~?<>\|).

    (alternatively, specify it as the
    ^[[:alnum:]][[:alnum:]=]*:[[:alnum:]=:]*\n
    extended regexp in the C locale.)

A clarifying example would help like:

saveterm=$(stty -g)

and:

[ -n "$saveterm" ] && stty "$saveterm"
[ -n "$saveterm" ] && stty $saveterm
eval "${saveterm:+stty $saveterm}"

Are three ways the settings may be restored, the first one
being the canonical one and the last one assuming none of the
characters allowed in the stty -g output are currently present
in $IFS (and therefore not recommended).

The example should be changed to

saveterm=$(stty −g) # save terminal state
restoresize=$(
  stty size | awk '{printf "stty rows %d cols %d", $1, $2}'
) # save terminal size
stty new settings # set new state
...
[ -n "$saveterm" ] && stty "$saveterm" # restore terminal state
eval "$ttysize" # restore terminal size

Also using awk instead of shell IFS-splitting+globbing as as
discussed on the mailing list, $IFS is not guaranteed to contain
all the blank characters in the locale (and anyway yash is the
only shell that considers multi-byte blanks as
IFS-whitespace-characters wrt IFS-splitting), while awk is
required to split fields on blanks (even though not all
implementations do).
Tags issue8
Attached Files

- Relationships
related to 0001687Applied Mismatch between blanks in file formats and default IFS 

-  Notes
(0005513)
stephane (reporter)
2021-11-03 14:23

Sorry, a few typos above.

"It was outputting on word on one line made" should be "It was outputting one word on one line made"

The regexp was intended to be

^[[:alnum:]][[:alnum:]=]*:[[:alnum:]=:]*\n$

(starts with an alnum, contains at least 1 ":" and contains only alnums, ":" or "=" characters).

In:

> [ -n "$saveterm" ] && stty "$saveterm"
> [ -n "$saveterm" ] && stty $saveterm
> eval "${saveterm:+stty $saveterm}"

It's the second, not last that is dependant on IFS and should be avoided.
(0005514)
stephane (reporter)
2021-11-03 14:51
edited on: 2021-11-03 14:51

> The reference to 2.6 suggests maybe "sh" should be involved to
> perform that splitting. It almost suggests that the output
> should be appended to "stty ", or possibly "stty -- " and fed to
> sh as in (printf "stty -- "; stty -g) | sh

That however wouldn't work as sh's stdin would then be a pipe and not the terminal . Not to mention the fact that if stty -g fails, the code becomes "stty " or "stty --" which requests tty settings.

Also, in:

> The form used shall
> consist of one line of text consisting of only printable
> characters from the portable character set, excluding
> whitespace characters, NUL, and all characters that are
> special in the syntax of the sh language
> (`"$&*()[]{};'#~?<>\|).

Since I've added "printable" (with the intention of excluding control characters) and "line of text", the "NUL, " is redundant.

(0005515)
stephane (reporter)
2021-11-03 16:01

Also, on a not totally related note, IMO it's undesirable that stty "$saveterm" should restore the cols and rows settings.

In the now most common case of stty being used inside a terminal emulator in some windowing system, the rows and cols are typically being changed on the master side of the pty pair by the terminal emulator when the window of that emulator is resized.

The almost only use cases of "stty rows y cols x" is to fix those tty settings so they match those of the terminal when they are incorrect.

While the general use case for "stty -g" is so one can temporarily disable local echo or icanon while input is taken from the user. And the user could very well resize their terminal whilst they're being prompted for some input, and you don't want stty "$saveterm" to render "rows" and "cols" incorrect afterwards by restoring cols/rows from before the time the terminal window was resized.

If we allow implementations to restore the saved cols/rows upon stty "$saveterm", that means we now have to write:

{
  saveterm=$(stty -g)
  stty -echo
  printf 'Password: '
  IFS= read -r passwd
  printf '\n'

  restoresize=$(
    stty size | awk '{printf "stty rows %d cols %d", $1, $2}'
  )
  if [ -n "$saveterm" ]; then
    stty "$saveterm" # restore terminal state which may break cols/rows
    eval "$restoresize" # restore terminal size potentially broken by stty above
  fi
} 0<> /dev/tty >&0 2>&0


(which does have a race condition) to prompt for a password instead of just:

{
  saveterm=$(stty -g)
  stty -echo
  printf 'Password: '
  IFS= read -r passwd
  printf '\n'
  if [ -n "$saveterm" ]; then
    stty "$saveterm"
  fi
} 0<> /dev/tty >&0 2>&0
(0005516)
stephane (reporter)
2021-11-03 16:04

Sorry again, yet another typo in my initial submission:

> saveterm=$(stty −g) # save terminal state
> restoresize=$(
> stty size | awk '{printf "stty rows %d cols %d", $1, $2}'
> ) # save terminal size
> stty new settings # set new state
> ...
> [ -n "$saveterm" ] && stty "$saveterm" # restore terminal state
> eval "$ttysize" # restore terminal size


Should be eval "$restoresize"
(0005655)
geoffclare (manager)
2022-02-03 16:47
edited on: 2022-02-03 16:49

On page 3181 line 107953, change the description of the -g option to:
Write to standard output all the current settings, optionally excluding the terminal window size, in an unspecified form that, when stripped of trailing <newline> characters, and used as the one and only argument to another invocation of the stty utility on the same system, attempts to apply those settings to the terminal. The form used shall not contain any sequence that would form an Informational Query, and shall consist of one line of text consisting of only printable characters from the portable character set, excluding white-space characters (other than the terminating <newline>) and these characters that could be altered by pathname expansion performed by the shell: '*', '?', and '['.

On page 3188 line 108251 - 108256 change the example code to:
saveterm=$(stty −g)                       # save terminal state
restoresize=$(
  stty size | awk '{printf "stty rows %d cols %d", $1, $2}'
)                                         # save terminal size
stty new settings                         # set new state
...
[ -n "$saveterm" ] && stty "$saveterm"    # restore terminal state
eval "$restoresize"                       # restore terminal size


(0005659)
kre (reporter)
2022-02-03 19:04

This is a truly insignificant point, but does the example
really need to use awk? (Just to parse 2 numbers).

Wouldn't

restoresize=$(
  stty size | { read r c ; printf 'stty rows %d columns %d' "$r" "$c"; }
)

work just as well? (The $() is a subshell environment, so there's no
issue of the r & c variables polluting the caller's environment -- I prefer
to simply ignore the possibility that readonly vars of those names might
exist as being an issue for the implementor, just as is the possibility that
readonly "saveterm" or "restoresize" vars might already exist.)

Also, since the example shows the output of stty -g used quoted, does it
really need all of the charset restrictions? Implementations don't use
any of the unwanted chars, which permits use of the result unquoted if someone
desires that (and provided they have IFS set to a reasonable value) - but
unless the intent of the standard is to assume the output will be a ':'
separated list of values, and to allow
        IFS=:; for field in $saveterm; do...
to process the data as individual fields, then I don't see a need for the
restrictions. Implementations can of course keep the restricted charset,
and define in more detail the output format, but that's non-portable
implementation specific information. Avoid overspecification.

ps: I'm also not sure I'd show the stty ize save/restore - what effect doing
"stty rows..." should have seems to be debated, with expectations of simply
setting fields for stty to output later, actually altering the size of the
(presumably) virtual terminal to be the size specified, or altering the font
size to make the rows/cols selected fit the current physical size. I'd suggest
simply avoiding that issue here.
(0005661)
geoffclare (manager)
2022-02-04 09:35

> does the example really need to use awk?

The reason for this is stated at the end of the desired action. If at some point we change XBD chapter 5 so that it allows d,i,o,u,x,X conversions to add blanks only from the portable character set, then this could be changed so that it doesn't use awk.

> since the example shows the output of stty -g used quoted, does it really need all of the charset restrictions?

The example uses quotes but the intention is that it can be used without quotes, and there is likely a significant amount of existing code that does so. Quotes are only needed if there are non-whitespace characters in IFS.

- Issue History
Date Modified Username Field Change
2021-11-03 14:15 stephane New Issue
2021-11-03 14:15 stephane Name => Stephane Chazelas
2021-11-03 14:15 stephane User Reference => 0001053
2021-11-03 14:15 stephane Section => stty utility
2021-11-03 14:23 stephane Note Added: 0005513
2021-11-03 14:51 stephane Note Added: 0005514
2021-11-03 14:51 stephane Note Edited: 0005514
2021-11-03 16:01 stephane Note Added: 0005515
2021-11-03 16:04 stephane Note Added: 0005516
2022-02-03 16:47 geoffclare Note Added: 0005655
2022-02-03 16:48 geoffclare Note Edited: 0005655
2022-02-03 16:49 geoffclare Note Edited: 0005655
2022-02-03 16:50 geoffclare Final Accepted Text => Note: 0005655
2022-02-03 16:50 geoffclare Status New => Resolved
2022-02-03 16:50 geoffclare Resolution Open => Accepted As Marked
2022-02-03 16:50 geoffclare Tag Attached: issue8
2022-02-03 19:04 kre Note Added: 0005659
2022-02-04 09:35 geoffclare Note Added: 0005661
2022-02-24 11:52 geoffclare Status Resolved => Applied
2023-05-03 10:32 geoffclare Relationship added related to 0001687


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker