View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001532 | Issue 8 drafts | Shell and Utilities | public | 2021-11-03 14:15 | 2024-06-11 09:12 |
Reporter | stephane | Assigned To | |||
Priority | normal | Severity | Objection | Type | Error |
Status | Closed | Resolution | Accepted As Marked | ||
Product Version | Draft 2.1 | ||||
Name | Stephane Chazelas | ||||
Organization | |||||
User Reference | 0001053 | ||||
Section | stty utility | ||||
Page Number | |||||
Line Number | |||||
Final Accepted Text | 0001532: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 |
related to | 0001687 | Closed | Mismatch between blanks in file formats and default IFS |
|
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. |
|
> 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. |
|
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 |
|
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" |
|
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 |
|
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. |
|
> 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. |
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 | => 0001532: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 |
2024-06-11 09:12 | agadmin | Status | Applied => Closed |