Viewing Issue Advanced Details
1648 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Objection Clarification Requested 2023-03-30 09:34 2023-03-30 09:34
geoffclare
 
normal  
New  
Open  
   
Geoff Clare
The Open Group
1.4 Utility Description Defaults
2339
74433-74444
---
Confusing description of ASYNCHRONOUS EVENTS default behaviour
The default behaviour described for signal handling in the ASYNCHRONOUS EVENTS section of 1.4 Utility Description Defaults is highly confusing because the word "default" is doing multiple jobs.

It also has a list of three items that at first sight seem inter-related, but the list is introduced with "... shall be one of the following", indicating that they are independent choices. By a strict reading, this gives implementations the freedom to do unexpected things (like be terminated by a signal that was inherited as ignored).

In addition, the second list item appears to be redundant as it includes the condition "when no action has been taken to change the default". Since this section is describing the default behaviour, the condition is always true and thus the second item is effectively just a repeat of the first.

Finally, the last paragraph of this section should be conditional on cases where the signal terminates the utility.
Change:
... the action taken as a result of the signal shall be one of the following:
  1. The action shall be that inherited from the parent according to the rules of inheritance of signal actions defined in the System Interfaces volume of POSIX.1-2017.

  2. When no action has been taken to change the default, the default action shall be that specified by the System Interfaces volume of POSIX.1-2017.

  3. The result of the utility's execution is as if default actions had been taken.
A utility is permitted to catch a signal, perform some additional processing (such as deleting temporary files), restore the default signal action (or action inherited from the parent process), and resignal itself.
to:
... the action taken as a result of the signal shall be as follows:
  • If the action inherited from the invoking process, according to to the rules of inheritance of signal actions defined in the System Interfaces volume of POSIX.1-2017, is for the signal to be ignored, the utility shall ignore the signal.

  • If the action inherited from the invoking process, according to to the rules of inheritance of signal actions defined in the System Interfaces volume of POSIX.1-2017, is the default signal action, the result of the utility's execution shall be as if the default signal action had been taken.
When the required action is for signal to terminate the utility, the utility may catch the signal, perform some additional processing (such as deleting temporary files), restore the default signal action, and resignal itself.

There are no notes attached to this issue.




Viewing Issue Advanced Details
1647 [1003.1(2016/18)/Issue7+TC2] System Interfaces Objection Clarification Requested 2023-03-28 16:32 2023-03-30 16:33
eblake
 
normal  
New  
Open  
   
Eric Blake
Red Hat
ebb.printf %lc
fprintf
913
30957
---
printf("%lc", (wint_t)0) can't output NUL byte
In comparing a table of wide vs. narrow print operations, coupled with the NUL byte/character, we have the following surprising table of results:
narrow with narrow: printf("%c", '\0') -> 1 NUL byte
wide with wide: wprintf("%lc", L'\0') -> 1 NUL character
wide with narrow: wprintf("%c", '\0') -> 1 NUL character
narrow with wide: printf("%lc", L'\0') -> 0 bytes

Why? Because "If an l (ell) qualifier is present, the wint_t argument shall be converted as if by an ls conversion specification with no precision and an argument that points to a two-element array of type wchar_t, the first element of which contains the wint_t argument to the ls conversion specification and the second element contains a null wide character.", and printf("%ls", L"") outputs 0 bytes.

Even though ISO C has specified this for more than 23 years, it would make a lot more sense if 0 weren't special-cased as the one wide character you can't print to a narrow stream. Most libc have done the common-sense mapping, and only recently did we learn that musl differed from everyone else in actually obeying the literal requirements of C, leading to this glibc bug report: https://sourceware.org/bugzilla/show_bug.cgi?id=30257 [^]

Since these interfaces defer to the C standard unless explicitly stated otherwise, any change we do here will need to be coordinated with WG14. I recommend that the Austin Group start by filing a ballot defect report against the upcoming C23 recommending that narrow *printf %lc should behave like the other three combinations. At that point, even though Issue 8 will be tied to C17 which has the undesirable semantics, we can use <CX> shading to require POSIX to be in line with what C23 will land on. However, we should not start an interpretation request unless we know for sure how WG14 wants to proceed.
After coordination with WG14, and after applying the change to 0001643, change page 913 line 30957 (fprintf DESCRIPTION for <tt>%c</tt>) from:
If an <tt>l</tt> (ell) qualifier is present, the wint_t argument shall be converted as if by an <tt>ls</tt> conversion specification with no precision and an argument that points to a two-element array of type wchar_t, the first element of which contains the wint_t argument to the <tt>lc</tt> conversion specification and the second element contains a null wide character.
to:
If an <tt>l</tt> (ell) qualifier is present, <CX>the wint_t argument shall be converted to a multi-byte sequence as if by a call to wcrtomb( ) with the wint_t argument converted to wchar_t and an initial shift state, and the resulting bytes written.</CX>
Notes
(0006237)
eblake   
2023-03-28 17:30   
Maybe also add a paragraph to RATIONALE, page 999 line 34005:
The behavior specified for <tt>%lc</tt> conversions differs slightly from the specification in the ISO C standard, in that printing the null wide character produces a NUL byte instead of 0 bytes of output as would be required by a strict reading of the C standard's direction to behave as if applying the <tt>%ls</tt> specifier to a wchar_t array whose first element is the null wide character. Requiring a multibyte output for every possible wide character, including the null character, matches historical practice, and provides consistency with <tt>%c</tt> in fprintf( ) and with both <tt>%c</tt> and <tt>%lc</tt> in fwprintf( ). It is anticipated that a future edition of the C standard will change to match the behavior specified here.
(0006239)
eblake   
2023-03-30 16:33   
As discussed in the 2023-03-30 teleconference (wording may still be subject to change based on feedback, but this captures the consensus of the plan forward). Additionally, the Austin Group plans to file a ballot defect on C23 to WG14.

Interpretation response
------------------------
The standard states that printf("%lc", (wint_t)0) write no bytes, and conforming implementations must conform to this. However, concerns have been raised about this which are being referred to the sponsor.

Rationale:
-------------
The requirement to write no bytes does not match historical practice. However, the requirement derives from the ISO C standard and an attempt to change the requirements in a TC for Issue 7 would introduce a conflict. Therefore this will be addressed in Issue 8 by not deferring to the ISO C standard regarding this behavior.

Notes to the Editor (not part of this interpretation):
-------------------------------------------------------
Change page 909 line 30747 (fprintf DESCRIPTION) from:

    
Excluding dprintf(): The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2017 defers to the ISO C standard.


to:

    
Except for dprintf() and the behavior of the <tt>%lc</tt> conversion when passed a null wide character, the functionality described on this reference page is aligned with the ISO C standard. Any other conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-202x defers to the ISO C standard for all fprintf(), printf(), snprintf(), and sprintf() functionality except in relation to the <tt>%lc</tt> conversion when passed a null wide character.


    
Change page 913 line 30957 (fprintf DESCRIPTION for <tt>%c</tt>) from:
    
If an <tt>l</tt> (ell) qualifier is present, the wint_t argument shall be converted as if by an <tt>ls</tt> conversion specification with no precision and an argument that points to a two-element array of type wchar_t, the first element of which contains the wint_t argument to the <tt>ls</tt> conversion specification and the second element contains a null wide character.

to:
    
If an <tt>l</tt> (ell) qualifier is present, [CX]the wint_t argument shall be converted to a multi-byte sequence as if by a call to wcrtomb( ) with a pointer to storage of at least MB_CUR_MAX bytes, the wint_t argument converted to wchar_t, and an initial shift state, and the resulting byte(s) written.[/CX]


Add a paragraph to RATIONALE, page 920 line 31263:
    
The behavior specified for the <tt>%lc</tt> conversion differs slightly from the specification in the ISO C standard, in that printing the null wide character produces a null byte instead of 0 bytes of output as would be required by a strict reading of the ISO C standard's direction to behave as if applying the <tt>%ls</tt> specifier to a wchar_t array whose first element is the null wide character. Requiring a multibyte output for every possible wide character, including the null character, matches historical practice, and provides consistency with <tt>%c</tt> in fprintf( ) and with both <tt>%c</tt> and <tt>%lc</tt> in fwprintf( ). It is anticipated that a future edition of the ISO C standard will change to match the behavior specified here.




Viewing Issue Advanced Details
1646 [Issue 8 drafts] System Interfaces Objection Omission 2023-03-22 20:44 2023-03-23 10:02
eblake
 
normal  
New  
Open  
   
Eric Blake
Red Hat
ebb.exec at_quick_exit
XSH exec
866
29522
exec*() misses reference to at_quick_exit()
Now that C17 pulled in at_quick_exit(), we need to add that to the list of handlers that are dropped upon successful execl() and friends.
Line numbers from the Austin Group copy of D3_rc1 (may need adjustment depending on the draft being viewed).

At page 866 line 29522 (XSH exec DESCRIPTION), change:
After a successful call to any of the exec functions, any functions previously registered by the atexit( ) or pthread_atfork( ) functions are no longer registered.
to:
After a successful call to any of the exec functions, any functions previously registered by the atexit( ), at_quick_exit( ), or pthread_atfork( ) functions are no longer registered.
Notes
(0006230)
geoffclare   
2023-03-23 10:01   
(edited on: 2023-03-23 10:03)
There is some further inconsistency here that we should consider eliminating. Currently this requirement is stated twice for atexit(), once on the exec page and once on the atexit() page. For at_quick_exit(), bug 0001302 added it on the at_quick_exit() page but not on the exec page. For pthread_atfork() it is only stated on the exec page and not on the pthread_atfork() page.

My suggestion would be to state it only on the exec page for all three in order to avoid duplication. I.e. as well as the desired action, remove the corresponding statements from the atexit() and at_quick_exit() pages.





Viewing Issue Advanced Details
1645 [1003.1(2016/18)/Issue7+TC2] System Interfaces Objection Clarification Requested 2023-03-22 19:47 2023-03-23 10:53
eblake
 
normal  
New  
Open  
   
Eric Blake
Red Hat
ebb.execvp
XSH exec
784
26548
---
execvp( ) requirements on arg0 are too strict
The standard is clear that execlp() and execvp() cannot fail with ENOEXEC (except in the extremely unlikely event that attempting to overlay the process with sh also fails with that error), but must instead attempt to re-execute sh with a command line set so that sh will execute the desired filename as a shell script. Furthermore, the standard is explicit that the original:
execvl(file, arg0, arg1, ..., NULL)

is retried as:
execl(shell path, arg0, file, arg1, ..., NULL)


that is, whatever name was passed in argv[0] in the original attempt should continue to be the argv[0] seen by the sh process that will be parsing file.

But in practice, this does not actually happen on a number of systems. Here is an email describing bugs found in three separate projects (busybox, musl libc, and glibc) while investigating why attempting to rely on what the standard says about execvp() fallback behavior fails on Alpine Linux:
https://listman.redhat.com/archives/libguestfs/2023-March/031135.html [^]

In particular:
1. busybox installs /bin/sh as a multi-name binary, whose behavior DEPENDS on argv[0] ending in a basename of sh. If execvp() actually calls execl("/bin/sh", arg0, file, ...), the binary installed at /bin/sh will NOT see 'sh' as its basename but instead whatever is in arg0, and fails to behave as sh. (Bug filed at https://bugs.busybox.net/show_bug.cgi?id=15481 [^] asking the busybox team to consider installing a minimal shim for /bin/sh that is NOT dependent on argv[0])
2. musl currently refuses to do ENOEXEC handling (a knowing violation of POSIX, but the alternative requires coordinating the allocation of memory to provide the space for the larger argv entailed by injecting /bin/sh into the argument list); see https://www.openwall.com/lists/musl/2020/02/12/9 [^] which acknowledges the issue, where Adélie Linux has patched musl for POSIX compliance but upstream musl does not like the patch. This followup mail surveyed the behavior of various other libc; many use VLA to handle things, but musl argues that VLA is itself prone to bugs https://www.openwall.com/lists/musl/2020/02/13/3. [^] Arguably, musl's claim that execvp() must be safe to use after vfork() can therefore not use malloc() is a bit of a stretch (the standard explicitly documents that execlp() and execvp() need not be async-signal-safe; and even though we've deprecated vfork(), the arguments about what is safe after vfork() roughly correspond to the same arguments about what async-signal-safe functions can be used between regular fork() and exec*()).
3. glibc does ENOEXEC handling, but passes "/bin/sh" rather than arg0 as the process name of the subsequent shell invocation, losing any ability to expose the original arg0 to the script. https://sourceware.org/git/?p=glibc.git;a=blob;f=posix/execvpe.c;h=871bb4c4#l51 [^] shows that the fallback executes is the equivalent to execl("/bin/sh", "/bin/sh", file, arg1, ...)

Admittedly, Linux in general, and particularly Alpine Linux, will intentionally diverge from POSIX any time they feel it practical; but we should still consider whether the standard is too strict in requiring argv[0] to pass through unchanged to the script when the fallback kicks in. And I think the real intent is less about what sh's argv[0] is, and more about what the script's $0 is.

Even historically, FreeBSD used to pass in "sh" rather than preserving arg0, up until 2020: https://cgit.freebsd.org/src/commit/?id=301cb491ea. [^] And _requiring_ arg0 to be used unchanged falls apart when a user invokes execlp("binary", NULL, NULL) (such behavior is non-conforming, since line 26559 states "The argument arg0 should point to a filename string that is associated with the process being started by one of the exec functions.", but a fallback to execl("/bin/sh", NULL, "binary", NULL) obviously won't do what is intended, so the library has to stick something there).

Why don't we see complaints about this more frequently? Well, for starters, MOST people install shell scripts (or even scripts designed for other interpreters) with a #! shebang line. The standard is explicit that this is outside the realm of the standards (because different systems behave differently on how that first line is parsed to determine which interpreter to invoke), but at least on Linux, a script with a #! line NEVER fails with ENOEXEC - that aspect is handled by the kernel. The only time you ever get to a glibc or musl fallback that even has to worry about ENOEXEC is when the script has no leading #! line, which tends to not be common practice (even though the standard seems to imply otherwise). Additionally, most shells don't directly call execvp() - they instead do their _own_ PATH lookup, and then use execl() or similar - if that fails with ENOEXEC, the shell itself can then immediately parse the file contents with the desired $0 already in place, without having to rely on execvp() to try to spawn yet another instance of sh for the purpose.

In playing with this, I note that the as-if rule might permit:

execl("/bin/sh", "sh", "-c", ". quoted_filename", arg0, arg1, ..., NULL)

where quoted_filename is created by quoting the original file in such a way that the shell sees the original name after processing quoting rules (so as not to open a security hole when file contains shell metacharacters) as roughly the same effect as execl("/bin/sh", arg0, file, arg1, ..., NULL) - in that it kicks off a shell invocation that executes commands from the given file while $0 is set to the original name. It additionally has the benefits that it will work on a system with busybox as /bin/sh (because busybox still sees "sh" as argv[0], but also has enough knowledge of what to store into $0 for the duration of sourcing the file). So I went ahead and included a mention of that in non-normative RATIONALE - but we may decide to drop that. Why? Because we took pains in 0000953 to clarify that the dot utility might parse a file as either a program or a compound_list, while the 'sh file arg1' form requires parsing as a program, so it might create an observable difference if this alternative fallback ends up parsing as a compound_list (or we might also decide to tweak the proposed normative text to allow for this difference in parsing). What's more, if musl is already complaining about injecting "/bin/sh" into argv as being hard to do safely given memory constraints after vfork( ), it will be even harder to argue in favor of creating the string ". quoted_filename", which requires even more memory.

In parallel with this, I'm planning to open a bug report against glibc to see if they will consider making the same change as FreeBSD did in 2020 of preserving arg0 to the eventual script. But they may reply that it risks breaking existing clients that have come to depend on the fallback passing $0 as a variant of "sh" rather than the original arg0, therefore my proposal here is to relax the requirements of the standard to allow more existing implementations to be rendered compliant as-is, even though it gives up the nice $0 guarantees.

I also wonder if the standard should consider adding support for 'exec -a arg0 cmd arg1...', which is another common implementation extension in many sh versions for setting argv[0] of the subsequent cmd. That belongs in a separate bug report, if at all. But by the as-if rule, an implementation with that extension might use execl("/bin/sh", "sh", "-c", "exec -a \"$0\" quoted_file \"$@\"", arg0, arg1, ..., NULL) as a way to execute the correct file with the desired $0 even if it can't use the proposed dot trick due to difference in parse scope.
line numbers from Issue 7 + TC2 (POSIX 2017), although the same text appears in draft 3 of issue 8.

At page 784 lines 26552-26557 (XSH exec DESCRIPTION), change:
...the executed command shall be as if the process invoked the sh utility using execl( ) as follows:
<tt>execl(<shell path>, arg0, file, arg1, ..., (char *)0);</tt>
where < shell path > is an unspecified pathname for the sh utility, file is the process image file, and for execvp( ), where arg0, arg1, and so on correspond to the values passed to execvp( ) in argv[0], argv[1], and so on.
to:
...the executed command shall be as if the process invoked the sh utility using execl( ) as follows:
<tt>execl(<shell path>, <name>, file, arg1, ..., (char *)0);</tt>
where < shell path > is an unspecified pathname for the sh utility, < name > is an unspecified process name, file is the process image file, and for execvp( ), where arg1, arg2, and so on correspond to the values passed to execvp( ) in argv[1], argv[2], and so on.


After page 794 line 26981 (XSH exec RATIONALE), add a new paragraph:
When execlp( ) or execvp( ) fall back to invoking sh because of an ENOEXEC condition, the standard leaves the process name (what becomes argv[0] in the resulting sh process) unspecified. Existing implementations vary on whether they pass a variation of "sh", or preserve the original arg0. There are existing implementations of sh that behave differently depending on the contents of argv[0], such that blindly passing the original arg0 on to the fallback execution can fail to invoke a compliant shell environment. An implementation may instead utilize <tt>execl(<shell name>, "sh", "-c", ". <quoted_file>", arg0, arg1, ..., NULL)</tt>, where quoted_file is created by escaping any characters special to the shell, as a way to expose the original $0 to the shell commands contained within file without breaking sh sensitive to the contents of argv[0].
Notes
(0006226)
eblake   
2023-03-22 20:35   
Promised glibc bug at https://sourceware.org/bugzilla/show_bug.cgi?id=30262 [^]
(0006228)
lacos   
2023-03-23 08:11   
It occurs to me that argv[0], as execvp() is currently required to fill it in on the ENOEXEC fallback, could be irrelevant as far as $0 in the shell script is concerned. To recap, the fallback is

  execl(<shell path>, arg0, file, arg1, ..., (char *)0);

Now if you compare that with the "sh" utility's specification, it seems to correspond to the *sole* synopsis form where the "command_file" operand is provided.

And then the spec states (in the description of the "command_file" operand), "Special parameter 0 [...] shall be set to the value of command_file". This means that argv[0] will never be visible to the script, only to the shell executable.

(The next question is of course if the shell executable cares about argv[0]. BusyBox does.)

This suggests that

- the normative section (description) should indeed be relaxed as Eric says,

- the rationale need not recommend either "exec -a" or "sh -c", because $0 is already well specified.
(0006231)
bastien   
2023-03-23 10:53   
@eblake dash does not support exec -a ...




Viewing Issue Advanced Details
1644 [1003.1(2016/18)/Issue7+TC2] System Interfaces Comment Enhancement Request 2023-03-22 09:52 2023-03-23 16:42
bastien
 
normal  
New  
Open  
   
Bastien Roucaries
debian
dlsym - get the address of a symbol from a symbol table handle
Application usage
all
---
void * to function pointer is described in annex J of C standard (informative).
Standard say
  Note that conversion from a void * pointer to a function pointer as in:

   fptr = (int (*)(int))dlsym(handle, "my_function");

  is not defined by the ISO C standard. This standard requires this conversion to work correctly on conforming implementations.
J.5.7 Function pointer casts
1 A pointer to an object or to void may be cast to a pointer to a function, allowing data to
be invoked as a function (6.5.4).
2 A pointer to a function may be cast to a pointer to an object or to void, allowing a
function to be inspected or modified (for example, by a debugger) (6.5.4).
It is not true, this behavior is described in J - Portability issues, §J.5.7 Function pointer cast (informative)

Add a note that POSIX conforment compiler should implement §J.5.7 Function pointer casts
1 A pointer to an object or to void may be cast to a pointer to a function, allowing data to
be invoked as a function (6.5.4).
2 A pointer to a function may be cast to a pointer to an object or to void, allowing a
function to be inspected or modified (for example, by a debugger) (6.5.4).
Notes
(0006220)
wlerch   
2023-03-22 13:24   
Requiring §J.5.7 is overkill. Requiring support for calling into data, or examining code as data, sounds like asking for all sorts of security issues.

All that is needed to have a working dlsym() is that a void* pointer returned by a dlsym() call that names a function, and no other void* pointer, can be safely converted to the correct function type and called. This can be achieved without opening up the entire address space for accessing data as code and code as data, as would be required by §J.5.7.
(0006222)
bastien   
2023-03-22 15:15   
@wlerch I perfectly understand your remark, nevertheless could we reformulate like this:

the returned pointer of dlsym() may be cast to a pointer to a function, allowing data to
be invoked as a function. Posix system should respect §J.5.7.1 of ISO C standard for the pointer returned by dlsym()

I want in fact to use the same wording between C standard and POSIX.
(0006223)
wlerch   
2023-03-22 15:43   
Why? The same wording would mean the same requirements, wouldn't it? Why would you want to impose unnecessary requirements that lead to potential security risks?

dlsym does not need to allow data to be invoked as a function. The pointer returned by it does not need to point to data. The only requirement that is necessary is that it can be converted to a pointer to function, resulting in a pointer that can be used to call the function.
(0006224)
bastien   
2023-03-22 16:10   
Ok understood your point

may be:
a void* pointer returned by a dlsym() call that names a function, can be safely converted to the correct function type and called.
(0006225)
wlerch   
2023-03-22 18:43   
I like the text suggested in 0000074


dlsym()'s return value, cast to a pointer to the type of the symbol, may be used to call (in case of a function) respectively access (in case of a [data] object) the symbol.


But it should say "converted", not "cast".

And it could just say that result of the conversion will point to the object or function, and let C define what such a pointer can then be used for.

I am not a big fan of the existing text saying that "if name names a function identifier, dlsym() shall return the address of the function converted from type pointer to function to type pointer to void". It's not the job of POSIX to specify how an implementation of dlsym() must produce the void* value to return, and it makes particularly little sense to insist that it must use a conversion that has undefined behaviour in standard C.

Saying later that a different conversion, from the void* pointer to a function pointer, is required to "work correctly" does not really fix that.
(0006229)
geoffclare   
2023-03-23 09:39   
> I like the text suggested in 0000074
>
> dlsym()'s return value, cast to a pointer to the type of the symbol, may be
> used to call (in case of a function) respectively access (in case of a [data]
> object) the symbol.

This was added to the standard, with minor wording changes, at line 25417:
The return value from dlsym(), cast to a pointer to the type of the named symbol, can be used to call (in the case of a function) or access the contents of (in the case of a data object) the named symbol.

> But it should say "converted", not "cast".

I suspect the text says "cast" for the thing the application does because trying to do the conversion without a cast would cause C compilers to produce a diagnostic. (It can just say "converted" for the thing the implementation does because how it does that is internal implementation detail.)
(0006232)
wlerch   
2023-03-23 13:47   
(edited on: 2023-03-23 13:52)
Ah, right, in the Description, somehow I didn't look there, thanks. :)

Regarding "cast", no, a conversion without a cast would not necessarily produce a diagnostic -- a diagnostic is not required if the target type is a pointer to an object type. If the text said "converted", it would be up to the reader to figure out from the rules of C when a cast is necessary to prevent a diagnostic; but since it says "cast", it might make a pedantic reader wonder if it means to say that an explicit cast is indeed required, even in cases where an assignment without a cast would be just as good as far as standard rules of C are concerned.

I suspect the real reason it says "cast" is because a lot of people refer to any conversion as a "cast" and a cast as an "explicit cast". I think it's common enough to be tolerable in less formal contexts, but in a formal document such as this it would be better to use terms defined in the C standard consistently with how they're defined there.

(0006233)
geoffclare   
2023-03-23 14:02   
> a diagnostic is not required if the target type is a pointer to an object type

Of course you're right. In my mind I was replying in the context of the named symbol being a function, but I neglected to state that condition.

> I suspect the real reason it says "cast" is because a lot of people refer to any conversion as a "cast" and a cast as an "explicit cast".

If that were the reason, I would expect the related text in RETURN VALUE to say "cast" as well.
(0006234)
wlerch   
2023-03-23 14:45   
> In my mind I was replying in the context of the named symbol being a function, but I neglected to state that condition.

But my point is that the text in the standard does not state that condition either. Yes, trying to do the conversion without a cast would sometimes cause C compilers to produce a diagnostic, but other times it would not, so that does not sound like a good reason to have a wording that can be interpreted as implying that a cast is always required.

> > I suspect the real reason it says "cast" is because a lot of people refer to any conversion as a "cast" and a cast as an "explicit cast".
> If that were the reason, I would expect the related text in RETURN VALUE to say "cast" as well.

The text that says "cast" was added after the text in RETURN VALUE was already there, wasn't it? It wouldn't make a lot of sense to adjust the existing text that was already using the more accurate "conversion" to use the less accurate "cast" instead, just because new text using "cast" was being added. I think would have been better to adjust the new text to use the more accurate "conversion" and be more consistent with the existing text, but if it was done by someone who thought of "cast" as a synonym for "conversion", I can understand why they would not have bothered.

Anyway, investigating the reasons and motives behind the existing text is probably not quite as important as figuring out whether the existing text is sufficient or deserves some changes, is it?...
(0006235)
geoffclare   
2023-03-23 16:42   
> The text that says "cast" was added after the text in RETURN VALUE was already there, wasn't it?

No, all of the wording about casting and conversion is from bug 0000074.

> Anyway, investigating the reasons and motives behind the existing text is
> probably not quite as important as figuring out whether the existing text is
> sufficient or deserves some changes

Indeed.




Viewing Issue Advanced Details
1643 [1003.1(2016/18)/Issue7+TC2] System Interfaces Editorial Error 2023-03-21 11:13 2023-03-21 15:44
bhaible
 
normal  
New  
Open  
   
Bruno Haible
GNU
fprintf
913
30960
---
fprintf %lc: wrong reference to the current conversion specification
The reference to "the wint_t argument to the ls conversion specification" makes no sense, since an ls conversion specification takes a wchar_t* argument.

In ISO C 99 this paragraph reads
"If an l length modifier is present, the wint_t argument is converted as if by
an ls conversion specification with no precision and an argument that points
to the initial element of a two-element array of wchar_t, the first element
containing the wint_t argument to the lc conversion specification and the
second a null wide character."

So, apparently POSIX and ISO C 99 are based on a common ancestor document, and the reference to "ls" has been corrected in ISO C 99, i.e. changed to "lc".
Change "the wint_t argument to the ls conversion specification" to "the wint_t argument to the lc conversion specification".
Notes
(0006214)
eblake   
2023-03-21 15:44   
For my own reference as much as anything else, Bruno found this while reporting a corner-case bug in glibc's printf(): https://sourceware.org/bugzilla/show_bug.cgi?id=30257 [^]
and which he found to be also present in most other tested libc except musl.

Namely, narrow printf("%lc", (wint_t)0) is surprisingly required to produce 0 bytes instead of the multibyte sequence for the null character, because that is the behavior of %ls with no precision when handed a wchar_t array with a null character in the first index; and this behavior is both different than the wprintf behavior, and from the %c behavior with a NUL byte.




Viewing Issue Advanced Details
1642 [1003.1(2016/18)/Issue7+TC2] Base Definitions and Headers Editorial Clarification Requested 2023-03-19 09:10 2023-03-22 09:47
bastien
 
normal  
New  
Open  
   
Bastien Roucaries
debian
any
any
any
---
DUMB terminal is not defined
Hi,

They are no definition of a dumb terminal used in vi and ed pages.

- Define that is a dumb terminal
- Define how to detect a dumb terminal
Notes
(0006213)
geoffclare   
2023-03-21 12:10   
(edited on: 2023-03-21 13:19)
There is only one use of "dumb" in normative text, which is in the description of the redraw edit option (P2739 L89670).

In the description of the -s option, the phrase "the terminal is a type incapable of supporting open or visual modes" is used instead and the rationale explains "The terminal type ``incapable of supporting open and visual modes'' has historically been named ``dumb''". Given that this statement exists, I don't see any problem with the use of "dumb terminal" elsewhere in non-normative text.

Proposed change:

On page 2739 line 89670 section ex, change:
The editor simulates an intelligent terminal on a dumb terminal.
to:
If redraw is set and the terminal is a type incapable of supporting open or visual modes, the editor shall redraw the screen when necessary in order to update its contents.


(0006218)
bastien   
2023-03-22 09:47   
Thanks,

Will prefer something like:
On page 2739 line 89670 section ex, change:

    The editor simulates an intelligent terminal on a dumb terminal.

to:

    If redraw is set and the terminal is a type incapable of supporting open or visual modes (this terminal has historically been named ``dumb''"), the editor shall redraw the screen when necessary in order to update its contents.




Viewing Issue Advanced Details
1641 [1003.1(2016/18)/Issue7+TC2] System Interfaces Editorial Clarification Requested 2023-03-18 07:52 2023-03-30 15:22
bastien
 
normal  
Resolved  
Accepted As Marked  
   
Bastien Roucaries
debian
sys/socket.h
Application usage
sockaddr_storage
---
see Note: 0006238
sockaddr_storage is not alias safe
 sockaddr_storage was designed back when strict aliasing wasn’t a problem.

 Back then, one would define a variable of that type, and then access it as any of the other sockaddr_* types, depending on the value of the first member. This is Undefined Behavior.

However, there is no
way to use these APIs without invoking Undedfined Behavior, either in
the user program or in libc, so it is still recommended to use this
method. The only correct way to use different types in an API is
through a union.

Exemple of safe use
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stddef.h>

union sockaddr_mayalias {
  sa_family_t ss_family;
  struct sockaddr sock;
  struct sockaddr_storage storage;
  struct sockaddr_in in;
  struct sockaddr_in6 in6;
  struct sockaddr_un un;
};
  
int main() {
  union sockaddr_mayalias sa = {};
  socklen_t addrlen = sizeof(sa);
  if(getsockname(STDIN_FILENO, &sa.sock, &addrlen) < 0) {
    perror("getsockname");
    return 1;
  }
  if(addrlen >= sizeof(sa)) {
    errno = EPROTONOSUPPORT;
    perror("getsockname return a not supported sock_addr");
    return 1;
  }
  
  switch(sa.ss_family) {
  case(AF_UNSPEC):
    printf("AF_UNSPEC socket\n");
    break;
  case(AF_INET):
    {
      char s[INET_ADDRSTRLEN];
      in_port_t port = ntohs(sa.in.sin_port);
      if (inet_ntop(AF_INET, &(sa.in.sin_addr), s, sizeof(s)) == NULL) {
    perror("inet_ntop");
    return 1;
      }
      printf("AF_INET socket %s:%i\n",s,(int)port);
      break;
    }
  case(AF_INET6):
    {
      char s[INET6_ADDRSTRLEN];
      in_port_t port = ntohs(sa.in6.sin6_port);
      if (inet_ntop(AF_INET6, &(sa.in6.sin6_addr), s, sizeof(s)) == NULL) {
    perror("inet_ntop");
    return 1;
      }
      printf("AF_INET6 socket %s:%i\n",s,(int)port);
      break;
    }
  case(AF_UNIX):
    if(addrlen == sizeof(sa_family_t)) {
      printf("AF_UNIX socket anonymous\n");
      break;
    }
    /* abstract */
    if(sa.un.sun_path[0]=='\0') {
      printf("AF_UNIX abstract socket 0x");
      for (int i = 0; i < (addrlen - sizeof(sa_family_t)); ++i)
    printf("%x",sa.un.sun_path[i]);
      printf("\n");
      break;
    }
    /* named */
    printf("AF_UNIX named socket ");
    for (int i=0; i < strnlen(sa.un.sun_path, addrlen - offsetof(struct sockaddr_un, sun_path));++i)
      printf("%c",sa.un.sun_path[i]);
    printf("\n");
    break;
  default:
      errno = EPROTONOSUPPORT;
      perror("socket not supported");
      return 1;
}

    
}
1. document aliasing problem
2. define sockaddr storage as:
struct sockaddr_storage {
        union {
                sa_family_t ss_family;
                struct sockaddr sa;
                struct sockaddr_in sin;
                struct sockaddr_in6 sin6;
                struct sockaddr_un sun;
                struct _sockaddr_padding padding;
        };
};
Notes
(0006207)
bastien   
2023-03-18 07:53   
Please note that function that pass sockaddr * instead of void may suffer of the same aliasing problem
(0006208)
wlerch   
2023-03-20 13:20   
A general note: just because C considers something undefined behaviour does not mean that POSIX can't define it. For example, using dlsym() to return a pointer to a function involves a conversion that C considers undefined, but POSIX requires it to work. It just means that POSIX specifies some additional requirements on compilers that C does not.

Of course, it is probably a good idea to try to keep such additional requirements to a minimum, and mention them explicitly, like the dlsym() page does.
(0006209)
bastien   
2023-03-20 13:38   
yes I should be documented at least.

Using a __attribute__((__may_alias__)) for the struct attribute will help here, but it is I think simpler to use the plan 2 that is safe and backward compatible.

For the *sockaddr problem for int getpeername, I do not know the safe path.

transparent_union is a solution but it is not always implemented.
(0006211)
steffen   
2023-03-20 23:06   
The famous Dennis Ritchie 7753@alice.UUCP quote from Article 7844 of comp.lang.c:
 
 The fundamental problem is that it is not possible to write real programs using the X3J11 definition of C. The committee has created an unreal language that no one can or will actually use.

Also the July 15, 2019 LWN.net "Who's afraid of a big bad optimizing compiler?"

Other than that ISO C99 does not know about unnamed unions.
ISO C89 that i comply to as far as possible (a hundred percent with the help of some support macros) also does not.

  (Not to mention that terrible tremendous breath-taking gcc (g++) 3.4.2 bug which did not like unnamed unions and caused real pain on my side.)
(0006212)
hvd   
2023-03-21 12:01   
Re Note: 0006211: That famous quote is about something that was proposed to be part of the standard but ended up being removed before C90 and is not part of any version of the C standard. The sentence that follows that quote would have made that beyond obvious. I highly suspect you are well aware of this and left out that following sentence deliberately.
(0006215)
sam_james   
2023-03-21 23:09   
This was discussed extensively recently on the libc-alpha and gcc mailing lists at https://sourceware.org/pipermail/libc-alpha/2023-February/145304.html [^] which was the motivation for this defect report.
(0006216)
steffen   
2023-03-21 23:33   
I'd very much prefer if there would be an exception like there is one for dlsym, like wlerch has shown in #0006208.

Anything else seems to be a road to madness, as sockaddr_storage is required by the standard (and by real life, mind you) to be correctly aligned for any other socket address type, and then you should be able to cast -- _without_ going over an intermediate (char*), or (char*)(void*), or whatever they want to be done .. to get it done.

Anyway this issue is opened against the wrong standard, because this POSIX bases upon ISO C99, and ISO C99 does not support unnamed unions. Voila.


P.S.: since my C can be compiled with C++ i am still frustrated after more than two decades to have the necessity to use C-style casts to assign to some "virtual table" function pointers, instead of even reinterpret_cast<>.
You know, if i have xy_clone() i want and need to assign it to (*y_clone), and i do so for almost the quarter of a century, and it works. (I assign a function pointer, though mismatch -- the generic vtbl uses void*, say.)
Now compilers complain on the use of "old-style" casts, and i am afraid someday they close the door without replacement. Then i stop flying over that coockoo thing.
Just my one cent.
(0006217)
bastien   
2023-03-22 09:42   
@steffen do not supporting aliasing in general will be no way from compiler folk...

And it is not the wrong standard, the problem is for historical reason socket API pass struct sockaddr* and not void *.

Using void * will have avoided this issue.

the __attribute__((__may_alias__)) is a common C extension and will solve this problem.

Transparent union is also a common supported extension.

May be a safe path will be:
1. Prefered option struct sockaddr and struct sockaddr_storage may alias other structure
2. If compiler does not support this common extension, aliasing should be disabled
(0006227)
steffen   
2023-03-22 21:56   
No. "Issue 8 drafts" is maybe the right standard.

I say maybe. I personally am the wrong person to talk to, i hate this aliasing issue, i saw so-and-so many *BSD and more commits fly by where code that worked started breaking, and had to be circumvented by doing memcpy(), sheer grazy.

They _broke_ the system. And i am yet to see the advantages. (From my simple userspace programmer's point of view, with a bit of assembler, in earlier times.)
So if an intermediate cast to "char*" gets you going, or "void*", why do that at all?
It _will_ fit in the size of sockaddr_storage, it will have the proper alignment, i want to cast it. Period.

"POSIX-compliant compilers" (-std=c99) should not fail in theory.
Issue 7 is based upon ISO C99.
(0006238)
eblake   
2023-03-30 15:20   
On page 386 line 13115 section <sys/socket.h> DESCRIPTION, change:
When a pointer to a sockaddr_storage structure is cast as a pointer to a sockaddr structure, the ss_family field of the sockaddr_storage structure shall map onto the sa_family field of the sockaddr structure. When a pointer to a sockaddr_storage structure is cast as a pointer to a protocol-specific address structure, the ss_family field shall map onto a field of that structure that is of type sa_family_t and that identifies the protocol’s address family.
to:
When a pointer to a sockaddr_storage structure is cast as a pointer to a sockaddr structure, or vice versa, the ss_family field of the sockaddr_storage structure shall map onto the sa_family field of the sockaddr structure. When a pointer to a sockaddr_storage structure is cast as a pointer to a protocol-specific address structure, or vice versa, the ss_family field shall map onto a field of that structure that is of type sa_family_t and that identifies the protocol’s address family. When a pointer to a sockaddr structure is cast as a pointer to a protocol-specific address structure, or vice versa, the sa_family field shall map onto a field of that structure that is of type sa_family_t and that identifies the protocol’s address family. Additionally, the structures shall be defined in such a way that these casts do not cause the compiler to produce diagnostics about aliasing issues when compiling conforming application (xref to XBD section 2.2) source files.


On page 390 line 13260 section <sys/socket.h> APPLICATION USAGE, append a sentence:
Note that this example only deals with size and alignment; see RATIONALE for additional issues related to these structures.


On page 390 line 13291 section <sys/socket.h>, change RATIONALE from "None" to:
Note that defining the sockaddr_storage and sockaddr structures using only mechanisms defined in editions of the ISO C standard prior to the 2011 edition (C11) may produce aliasing diagnostics when used in C11 and later editions of the ISO C standard. Because of the large body of existing code utilizing sockets in a way that was well-defined in the 1999 edition of the ISO C standard (C99) but could trigger undefined behavior if C11/C17 aliasing detection were enforced, this standard mandates that casts between pointers to the various socket address structures do not produce aliasing diagnostics, so as to preserve well-defined semantics. An implementation's header files may need to use anonymous unions, or even an implementation-specific extension such as a <tt>[[__may_alias__]]</tt> attribute, to comply with the requirements of this standard.




Viewing Issue Advanced Details
1640 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Objection Error 2023-03-12 07:00 2023-03-16 15:55
kre
 
normal  
Resolved  
Accepted As Marked  
   
Robert Elz
XCU 3 / true
3318
111745 - 111748
---
Note: 0006206
The rationale given for retaining "true" is nonsense.
The RATIONALE section of the page for the "true" utility says:

    The true utility has been retained in this volume of POSIX.1-2017,
    even though the shell special built-in : provides similar functionality,
    because true is widely used in historical scripts and is less cryptic to
    novice script readers.

That text remains unchanged in Issue 8 draft 2.1

The functionality is only vaguely similar, true is a normal utility, ':' is
a special builtin, hence the consequences of redirection errors are
different, and use, redirections are used with these utilities.

Further, the OPERANDS listed for "true" are "None" which XCU 1.4 says
means "When this section is listed as ``None.'', it means that the
implementation need not support any operands.", which allows an
implementation to do things with operands if it wants, including issueing
an error message failing (turning info "false"). While none do, that I
am aware of (true is generally, and entirely, "exit 0" or "exit(0)" in C)
it is possible.

Finally, since this bug is being submitted against Issue 7 TC2,
XCU 2.9.1.1 bullet point 'd' says:

     If the command name matches the name of the type or ulimit utility,
     or of a utility listed in the following table, that utility shall be
     invoked.

Note "shall be invoked" and "true" is in the table. If there were no
"true" utility, that would be impossible, so deleting true really could
not have happened (back then) no matter how redundant it seemed to be.

Note that in Issue 8 draft 2.1, this has altered, it is now 2.9.1.4
(still bullet point d) but that now refers to the intrinsic utilities
defined in XCU 1.7, and "true" is not in that list.
Delete the entire RATIONAL section (lines 111746 - 111748) and replace
them with
None.

Notes
(0006202)
stephane   
2023-03-12 16:54   
GNU true accepts some --version, --help options.

I don't have access to ksh93 just now but I'd expect its true to supports those as well as --author --man --usage and many more in that vein like most of its builtins do.
(0006206)
geoffclare   
2023-03-16 15:54   
On page 3317 line 111737 section true (APPLICATION USAGE), change:
The special built-in utility : is sometimes more efficient than true.
to:
Although the special built-in utility : (colon) is similar to true, there are some notable differences, including:

  • Whereas colon is required to accept, and do nothing with, any number of arguments, true is only required to accept, and discard, a first argument of "--". Passing any other argument(s) to true may cause its behavior to differ from that described in this standard.

  • A non-interactive shell exits when a redirection error occurs with colon (unless executed via command), whereas with true it does not.

  • Variable assignments preceding the command name persist after executing colon (unless executed via command), but not after executing true.

  • In shell implementations where true is not provided as a built-in, using colon avoids the overheads associated with executing an external utility.

On page 3318 line 111746 section true, replace the contents of RATIONALE with:
None.

On page 3318 line 111752 section true, add colon and command to SEE ALSO.

On page 2389 line 76461 section colon, change APPLICATION USAGE from:
None.
to:
See the APPLICATION USAGE for true.

On page 2390 line 76479 section colon, add true to SEE ALSO.




Viewing Issue Advanced Details
1639 [Issue 8 drafts] Base Definitions and Headers Objection Clarification Requested 2023-03-05 06:57 2023-03-16 15:48
kre
 
normal  
Resolved  
Accepted As Marked  
   
Robert Elz
XBD 8.3 TZ
162
5643-5644
Note: 0006205
Clarify minimun length requirement of "quoted" std and dst names in POSIX TZ string.
In the description of the POSIX TZ string, in the XBD 8.3 section that
describes the TZ variable, it says:

std and dst Indicate no less than three, nor more than {TZNAME_MAX},
                  bytes that are the designation for the standard (std)

and that's fine, then in the description of the quoted form encoding
of those fields, we have:

Each of these fields may occur in either of two formats quoted or
unquoted:

     -- In the quoted form, the first character shall be the <less-
        than-sign> ('<') character and the last character shall be
        the <greater-than-sign> ('>') character.

That's fine too.

Then the description (after text about the allowed chars, not relevant
here) it concludes:

        The std and dst fields in this case shall not include the
        quoting characters.

And that is OK too, so if we had
        TZ='<+0700>-7'
that would be OK, and the tzname for standard time would be +0700
(with an offset 7 hours ahead of UTC) with the '<' and '>' chars
not included (and no summer time applies).

That's all fairly straight forward.

However, it turns out there is an ambiguity there (or at least it
seems like there is).

The way I read this, is that the std (and dst if given) fields must
be 3 bytes long (at least - forget the max for now), and those 3
bytes can include the '<' and '>' chars, which would make

        TZ='<Z>0'

also acceptable. That is, I read the sentence:

        The std and dst fields in this case shall not include the
        quoting characters.

as meaning that the names extracted from the std and dst fields
don't include the quote characters (and for convenience they're
still called "std" and "dst" as the rest of the text refers to
them that way) - the "minimum 3 bytes" test has already been
satisfied.

Others apparently read that as if it said "when quoted, the minimum
length of the field is 5 bytes, including the quotes, leaving at
least 3 bytes for the extracted name."

It was even claimed that POSIX requires tzname (timezone name
abbreviations -- no-one has ever invented a good term to use to
refer to these things) fields to be at least 3 chars (bytes) long,
because of this rule.

But that's clearly not the case, as in the ':' form (or in the
new "geographic/special" form added by 0001619 there is no
such requirement, it is all implementation defined. Nothing I
can find elsewhere (which doesn't mean it doesn't exist) places
any limits (minimum, maximum, or allowed characters) upon those
values, the limits are there only for the sake of parsing the
POSIX TZ string.

Note that if I am incorrect, and the intent really was to require
at least 3 bytes between the '<' '>' quoting characters, then
first, why? And second that must mean that, assuming
TZNAME_MAX=10 (no idea if it is allowed to be or not, I am picking
10 because strlen("TZNAME_MAX") == 10, then
        TZ='<TZNAME-MAX>12'
would be a legitimate TZ string, where here there are 12 chars
(that is, more than TZNAME_MAX) in the "std" field as it first
appears. [Aside: the change in the example from '_' to '-' was
deliberate, '-' is an allowed character there, '_' probably is
not].

Note the "Why?" there is not rhetorical, an implementation can
choose to accept
        TZ=':<Z>0'
as a legitimate TZ string (because of the ':' the format is
implementation defined) producing a one character tzname (abbreviation),
in this particular case, it isn't even an odd thing to want to do.
That is, applications need to deal with short tzname (tm_zone) values
anyway, restricting the normal quoted format to prevent it seems kind
of petty.

The unquoted form I understand, that has been around since the
dark ages, and 3 char (3 byte) abbreviations were what it initially
allowed - altering that would be hard. The quoted form is much
newer (and far less commonly used).
Change the sentence in XBD 8.3 TZ variable description,
on page 162 of I8 D2.1, lines 5643-4, from:

The std and dst fields in this case
shall not include the quoting characters.

to be:
The tzname abbreviations obtained from the std
and dst fields in this case shall not include the
quoting characters, but shall be referred to as the std
or dst fields, as appropriate, throughout the remainder
of this specification, the requirement that the fields be at
least 3 bytes long applies to the quoted form, the minimum length
after the quoting characters have been removed is 1 byte.


There is no need to say anything about the maximum length of
the quoted fields, as removing the '<' and '>' cannot make
them become longer, only shorter.

If this is not to be the intent of the standard (again, why?)
then after the sentence quoted above (lines 5643-4 on page 162
of I8 D2.1) add a new sentence.

Note: In this case, the quoted std, and
dst (if present) fields shall have a minimum length
of 5 bytes, and a maximum length of {TZNAME_MAX}+2 bytes.


But why?
Notes
(0006189)
kre   
2023-03-05 07:01   
(edited on: 2023-03-05 07:03)
In the above Desired action, I somehow managed to enter < em >
where I meant to put < /blockquote >

The spell checker did not catch that (yes, I used one this time!)

(0006190)
Don Cragun   
2023-03-05 07:44   
The mismatched < em > has been replaced by < /blockquote >. The matched < em > < /em > pairs have been replaced by the more common < i > < /i > pairs.
(0006191)
eggert   
2023-03-05 10:15   
As I noted in the tz mailing list (see the second half of <https://mm.icann.org/pipermail/tz/2023-March/032629.html>), [^] current GNU/Linux, macOS, AIX, and Solaris all require at least three bytes in 'std' and 'dst' (not counting the quoting characters) for proper results, and requiring support for TZ='<Z>0' would invalidate the current implementation of these systems.

Assuming the idea is to standardize existing practice, POSIX should simply require at least three bytes in 'std' and 'dst', not counting any quoting characters. That way, existing systems would continue to conform.

The main argument for invaliding existing implementations is the possibility that the US Congress might require "permanent DST", and that the common abbreviation for US Eastern time might become "ET" (instead of "EST" or "EDT" each of which would become confusing). If we're concerned that this needs to be addressed in POSIX now just in case, then the minimum lengths for 'std' and 'dst' should indeed be shrunk to 2 bytes (or to 1 byte; why stop at 2?). However, if such a change is made the minimum length should be computed after quoting chars are removed, so that (for example) TZ='ET4' should act like TZ='<ET>4' for the hypothetical Eastern Time.
(0006205)
geoffclare   
2023-03-16 15:39   
Change:
The std and dst fields in this case shall not include the quoting characters.
to:
The std and dst fields in this case shall not include the quoting characters and the quoting characters do not contribute to the three byte minimum length and {TZNAME_MAX} maximum length.




Viewing Issue Advanced Details
1638 [Issue 8 drafts] Base Definitions and Headers Objection Clarification Requested 2023-03-03 10:03 2023-03-16 15:27
kre
 
normal  
Resolved  
Accepted As Marked  
   
Robert Elz
XBD 8.3
162
5648-5651
See Note: 0006204.
Requirement that TZ "std" and "dst" be 3 chars long (when given) is apparently ambiguous
This could be filed against 7 TC2, and I think probably D3 (when it
appears as well) - I don't think the text has changed.

It wasn't changed by 0001619 though perhaps should have been.

The current (as in D2.1) text says:

   The interpretation of these fields is unspecified if either field is
   less than three bytes (except for the case when dst is missing),

To me that was always clear enough, it means that "dst" doesn't have to be
at least 3 chars, if it was omitted, that would be absurd. But on a (unrelated) mailing list, I have just seen a claim:

   When /dst/ is missing, /std/ can be less than 3 bytes.

which is obviously based upon reading that "except" as applying to both
"std" and "dst" rather than just "dst" which I have always assumed.

And when the text is read, without already having a preconceived idea of
what it is intended to mean, I can see how that interpretation is possible.

Beyond that, for all parts of the POSIX TZ strip specification, now that
0001619 has been applied, we really need to remove all "is unspecified"
in invalid cases - those should now be simply invalidating the string as
being considered as a POSIX TZ string, leaving it open to be considered as
one of the new form added by 0001619.

That part I am not going to supply new text for here, that can wait until
after D3 is available, when we know what we're working with.
Replace the paragraph in lines 5648-5651 (D2.1) on page 162

The interpretation of these fields is unspecified if either
field is less than three bytes (except for the case when dst is missing),
more than {TZNAME_MAX} bytes, or if they contain characters
other than those specified.


with (something like - and here I am making the working, for just this one
case for now, invalidate the string, as being a POSIX TZ string):

If std contains less than 3 bytes, or dst
(if present in the string) contains less than 3 bytes, or if either
std or dst contain more than {TZNAME_MAX} bytes, or
if either of those fields contains any characters other than those
specified, the string will not be a valid string of this format, and
shall be considered as a candidate for being of the third format.


(Yes, I know, that's ugly - someone else can do better...)
Notes
(0006187)
kre   
2023-03-03 10:11   
Rather than "not be a valid string of this format, and
shall be considered as a candidate for being of the third format."
maybe it could say something like

"shall be a failure to match the syntax of this format" which then
fits with the text added in Note: 0006073
(0006188)
Don Cragun   
2023-03-03 14:31   
Occurrences of "bugno:" and "POSIZ" in the Description have been changed to "bugid:" and "POSIX", respectively.
(0006204)
Don Cragun   
2023-03-16 15:26   
Change:
The interpretation of these fields is unspecified if either field is less than three bytes (except for the case when dst is missing), more than {TZNAME_MAX} bytes, or if they contain characters other than those specified.
to:
The interpretation of std and, if present, dst is unspecified if the field is less than three bytes or more than {TZNAME_MAX} bytes, or if it contains characters other than those specified.




Viewing Issue Advanced Details
1637 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Objection Clarification Requested 2023-02-27 17:17 2023-03-13 15:53
nick
 
normal  
Resolved  
Accepted As Marked  
   
Nick Stoughton
Logitech
command
2596
84263-84266
---
Note: 0006203
The command utility does not execute aliases
The description of command with no options given states:

If the command_name is the same as the name of one of the special built-in utilities, the special
properties in the enumerated list at the beginning of Section 2.14 (on page 2384) shall not occur.
In every other respect, if command_name is not the name of a function, the effect of command
(with no options) shall be the same as omitting command.

This suggests that
alias x=ls
command x

should run the alias "x". No existing shell or implementation of the "command" utility I have found does this, but instead says that "x is not found" (in some form).
In D2.1, page 2553, line 83836, change

... if command_name is not the name of a function,

to

... if command_name is not the name of a function or alias,
Notes
(0006180)
kre   
2023-02-27 18:55   
Yet another case where we would be far better off if the standard
had no aliases.

No surprise that no shells do what the text kind of looks like it
expects, as aliases would have been processed long before the
"command" command is executed - if one wanted to have "command"
apply to aliases (alias values) as well, one could do

alias command='command '

which would expand a following alias after command (as part of lexical
processing) if one appears there.

Without that, "command" is the word in the command word position, if that
is not an alias, no further words get checked to see if they are, until the
next command word position (which the following word is not, nor is it in
"exec word", xargs word, env word, ... though it can be in "eval word" as
that word is subject to lexical processing (to be tokenised).

The desired action is not adequate however, as it gives no clue what should
happen in the case in question. When the word after "command" is a function,
earlier text says what happens, but nothing does if it is an alias.

However, I agree that as long as aliases remain in POSIX, the text there
needs to be clearer.

I'd suggest something more like adding to the end of the sentence in
question

except that command_word does not appear in the command word
position in the command command, hence is not subject to alias or
reserved word lookups.


Note that command also suppresses reserved words, "command if ..." runs the
"if" command (from the filesystem, since command suppresses function lookups,
a function named "if" can't be run this way, even in shells that allow it to
be defined).

eg:

$ cat $HOME/bin/if
#! /bin/sh

echo If Only.
$ command if args are ignored in that script
If Only.

Every shell I tested behaves like that, as they all should.
(0006203)
geoffclare   
2023-03-13 15:52   
(edited on: 2023-03-13 15:56)
After:
If the command_name is the same as the name of one of the special built-in utilities, the special properties in the enumerated list at the beginning of Section 2.14 (on page 2384) shall not occur. In every other respect, if command_name is not the name of a function, the effect of command (with no options) shall be the same as omitting command .
add:
, except that command_name does not appear in the command word position in the command command, and consequently is not subject to alias substitution (see [xref to 2.3.1]) nor recognized as a reserved word (see [xref to 2.4]).






Viewing Issue Advanced Details
1636 [1003.1(2016/18)/Issue7+TC2] System Interfaces Objection Error 2023-02-23 11:57 2023-03-13 15:39
geoffclare
 
normal  
Resolved  
Accepted  
   
Geoff Clare
The Open Group
pthread_sigmask()
1734
56226
---
See Desired Action
pthread_sigmask() equivalence to sigprocmask()
The description of pthread_sigmask() says it is equivalent to sigprocmask() except for the single-thread restriction. This omits the exception that the error return convention is different.

In RETURN VALUE there is a clause for sigprocmask() that is both redundant and incorrect: "and the signal mask of the process shall be unchanged". (It is redundant because of line 56250, and incorrect because "process" should be "thread".)

Also, in ERRORS, the statement:
The pthread_sigmask() function shall not return an error code of [EINTR].
is made for pthread_sigmask(), whereas all other requirements that rely on the equivalence in order to apply to both functions are stated for sigprocmask(). It could be changed to sigprocmask(), but given that the first line of the section is:
The pthread_sigmask() and sigprocmask() functions shall fail if:
it would be better to switch to the usual convention of saying "these functions" in the ERRORS section.

Finally, rather than fix these problems by the minimum necessary changes, the description would read better if it is rearranged to describe pthread_sigmask() first and then sigprocmask().
On page 1734 line 56225 section pthread_sigmask(), change:
The pthread_sigmask() function shall examine or change (or both) the calling thread's signal mask, regardless of the number of threads in the process. The function shall be equivalent to sigprocmask(), without the restriction that the call be made in a single-threaded process.

In a single-threaded process, the sigprocmask() function shall examine or change (or both) the signal mask of the calling thread.
to:
The pthread_sigmask() function shall examine or change (or both) the calling thread's signal mask.

On page 1734 line 56243-56250 section pthread_sigmask(), change (3 occurrences):
sigprocmask()
to:
pthread_sigmask()

On page 1734 line 56251 section pthread_sigmask(), change:
The use of the sigprocmask() function is unspecified in a multi-threaded process.
to:
The sigprocmask() function shall be equivalent to pthread_sigmask(), except that its behavior is unspecified if called from a multi-threaded process, and on error it returns -1 and sets errno to the error number instead of returning the error number directly.

On page 1734 line 56255 section pthread_sigmask(), change:
otherwise, -1 shall be returned, errno shall be set to indicate the error, and the signal mask of the process shall be unchanged.
to:
otherwise, -1 shall be returned and errno shall be set to indicate the error.

On page 1735 line 56258 section pthread_sigmask(), change:
The pthread_sigmask() and sigprocmask() functions shall fail if
to:
These functions shall fail if

On page 1735 line 56260 section pthread_sigmask(), change:
The pthread_sigmask() function shall not return an error code of [EINTR].
to:
These functions shall not return an error code of [EINTR].

There are no notes attached to this issue.




Viewing Issue Advanced Details
1635 [1003.1(2016/18)/Issue7+TC2] Base Definitions and Headers Editorial Clarification Requested 2023-02-21 00:14 2023-03-06 16:35
steffen
 
normal  
New  
Open  
   
steffen
iconv
1123
38014
---
iconv: please be more explicit in input-not-convertible case
issue 1007 resolves this to

    If iconv() encounters a character in the input buffer that is valid, but for which an identical character does not exist in the output codeset:

        If either the //IGNORE or the //NON_IDENTICAL_DISCARD indicator suffix was specified when the conversion descriptor cd was opened, the character shall be discarded but shall still be counted in the return value of the iconv() call.

        If the //TRANSLIT indicator suffix was specified when the conversion descriptor cd was opened, an implementation-defined transliteration shall be performed, if possible, to convert the character into one or more characters of the output codeset that best resemble the input character. The character shall be counted as one character in the return value of the iconv() call, regardless of the number of output characters.

        If no indicator suffix was specified when the conversion descriptor cd was opened, or the //TRANSLIT indicator suffix was specified but no transliteration of the character is possible, iconv() shall perform an implementation-defined conversion on the character and it shall be counted in the return value of the iconv() call.

However, as Martin Sebor stated in the issue description,

     The specification for the iconv() function assumes that every input sequence that is valid in the source codeset is convertible to some sequence in the destination codeset. In particular, the specification doesn't allow the function to fail when a valid sequence in the source codeset cannot be represented in the destination codeset. As an example where this assumption doesn't hold, consider a conversion from UTF-8 to ISO-8859 where a large number of source characters don't have equivalents in the destination codeset.

     A survey of a subset of existing implementations shows that they fail with EILSEQ in such cases, despite the specification defining the error condition as "Input conversion stopped due to an input byte that does not belong to the input codeset."

And this is true, GNU C library and GNU libiconv seem to fail output conversion immediately with the same EILSEQ error that denotes invalid input data.
(A much more drastic error, .. is it!?!)
Please be more explicit and denote that implementations exist which behave like GNU C-lib iconv / libiconv.
That is to say that "implementation defined conversion" may mean no conversion at all, but an immediate stop.

It would be tremendous if the standard could define hands that programmers can react upon, because, due to restriction of the iconv interface, it is impossible to decide what the error was.
A programmer does know nothing of input nor output character set, how many bytes may make up a character, how many were consumed / produced, whether conversion replacements where stored, or not. (In practice all others known to me do place some character and continue.)

This refers to GNU library bug report

  https://sourceware.org/bugzilla/show_bug.cgi?id=29913 [^]

where the honourable author of GNU iconv, and YES!, the GNU approach has lots of merits!, but it should be possible to differentiate in between the errors,

  Better even would be an explicit //CONVERR-STOP-WITH-ENODATA modifier.

refers to gnulib source files where the same approach is implemented portably, it seems, and the cost is tremendous, because of all the shortcomings of the iconv interface!
Like approaching cautiously byte-by-byte until a conversion succeeds!

      for (insize = 1; inptr + insize <= inptr_end; insize++)
        {
          res = iconv (cd,
                       (ICONV_CONST char **) &inptr, &insize,
                       &outptr, &outsize);
          if (!(res == (size_t)(-1) && errno == EINVAL))
            break;
          /* iconv can eat up a shift sequence but give EINVAL while attempting
             to convert the first character. E.g. libiconv does this. */
          if (inptr > inptr_before)
            {
              res = 0;
              break;
            }
        }

This is ridiculous!
Notes
(0006164)
steffen   
2023-02-21 18:20   
P.S.: to eloberate some more, any implementation which wants to conform to the upcoming POSIX standard needs to pass the configured state (//IGNORE, //TRANSLIT ..) along its internal code path, so that this addition would be an "easy" one.

Adding this very helpful addition to make the behaviour of the most widely used (and standards-incompatible) implementation explicitly addressable allows future programmers to know what they are doing.
(By other means than performing compile-time tests and fixate behaviour according to the compile-time-tested environment.)

I truly believe in the honourable Bruno Haible's approach, if it is addressable like that.

The only other implementation that allows programmers to realize their own output conversion failure stuff is that of AIX (looking at gnulib), because that uses the NUL byte as an implementation-defined conversion, but that, of course, will fail for data which contains embedded NULs (which for one is otherwise graspable by iconv(3), and second will fail for all multi-byte as in 16-bit or 32-bit encodings per se).

In general real life situation it very bad, just look at the efforts of character set conversion in the widely used and widely available libarchive.
This addition could make things a bit better.




Viewing Issue Advanced Details
1634 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Editorial Enhancement Request 2023-02-18 20:11 2023-03-06 16:30
steffen
 
normal  
Resolved  
Accepted As Marked  
   
steffen98141
mailx
2960
98141-2
---
See Note: 0006193.
mailx: more clarification on system mailbox
The current text "suggests" the commands work in any
mailbox, but the code bases shortcut to "edstop()"
unless in a primary (system) mailbox, and only then
$MBOX comes into play at all.

(My own clone has a TODO to change that for the "mbox"
command, as that always makes sense, like $MBOX being
the default for the "save" command, but that
off-topic. And was issue #991.)
on page 2960, line 98141-2, "touch", change

        Touch the specified messages. If any message in
        msglist is not specifically deleted nor saved
        in a file, it shall be placed in the mbox upon
        normal termination. See exit and quit.

to

        Touch the specified messages. If the current
        mailbox is the system mailbox any message in
        msglist that is not specifically deleted nor
        saved in a file shall be placed in the mbox
        upon normal termination. See exit and quit.
Notes
(0006157)
steffen   
2023-02-18 21:10   
Addition:
on page 2957, lines 98020ff, "hold" / "preserve", change

        Mark the messages in msglist to be retained in
        the mailbox when mailx terminates.[.]

to

        In a primary (system) mailbox, mark the
        messages in msglist to be retained in the
        mailbox when mailx terminates regardless of the
        setting of hold[the internal variable].[.]


That is to say, finally (also regarding issue 991),
that mbox, hold (preserve), (and touch) are ways to
counteract the setting of the variable hold.
(0006159)
steffen   
2023-02-18 23:27   
P.S.:
to make it plain.
The "touch" and "mbox" commands only differ in that "touch" may be overwritten by explicit "delete" or "save".
If they are adhered to, the messages are _moved_ to $MBOX -- and i think this should be said instead of the "placed" (because that could also be "copy" aka duplication).
(0006162)
steffen   
2023-02-20 23:50   
After a ML list intermezzo here something refined:

on page 2957, line 98020 ff., "hold" / "preserve", change

        Mark the messages in msglist to be retained in the mailbox
        when mailx terminates. This shall override any commands
        that might previously have marked the messages to be
        deleted. During the current invocation of mailx, only the
        delete, dp, or dt commands shall remove the preserve
        marking of a message.

to

        Allowed only in the system mailbox.
        Mark the messages in msglist to be preserved, as if the
        hold variable were set, upon normal termination, or when
        the folder is changed.
        This shall override any commands that might previously
        have marked the messages to be deleted.
        During the current invocation of mailx, only the delete,
        dp, or dt commands shall remove the preserve marking of
        a message.
        See exit and quit.

on page 2960, line 98141-2, "touch", change

        Touch the specified messages.
        If any message in msglist is not specifically deleted nor
        saved in a file, it shall be placed in the mbox upon
        normal termination.
        See exit and quit.

to

        Allowed only in the system mailbox.
        Touch the specified messages.
        Unless overriden by the hold variable, any message in
        msglist that is not specifically deleted nor saved in
        a file shall be placed in the mbox upon normal
        termination, or when the folder is changed.
        See exit and quit.

(Different to "hold" / "delete" this is not ensured by code like

        if (edit) {
                printf("Cannot \"preserve\" in edit mode\n");
                return(1);
        }

(yet), but the requirement is effective.)

Furthermore the solution of issue 991 for the "mbox" command has
to be furtherly refined. The editor notes by then were

        Change on page 2923, starting at line
        96567:
Arrange for the given messages to end up
        in the mbox save file when mailx terminates
        normally.
to:
Arrange for the given
        messages to be moved to the mbox save file when
        mailx terminates normally or when the folder is
        changed. This command can be used in any folder; for
        messages residing in the system mailbox, mailx
        shall ignore the settings of the internal variables
        [no]hold and [no]keepsave when the
        mbox command has been used to mark them
        explicitly.


This shall instead read

        Allowed only in the system mailbox.
        Arrange for the given messages to end up in the secondary
        mailbox, overriding a possibly set hold variable, upon
        normal termination, or when the folder is changed.
        See exit and quit.

(The requirement is not enforced (yet), but effective.)
(0006165)
steffen   
2023-02-21 23:01   
One more iteration on that that clarifies which commands strip
which flags again.
This now correctly reflects what V10 Mail, BSD Mail of Apple of
2015, OpenBSD Mail of 2023-01-28, and s-nail (devel) do.
It also adds a possible change for the hold variable.

on page 2957, line 98020 ff., "hold" / "preserve", change

        Mark the messages in msglist to be retained in the mailbox
        when mailx terminates. This shall override any commands
        that might previously have marked the messages to be
        deleted. During the current invocation of mailx, only the
        delete, dp, or dt commands shall remove the preserve
        marking of a message.

to

        Allowed only in the system mailbox.
        Mark the messages in msglist to be preserved, as if the
        hold variable were set, upon normal termination, or when
        the folder is changed.
        This shall override any commands that might previously
        have marked the messages to be deleted,
        and only the delete, dp, or dt, as well as the mbox and
        touch commands shall remove the preserve mark of a message.

on page 2960, line 98141-2, "touch", change

        Touch the specified messages.
        If any message in msglist is not specifically deleted nor
        saved in a file, it shall be placed in the mbox upon
        normal termination.
        See exit and quit.

to

        Allowed only in the system mailbox.
        Touch the specified messages.
        Unless overriden by the hold variable, any message in
        msglist that is not specifically deleted nor saved in
        a file shall be placed in the mbox upon normal
        termination, or when the folder is changed.
        Overrides a former hold or preserve request.

Furthermore the solution of issue 991 for the "mbox" command has
to be furtherly refined.
Its editor notes shall instead read

        Allowed only in the system mailbox.
        Arrange for the given messages to end up in the secondary
        mailbox, overriding a possibly set hold variable, upon
        normal termination, or when the folder is changed.
        Overrides a former hold or preserve request.

Ditto. Let's center on the variable.
On page 2952, lines 97820 ff, variable "hold", change

        hold
        Preserve all messages that are read in the system mailbox
        instead of putting them in the mbox save file. The default
        shall be nohold.

to

        hold
        Disable message moving of read messages from the system
        mailbox to the mbox save file upon normal program
        termination or folder change.
        This automatic email management is complemented with the
        commands hold (and preserve), mbox, and touch, which
        partially override the hold variable.
        The default shall be nohold.

On page 2953, lines 97972 ff, "exit", "xit", change

        Exit from mailx without changing the mailbox.
        No messages shall be saved in the mbox (see also quit).

to

        Exit from mailx without performing automatic message
        moving, or any other management tasks.
        Also see quit.

On page 2959, lines 98078 ff, "quit", "EOF", change

        Terminate mailx, storing messages that were read in mbox
        (if the current mailbox is the system mailbox and unless
        hold is set), deleting messages that have been explicitly
        saved (unless keepsave is set), discarding messages that
        have been deleted, and saving all remaining messages in
        the mailbox.

to

        Terminate mailx normally.
        Dependent upon the conditions documented for the variable
        hold this may perform automatic message moving.
        It will delete messages that have been explicitly saved
        (unless keepsave is set), discard messages that have been
        deleted, and save all remaining messages in the mailbox.

(Better yet, move that to the folder command, instead of vice
versa, and only say

        It will quit the folder and perform management task as
        documented there.)

Thank you.
(0006193)
Don Cragun   
2023-03-06 16:27   
Make the changes in Note: 0006165 except for the line 98078 change.

On page 2956 lines 97977 ff, fi[le] [file], fold[er] [file], change:
Quit (see the quit command) from the current file of messages and read in the file named by the pathname file. If no argument is given, the name and status of the current mailbox will be written.
to:
If no argument is given, write the name and status of the current mailbox. Otherwise, close the current file of messages after performing actions as specified for the quit command (except for terminating mailx) and then read in the file named by the pathname file. The behavior is unspecified if file is not a valid mbox.


On page 2959, lines 98078 ff, "quit", "EOF", change:
Terminate mailx, storing messages that were read in mbox (if the current mailbox is the system mailbox and unless hold is set), deleting messages that have been explicitly saved (unless keepsave is set), discarding messages that have been deleted, and saving all remaining messages in the mailbox.
to:
Terminate mailx normally, performing automatic message moving as specified in the description of the variable hold, deleting messages that have been explicitly saved (unless keepsave is set), discarding messages that have been deleted, and saving all remaining messages in the mailbox.




Viewing Issue Advanced Details
1633 [Issue 8 drafts] Base Definitions and Headers Comment Enhancement Request 2023-02-16 10:07 2023-03-06 16:36
nrk
 
normal  
New  
Open  
   
Nickolas Raymond Kaczynski
<string.h>
n/a
n/a
Add memrchr
memrchr is a simple and useful function that is similar to memchr, except it finds the last occurrence of a byte. It is provided by the following implementations already:

* glibc (https://www.man7.org/linux/man-pages/man3/memrchr.3.html) [^]
* musl
* openbsd (https://man.openbsd.org/memrchr.3) [^]
* freebsd (https://man.freebsd.org/cgi/man.cgi?query=memrchr&manpath=FreeBSD+13.1-RELEASE+and+Ports) [^]

(And probably many others).
Under section <string.h> add:

void *memrchr(const void *s, int c, size_t n);

Under memchr, add memrchr to SEE ALSO.

Add a new memrchr page:

NAME

    memrchr - find last occurrence of a byte in memory

SYNOPSIS

    #include <string.h>

    void *memrchr(const void *s, int c, size_t n);

DESCRIPTION

    The memrchr() function shall locate the last occurrence of c (converted to an unsigned char) in the initial n bytes (each interpreted as unsigned char) pointed to by s.

RETURN VALUE

    The memrchr() function shall return a pointer to the located byte, or a null pointer if the byte is not found.

ERRORS

    No errors are defined.
Notes
(0006185)
Don Cragun   
2023-03-02 16:56   
In addition to memchr(), the standard also includes wmemchr(). Does this request also intend to add wmemrchr()?
(0006186)
nrk   
2023-03-02 17:10   
The purpose of this defect report was to standardize a widely implemented interface.

I've quickly looked into glibc, musl, freebsd & openbsd and none of them seem to provide wmemrchr(). As such, I have no intention of adding wmemrchr().
(0006194)
shware_systems   
2023-03-06 16:36   
Note 6186 was discussed in the 2023-03-06 teleconference and it was noted that because wcsrchr() is already present, it functionally serves as an equivalent for most situations to wmemrchr(), and this is a reason there hasn't been much call to implement wmemrchr(). However, for searching blocks that may have embedded wide null chars it is not sufficient; application code is necessary to find the last null before attempting the right scan.

As such, for symmetry and completeness the consensus is more the standard should contain the interface, unless some implementation has a compelling reason it can communicate here why it shouldn't be.




Viewing Issue Advanced Details
1632 [Issue 8 drafts] Shell and Utilities Objection Clarification Requested 2023-01-31 00:58 2023-03-02 16:44
kre
 
normal  
Resolved  
Accepted As Marked  
   
Robert Elz
XCU 2.6.1
2319-2320
74775-74794
Note: 0006184
Tilde expansions with HOME="" or HOME value ending in /
The current draft, and earlier versions, this is not a new problem, it
could have been filed against any older version - but as 2.6.1 has already
been updated for other reasons for Issue 8, it seemed sensible to use its
most recent draft, don't specify what should happen if HOME="" or if the
value of HOME ends in a '/' - including particularly, the case of HOME=/

The case of HOME=/ is perhaps most interesting, as if the text is treated
literally, which almost all shells do, the result of expanding ~/foo in
such a case is //foo which is an unspecified pathname (as I understand it).

A recent ksh93 produces /foo from this case, but that's the only shell I
can find which does (amusingly, for the case of HOME=/dir/ that version
of ksh93 produces /dir//foo for ~/foo whereas an older one produces //foo
for HOME=/ and /dir/foo for the HOME=/dir/ case)..

mksh also makes /dir/foo in the HOME=/dir/ case and //foo in the HOME=
case, most other shells simply do as the standard says, and replace the tilde
prefix (just '~' here) with the value of HOME, which results in the // in both
cases.

This leads to the desire to use HOME="" instead of HOME=/ in the case where
the home directory is intended to be the root directory, which results in
~/foo expanding to /foo in almost all shells (the now quite old FreeBSD shell
I use to test with doesn't expand ~ at all when $HOME is an empty string,
but that is. or quite likely was, clearly a bug, so I assume it has been
fixed sometime in the past several years).

However, despite the language of the standard:

   The pathname resulting from tilde expansion shall be treated as if
   quoted to prevent it being altered by field splitting and pathname
   expansion.

most shells expand a word which is just ~ to nothing if HOME='' rather
than (effectively) to "" which that sentence seems to require. Only
bash, the NetBSD shell, and the older version of ksh93 made "".
(Again, the FreeBSD shell just produces ~ here, for the same reason as above).

This all needs to be cleaned up.
I'd suggest requiring that if a pathname resulting from a tilde espansion
(a term which really ought be better defined - I assume that in ~/foo
where HOME=/dir that the pathname intended is "/dir" not "/dir/foo"
otherwise ~/*.c would never be able to work) ends in a / that if a /
occurs as the next character of the word containing the tilde expansion
be omitted from the result - as that produces better results overall
(despite it going to require changes in most shells, including the one
I maintain).

I'd also suggest being more explicit either than when HOME='' ~ expands
to "" or nothing (it makes no difference if there is more to the word).
For this, I'd prefer "" (for both the obvious reason, and because it is
more consistemt with both the current wording, and useful behaviour).
Notes
(0006144)
mirabilos   
2023-02-06 01:46   
I’d prefer HOME= to be treated the same as HOME=/ wrt. expansion, and to make sure that these are logical concatenations of pathnames, e.g. '/home' + 'foo' = '/home/foo' but '/' + 'foo' = '/foo'. This avoids both “naïve” string concatenation and the problem of having to decide what to do with an empty string; I consider an empty string to not be a valid pathname and therefore not a valid expansion for a sole tilde.

I’m happy to change mksh to match; from a Debian perspective, we’re entering soft freeze in a few days so a speedy decision would be welcome.
(0006184)
geoffclare   
2023-03-02 16:42   
On page 2320 line 74793 section 2.6.1, change:
The pathname resulting from tilde expansion shall be treated as if quoted to prevent it being altered by field splitting and pathname expansion.
to:
The pathname that replaces the tilde-prefix shall be treated as if quoted to prevent it being altered by field splitting and pathname expansion; if a <slash> follows the tilde-prefix and the pathname ends with a <slash>, the trailing <slash> from the pathname should be omitted from the replacement. If the word being expanded consists of only the <tilde> character and HOME is set to the null string, this produces an empty field (as opposed to zero fields) as the expanded word.
<small>Note: A future version of this standard may require that if a <slash> follows the tilde-prefix and the pathname ends with a <slash>, the trailing <slash> from the pathname is omitted from the replacement.</small>




Viewing Issue Advanced Details
1631 [Issue 8 drafts] Shell and Utilities Editorial Error 2023-01-21 18:45 2023-03-10 10:53
dmitry_goncharov
 
normal  
Applied  
Accepted As Marked  
   
Dmitry Goncharov
make
https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/nframe.html [^]
0
See Note: 0006169
Default archive rules are incompatible with parallel processing.
The default archive rules specified in the standard are

".c.a:
    $(CC) -c $(CFLAGS) $<
    $(AR) $(ARFLAGS) $@ $*.o
    rm -f $*.o


.f.a:
    $(FC) -c $(FFLAGS) $<
    $(AR) $(ARFLAGS) $@ $*.o
    rm -f $*.o
"

Parallel processing was introduced in
https://austingroupbugs.net/view.php?id=1436. [^]

With -j specified these rules can result in an incomplete archive, because multiple instances of ar are updating the same archive simultaneously.
One option is to state that these rules are incompatible with parallel processing.
Another option is to remove these rules from the standard.
Notes
(0006124)
kre   
2023-01-21 21:48   
I don't know make implementations, or whether any does this, but
another option might be to require that when running sub-builds
in parallel (whatever the correct terminology is for that) that
no two such parallel sub-builds can be building the same target,
simultaneously.

To me that seems like a sane rule for all parallel builds, regardless
of whether there are archives (or anything similar) involved.
(0006125)
rillig   
2023-01-21 22:10   
@dmitry_goncharov
Could you please elaborate why the archiving is the problem with these rules?

As far as I understand these rules, the same problem occurs when two competing files named `source.c` and `source.f` are compiled to `.o` files.

Since the inference "shall be searched in the order defined", `source.c` is chosen by both parallel makes, and `source.f` is effectively ignored.

Or are you talking about a different scenario in which one of the makefiles has deactivated the `.c.o` rule? But then, compilation would be as broken as archiving.

Or did I miss something?
(0006126)
dmitry_goncharov   
2023-01-22 02:08   
> but another option might be to require that when running sub-builds
in parallel (whatever the correct terminology is for that) that
no two such parallel sub-builds can be building the same target,
simultaneously.

This looks a reasonable idea to me. Should be relatively easy to implement in top make alone. However, this is more difficult when submake is involved. One submake does not know which target another submake or top make is building. One technique could be to use a form of file locking on the target (as long as the target is an actual file in the fs). However, this is not cheap.
(0006127)
dmitry_goncharov   
2023-01-22 03:02   
(edited on: 2023-01-22 03:13)
> Could you please elaborate why the archiving is the problem with these rules?

Let us assume we have hello.c and bye.c and have to build libhello.a which contains hello.o and bye.o.
With these rules make will first compile hello.c and bye.c in parallel. Once an object file (either hello.o or bye.o) is ready make will fork-exec an instance of ar to insert that object file to libhello.a. Which possibly results in these two instances of ar running in parallel.

(0006128)
psmith   
2023-01-22 18:42   
My preference would be to change the default rules to remove the $(AR) from the individual compilation, and add a new default rule to build the archive from object files using the "$?" (only updated files). But I'm not sure this can be easily done in the standard version of make, that doesn't have the complexity of intermediate files.
(0006131)
steffen   
2023-01-23 21:59   
My fault.

Personally i think the standard inference rules are very much overcome, especially anything regarding SCCS that has been deprecated by life (except maybe for some private use cases). (And Jörg is dead to improve his SCCS.)

The syntax regarding archives i have never seen used in real life.

I would go with what the GNU make manual says, "either write some dedicated rules, or do not use -j for archives" (more or less cited correctly).
So maybe a sentence of warning?
(0006132)
steffen   
2023-01-23 22:02   
P.S.: BSD make and smake (from Jörg) do not even get it right. BSD make also does not support the standard-documented way to output inference rules.
But eg

  lib: lib(t1.o) lib(t2.o)

only works with GNU make. (I have no Solaris to test.)
And GNU make may fail for -j, as it documents (in its info manual).

#?0|kent:x$ bmake
`lib' is up to date.
#?0|kent:x$ smake
smake: Can't find any source for 'lib(t1.o)'.
smake: Couldn't make 'lib'.
#?1|kent:x$ make
gcc -O1 -g -c -o t1.o t1.c
ar -rv lib t1.o
ar: creating lib
a - t1.o
gcc -O1 -g -c -o t2.o t2.c
ar -rv lib t2.o
a - t2.o
ok
rm t2.o t1.o
(0006133)
steffen   
2023-01-23 22:04   
P.P.S: even with "lib.a" it gets worse:

#?0|kent:x$ smake
smake: Can't find any source for 'lib.a(t1.o)'.
smake: Couldn't make 'lib.a'.
#?1|kent:x$ bmake
ok
#?0|kent:x$ ll
total 12K
-rw-r----- 1 steffen steffen 61 Jan 23 22:26 t1.c
-rw-r----- 1 steffen steffen 61 Jan 23 22:26 t2.c
drwxrwxrwt 10 root root 240 Jan 23 23:01 ../
drwxr-x--- 2 steffen steffen 100 Jan 23 23:02 ./
-rw-r----- 1 steffen steffen 41 Jan 23 23:02 makefile
#?0|kent:x$ make
gcc -O1 -g -c -o t1.o t1.c
ar -rv lib.a t1.o
ar: creating lib.a
a - t1.o
gcc -O1 -g -c -o t2.o t2.c
ar -rv lib.a t2.o
a - t2.o
ok
rm t2.o t1.o
#?0|kent:x$ ll
total 20K
-rw-r----- 1 steffen steffen 61 Jan 23 22:26 t1.c
-rw-r----- 1 steffen steffen 61 Jan 23 22:26 t2.c
-rw-r----- 1 steffen steffen 41 Jan 23 23:02 makefile
drwxrwxrwt 10 root root 240 Jan 23 23:02 ../
-rw-r----- 1 steffen steffen 7218 Jan 23 23:02 lib.a
drwxr-x--- 2 steffen steffen 120 Jan 23 23:02 ./
#?0|kent:x$

(But i have problems grasping inference rules, maybe it is my fault. I only used them very superficially.)
(0006134)
hvd   
2023-01-23 22:11   
> Let us assume we have hello.c and bye.c and have to build libhello.a which contains hello.o and bye.o.

The predefined rules do not support that even without -j, do they? The predefined .c.a rule supports building hello.a from hello.c, using hello.o as an intermediate file. That's it. If you want a different name, such as libhello.a, or if you want to include multiple object files, you need custom rules, and it's then your own responsibility to making them parallel-build-safe.

Whether the predefined rule should be kept or not, the parallel processing should have no impact on that. For the very limited scenarios that the built-in rules handle, the parallel processing should not be an issue.
(0006135)
dmitry_goncharov   
2023-01-24 02:24   
> The predefined rules do not support that even without -j, do they?
...
If you want a different name, such as libhello.a, or if you want to include multiple object files, you need custom rules, and it's then your own responsibility to making them parallel-build-safe.

You'll need to tell make that libhello.a depends on hello.o and bye.o.
But, the default rules, along with their default recipes, can still be used to build libhello.a.


$ ls
bye.c hello.c makefile
$ cat makefile
libhello.a: libhello.a(hello.o) libhello.a(bye.o)
$ make
cc -c -o hello.o hello.c
ar -rv libhello.a hello.o
ar: creating libhello.a
a - hello.o
cc -c -o bye.o bye.c
ar -rv libhello.a bye.o
a - bye.o
rm hello.o bye.o
$ ar tv libhello.a
rw-r--r-- 1001/1004 952 Jan 23 21:06 2023 hello.o
rw-r--r-- 1001/1004 952 Jan 23 21:06 2023 bye.o


> Whether the predefined rule should be kept or not, the parallel processing should have no impact on that.

People use parallel processing a lot. With these rules we expect every user to read the manual and notice the warning and avoid parallel processing.
(0006136)
hvd   
2023-01-24 09:56   
> But, the default rules, along with their default recipes, can still be used to build libhello.a.

Thanks for spelling it out.

> My preference would be to change the default rules to remove the $(AR) from the individual compilation, and add a new default rule to build the archive from object files using the "$?" (only updated files). But I'm not sure this can be easily done in the standard version of make, that doesn't have the complexity of intermediate files.

Right, they complicate things. It would be easy if the .o files did not need to be removed. Then, the default .c.o rule could be used to make the object file, and a rule to build the archive from the .o files could use $? to get the updated object files (as opposed to the updated source files). But the .o files getting removed complicates things.

kre's idea to require that no two rules for the same target run in parallel seems like a good idea, but prevents hello.c and bye.c from being compiled in parallel. With the current rule, compiling them in parallel is unsafe as there is no way to not also cause the $(AR) commands to run in parallel, which then causes issues. If there is a way to separate the commands into separate rules, like with the referenced concept of intermediate files, that would become safe.

Yet another option would be to leave make as is, but require ar to use file locking to allow concurrent invocations, where a second invocation blocks until a first one completes. This is probably a bad idea, but mentioning it for completeness.
(0006137)
psmith   
2023-01-24 18:55   
If the .o files don't need to be removed then you don't need any special handling for archives at all. You can just write standard rules and you don't need the magical libfoo.a(foo.o) syntax or the special behaviors of the .a suffix rules, because you can just base things on the timestamp of the archive itself compared to the timestamp of the .o files.

The only way this extra behavior is needed or useful is when you want to update the archive _without_ having to rebuild all the object files (like you do, for example, when you link a program).
(0006152)
shware_systems   
2023-02-16 17:05   
An alternative is possibly a change to ar requirements: that it check if an existing archive is already open for processing by another instance or application and then pause until it is capable of gaining such exclusive use. It is unknown whether any current implementation does this checking, however, but it would make use of -j with this rule plausible as the accesses and object adds would be self serializing.
(0006153)
steffen   
2023-02-16 20:41   
re @6152
You mean this would be the right time to standarIdize flock(1)?
I use it often


       flock [options] file|directory command [arguments]
       flock [options] file|directory -c command
       flock [options] number

DESCRIPTION
       This utility manages flock(2) locks from within shell scripts or from
       the command line.

       The first and second of the above forms wrap the lock around the
       execution of a command, in a manner similar to su(1) or newgrp(1). They
       lock a specified file or directory, which is created (assuming
       appropriate permissions) if it does not already exist. By default, if
       the lock cannot be immediately acquired, flock waits until the lock is
       available.

       The third form uses an open file by its file descriptor number. See the
       examples below for how that can be used.
(0006169)
nick   
2023-02-23 17:18   
(edited on: 2023-02-23 17:22)
Add to APPLICATION USAGE (D2.1 P2952, after line 99106):
It is important to be careful when using parallel execution (the -j switch) and archives. If multiple $(AR) commands run at the same time on the same archive file, they will not know about each other and can corrupt the file. If the -j option is used, it is necessary to use .WAIT in between archive member prerequisites to prevent this (see EXAMPLES).


On D2.1 page 2953 line 99164 section make (EXAMPLES), change:
lib: lib(file1.o) lib(file2.o) lib(file3.o)
    @echo lib is now up-to-date


The .c.a rule is used to make file1.o, file2.o, and file3.o and insert them into lib.

to:
lib.a: lib.a(file1.o) .WAIT lib.a(file2.o) .WAIT lib.a(file3.o)
    @echo lib is now up-to-date


The .c.a rule is used to make file1.o, file2.o, and file3.o and insert them into lib.a.






Viewing Issue Advanced Details
1630 [1003.1(2016/18)/Issue7+TC2] Base Definitions Objection Clarification Requested 2023-01-20 21:39 2023-03-01 23:04
mirabilos
 
normal  
New  
Open  
   
mirabilos
mksh
3.10
(page or range of pages)
(Line or range of lines)
---
Alias names
I have a strong objection for alias names beginning with either ‘+’ or ‘-’ (or are exactly “[[” but that’s not yet portable anyway).

This used to not be a problem, but with the recent change to POSIX alias name characters, it has become one.

(This was, indeed, discussed with users who wanted to use +/- as aliases, but there were problems and ambiguities stemming from them (mostly wrt. options), and so mksh denies aliases to start with either of these characters.)
   On page 34, lines 1168 ff., change

     3.10 Alias Name
     In the shell command language, a word consisting solely of alphabetics and
     digits from the portable character set and any of the following characters:

   to

     3.10 Alias Name
     In the shell command language, a word consisting solely of alphabetics and
     digits from the portable character set and any of the following characters
     (where '-' may not be used as the first character of the word):
Notes
(0006122)
kre   
2023-01-20 22:30   
As long as we're keeping aliases in the standard at all (no objection to
deleting them, and all that goes with them, from me), their names, just
like function names, should be able to be anything that a (simple) command
name can be, so an alias, or function, can be used to replace/augment any
command that can exist (just not ones containing '/' so using a full path
to defeat the function, or alias, though even that's not as important for
aliases, as quoting some of it also stops an alias from expanding).

Commands can begin with - and + (I use '-' as a shorthand for the nmh "prev"
command, and '+' for its "next" command), so aliases should be able to as
well.

The current text in XBD 3.10 doesn't require support in alias names
for '+' or '-' at all, but it allows that as an implementation extension.

I object to any attempt to restrict things more than is currently done
(note: nothing requires your shell to allow '-' or '+' in alias names
at all, if you do allow them, you can do that however you like, the
standard does not have to forbid a leading '-' for you to do so.)

[[ would be a dangerous alias to attempt to use, as it is on the "might
be a reserved word" list, if it is, then (with standard posix shell practices)
it cannot be used as an alias. If it isn't, I see no reason why that
shouldn't be an alias either.

While I'm here, a procedural note which I think is correct, but someone
more knowledgeable might correct me ... you're filing your recent issues
in the "Online Pubs" category. I think that's wrong - that's intended for
issues with the HTML translation of the (primary) PDF version of the
standard. I don't think it should be used for issues with what the
standard says, or changes/additions requested of that. Use the version
of the standard you're reading (if the HTML version that would be
Issue7+TC2 currently).
(0006123)
kre   
2023-01-20 22:36   
(edited on: 2023-01-20 22:38)
And I, of course, missed the changes made by 0001050 which is not
in the draft yet.

That makes no difference to my opinion of this, an alias name starting
with (or being entirely) '-' (or '+') is, and should remain, entirely
proper to have.

(0006149)
geoffclare   
2023-02-13 17:19   
This was discussed in the Feb 13, 2023 teleconference. For filenames, POSIX says in XBD 4.8 (or 4.9 in D2.1):
Applications should avoid using filenames that have the <hyphen-minus> character as the first character since this may cause problems when filenames are passed as command line arguments.

We are leaning towards adopting a similar solution for alias names, but would like to know more about the problems that alias names beginning with <hyphen-minus> caused for mksh. All we have to go on at the moment is the vague mention in the description, "there were problems and ambiguities stemming from them (mostly wrt. options)". We note that shells other than mksh do not seem to have problems in this area.
(0006156)
mirabilos   
2023-02-18 20:33   
I honestly don’t remember any more :|

The last mention of this is from March 2020:

| allow ‘+’ in alias names (just not as first character, like ‘-’)

mksh’s getopt has + and - as flag starters both, hence handling them the same.

The last change of “valid characters in alias names” before that was in April 2017 (: and [ but not exactly "[[")… and shortly before, - was re-added but not as first character (after we had stripped the list down to what POSIX said at that time).

That was shortly before that, and I *think* it was done in response to some user or researcher (Stéphane Chazelas is good at doing so) finding some issue with allowing “too much” in alias names.

So, sorry, I don’t recall details after five years.

I do appreciate the note asking applications not to do it; I’d appreciate it even more if an alias name beginning with [+-] could have implementation-specified behaviour (so I could continue rejecting them) but I understand if you’re reluctant to do so on the vague amount of reason I can give.
(0006171)
geoffclare   
2023-02-24 10:03   
That's unfortunate. The plan was not only to decide whether to include the warning based on your feedback but also to base the "since this may cause problems when ..." part of the text on it.

For filenames, problems can occur in common everyday interactive commands typed by users, such as "ls -l *.c", if a filename beginning with '-' happens to exist. (It can occur in shell scripts as well, of course, but I think these days shell script authors are more likely to take care to include "--", whereas users don't bother in interactive commands as it's more to type.) The only similar case for aliases I can think of would be some code to unalias or show the definition of a subset of the current aliases. Something like:
for a in $alias_names; do
    case $a in
    (foo|bar) ;;
    (*) unalias "$a" ;; # or: alias "$a"
    esac
done

But this is far from "common everyday" stuff.

Unless someone can come up with a use case that merits the warning, I expect we will end up rejecting this bug.
(0006172)
hvd   
2023-02-24 12:24   
(edited on: 2023-02-24 12:25)
One problem is that implementations disagree on whether the 'alias' command takes options, and in those implementations where it does not take options, whether option processing happens. Because of this, it is not possible to define an alias with a name starting with '-' portably.

In dash and osh, this works:

  alias -hello="echo hello"
  -hello

In bash, bosh, gwsh, ksh, pdksh, and yash, this works:

  alias -- -hello="echo hello"
  -hello

But there is not, I believe, a way to use the alias command to define an alias named '-hello' that works in all shells (edit: and does not attempt to print the definition of any existing alias with the name '--') that allow that as an alias name unless we resort to trickery like

  alias dummy=dummy -hello="echo hello"
  unalias dummy
  -hello

(0006173)
geoffclare   
2023-02-24 13:45   
Re Note: 0006172 The standard requires that alias supports "alias -- operand". If dash and osh do not support it, they are non-conforming. See XCU 1.4 Utility Description Defaults (under OPTIONS).
(0006174)
ormaaj   
2023-02-24 14:05   
(edited on: 2023-02-24 14:17)
Relatedly, the `-p` option used by several implementations is absolutely required in order to properly save and restore alias definitions, so `alias` must support handling them. -p causes each output alias to be prefixed with an alias command so that the string may be eval'd. The format prescribed by POSIX renders the output completely useless in spite of the impossible requirement that "the value string shall be written with appropriate quoting so that it is suitable for reinput to the shell".

One could theoretically interpret that in a reasonable manner once $'' becomes available as it could then be inferred that the shell must force each definition onto a single line to be subsequently parsed by newline delimiters. That could only happen safely if each definition is required to be represented that way.

Most current implementations don't do this even if they do support $''. zsh and ksh93 seem to. bash and dash do not.

(0006175)
stephane   
2023-02-24 14:30   
Re: Note: 0006174

I agree it's unclear what:

> suitable for reinput to the shell

means in that context. Does that mean "reinput as a scalar variable assignment"?

$ bash -c 'alias "a[1]=1"; alias'
alias a[1]='1'
$ bash -o posix -c 'alias "a[1]=1"; alias'
a[1]='1'
$ bash -o posix -c 'alias "*=1"; alias'
*='1'

None of that is suitable as reinput to the shell, neither as variable assignment, neither as alias invocations as those glob characters are not quoted; one would need to set the noglob option

zsh's is suitable as reinput as:

eval "saved_aliases=($(alias))"
alias -- $saved_aliases

Though of course that's not POSIX syntax and anyway zsh already exposes the list of aliases in the special $aliases associative array (not in sh emulation by default).

Another way bash is not compliant is that in:

alias a[0-9]=uname

in a directory that contains a a1=uname file, it defines a a[0-9] alias instead of a1.
(0006176)
hvd   
2023-02-24 14:44   
> Does that mean "reinput as a scalar variable assignment"?

I have interpreted it, and dash has interpreted it, as "reinput as an operand to the alias command", so that given an existing alias foo, v=$(alias foo) can be used to save its definition, and eval "alias $v" can be used to restore it. This is why dash has also recently changed to suitably quote not only the value, but also the name (in contradiction of POSIX because POSIX is clearly utterly wrong here). zsh does the same.

Mind, this is only useful for the output of a single alias definition. For the output of multiple alias definitions, the -p option is still needed.
(0006177)
ormaaj   
2023-02-24 14:52   
(edited on: 2023-02-24 15:20)
Bash is one of the shells that considers alias to be a declaration builtin. I suspect it will try parsing `alias a[0-9]=uname` as though it were an array assignment without globbing even though that's nonsense.

related discussion: https://github.com/ksh93/ksh/commit/b369f40ded0ec7e8dd3d4a0e7226ccf037bb3400#commitcomment-86945331 [^]

Edit: ...and indeed that's exactly what bash does. Stranger still, ksh93 (both v- and u+m) whine with an error: "cannot be an array" in spite of ksh supposedly not considering alias as a declaration command. `whence -v` says "special builtin" in v- (like typeset) while u+m says it's a regular builtin.

(0006178)
kre   
2023-02-24 16:59   
You all do realise that we could easily make all of this simply
go away, by deleting aliases from the standard, and leaving them
for shells to implement however they want (like "select" and "[["
and all kinds of other add-ons that are moderately common, but not
needed in the standard).

Aliases are an absurd feature to have standardised (they're absurd
in any event, but never mind) - the very thought of a portable
script attempting to use aliases in some productive way is frightening.
(0006179)
eblake   
2023-02-27 17:37   
https://git.sv.gnu.org/cgit/gnulib.git/tree/gnulib-tool?id=355e89bcb#n102 [^] is an example of a script that DOES try to use 'alias' as a feature, but where the item being aliased does not use leading '-' nor trailing ' ', and where even the attempt at (ab)using aliases is further conditionalized on being run by particular shells rather than trying to be portable to all POSIX sh. The fact that aliases are that hard to portably use in scripts is indeed an argument in favor of leaving aliases as an implementation extension, but I'm not sure if we have time to do that for Issue 8 (not least of which we need proposed wording changes)
(0006181)
kre   
2023-02-27 19:13   
Re Note: 0006179

The script in question is wacked out, rather than "alias sed='sed --posix'
it should instead do

    sed=sed

and then in the case where the alias is defined

    sed="$sed --posix"

and then use $sed everywhere instead of sed (as a command name).

The script as it is probably works as run as a command, or as a filename
arg to sh, but isn't guaranteed to work if run as ". script" since in that
case the shell is allowed to parse the whole thing before running any of it,
and in that case the alias command executes too late to alter anything in
the script.

[Aside: I do understand the temptation to do it the alias way, as when it
does work, it avoids needing changes elsewhere in the script, along with
the possibility that some might get missed - but it is still the wrong way.]

I think the changes could be made for Issue 8, apart from needing to add
"alias" and "unalias" to wherever is appropriate to tell users not to use
as arbitrary commands, the changes are almost all simply deleting stuff.

If there were agreement that this change can be made (ie: if the minutes
from a meeting say something like "if the changes needed to remove aliases
from the standard are made available, it was agreed to delete aliases from
the standard") then I'll take a look at finding all the relevant places and
suggesting what changes ought to be made.
(0006182)
geoffclare   
2023-02-28 14:08   
We cannot remove aliases without first making them obsolescent. So the route to getting them removed would be to request adding OB shading in Issue 8. Then they can be removed in Issue 9.
(0006183)
steffen   
2023-03-01 23:04   
Despite kre's repulsion against macros, they are implemented anywhere, and i would wildly claim that the majority of shell users use them, .. for decades.
Why should such a feature be removed?




Viewing Issue Advanced Details
1629 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Editorial Clarification Requested 2023-01-15 17:30 2023-03-20 16:28
mirabilos
 
normal  
Resolved  
Accepted As Marked  
   
mirabilos
mksh
unsure which applies
(page or range of pages)
(Line or range of lines)
---
Note: 0006210
Shell vs. read(2) errors on the script
As indicated in <Pine.BSM.4.64L.2301081426320.6999@herc.mirbsd.org> on the mailing list, both GNU bash <https://savannah.gnu.org/support/index.php?110763> [^] and mksh <https://bugs.launchpad.net/mksh/+bug/2002044> [^] got reports that the shell does not error out on read errors when loading either the first or any subsequent block of the script to execute.

Chet says that treating them as EOF is historical behaviour.

I don’t have a preference either way as I can see benefit in both; in contrast to Chet however I do think that the exit status mandated (if any) does matter and would prefer a high one, or even suggesting that the shell sends itself a suitable signal (PIPE, BUS and HUP, in that order, came to mind) so that the script could even have installed a trap handler to catch this condition beforehand (and clean up).
Decide whether…

① either ⓐ keep to existing behaviour; read errors on the script are treated as EOF, and the shell is still required to exit with the errorlevel of the last command executed (if any; a read error on the first block of a script would equal executing a null command and therefore exit zero),
  or ⓑ that read errors on script input require exiting indicating an error in some way,

and ② if 1b, how shells are supposed to treat these errors; options are at least
  ⓒ some code within 1‥125, as with other errors,
  ⓓ 126 as if the script was not executable (which will require changing 126 as it’s IIRC currently tied to ENOEXEC),
  ⓔ signalling itself with a suitable signal,
  ⓕ exiting with 128+signalnumber of the signal,
  ⓖ any other, possibly high, status.

I dislike 2c (which the bug submitter suggests as he interprets the spec this way currently) for possible confusion with utility exit statūs (grep, diff, cURL, unifdef, etc).
I’m not sure about 2d but it sounds good.
As mentioned above, I’d prefer 2e iff 1b is decided on (I’m similarly good with 1a, I just want a well-argumented decision either way).
If 2e is not palatable, I’d rank 2f almost as high as 2d.
2g has the potential of conflicting with 2f for possibly unrelated signals.
Notes
(0006120)
chet_ramey   
2023-01-20 21:18   
As part of the discussion on savannah, I looked into different shells' behavior.

The only shell that reflects a read error into $? is yash. The rest, including bash, treat read errors the same as EOF and exit with the last command's exit status.
(0006142)
chet_ramey   
2023-02-02 15:51   
I see that the minutes of the 30 January meeting begin to address this. The summary says that this is "partially handled by ... 0000367". I assume that means for errors during the `read' builtin.

It's far from clear that an EIO (or ESTALE, or whatever) error while reading a script is meant to be one of the "an error other than ...," but if it is, it's best to state that explicitly instead of hiding behind the "including, but not limited to" language.
(0006143)
chet_ramey   
2023-02-04 17:46   
I sent this to austin-group-l:

I looked at the etherpad. I'm not sure who tested bash-5.2.2 (Nick?), but
you ended up running something that a vendor -- probably Ubuntu via Debian --
modified to add an error message.

I can't tell what `/tmp/script' is, but running bash-5.2.15 on RHEL7

$ ./bash --version
GNU bash, version 5.2.15(5)-release (x86_64-pc-linux-gnu)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> [^]

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

against the following script:

$ cat x10
echo a; echo b;
echo after: $?

exits with status 0 after a read error:

$ strace -e trace=read -e inject=read:error=ESTALE:when=7 ./bash ./x10
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\316\0\0\0\0\0\0"..., 832) = 832
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\16\0\0\0\0\0\0"..., 832) = 832
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`&\2\0\0\0\0\0"..., 832) = 832
read(3, "MemTotal: 1862792 kB\nMemF"..., 1024) = 1024
read(3, "echo a; echo b;\necho after: $?\n", 80) = 31
read(255, "echo a; echo b;\necho after: $?\n", 31) = 31
a
b
after: 0
read(255, 0x26d0290, 31) = -1 ESTALE (Stale file handle) (INJECTED)
+++ exited with 0 +++

You have to make sure you inject the error when bash is reading input
for the parser (the fifth read is checking whether or not the script is a
binary file). You'd get the same results with when=6.

You didn't check dash, but it returns 0 as well. I assume the other ash-
derived BSD shells behave similarly. yash is still the only shell that
returns an error in this case.
(0006145)
geoffclare   
2023-02-09 16:59   
The following is a proposed resolution for this bug, but it is not existing practice in almost all shells (they treat a read error like end-of-file) and so we would like feedback from shell authors to indicate whether they are willing to make changes to follow these new requirements. The rationale for requesting this change in behavior is that executing the partial line after getting a read error is really not a good thing for any shell to do. Consider a shell script that contains the command:
rm -f -- *.tmp
If the shell successfully reads "rm -f -- *" and then gets an error when it tries to read ".tmp", it will execute "rm -f -- *", resulting in data loss.

Please send feedback by March 9, 2023.

Add a row (D2.1 p2330) to the table in 2.8.1 Consequences of Shell Errors:
Read error when reading commands | shall exit *4 | shall exit *4 | yes

and add a new note after the table:
4. If a partial command was read before the read error occurred, that partial command shall not be executed.

Add to the exit status section of the sh utility on P3155 after L107008:
    
1-126
A read error was detected while reading commands.
    

Change P3155, L107009-107011 in the exit status section of the sh utility from:
1-125
A non-interactive shell detected an error other than command_file not found or executable, including but not limited to syntax, redirection, or variable assignment errors.

to:
1-125
A non-interactive shell detected an error other than command_file not found, command_file not executable, or a read error while reading commands; including but not limited to syntax, redirection, or variable assignment errors.
(0006158)
mirabilos   
2023-02-18 21:51   
(edited on: 2023-02-18 21:54)
I’m okay with the proposal. [DEL:-To clarify, this is for nōn-interactive shells only, and interactive shells treat it as EOF.-:DEL] (I only saw the table now, it doesn’t render well in lynx.) This changes read errors, independent of whether the shell is interactive or not, to require a diagnostic and for the shell to exit with an error code.

I think we can go around the “lawmaking” concern by looking at whether “all” shell maintainers agree to make the change, and if so, add it as requirement soon because it’ll be existing practice in all shells in a short while?

Can we not standardise on a code here, if we’re changing things anyway? From the proposal, 126 looks the most palatable to me, so change 1–126 to just 126 (again, if everyone agrees).

For the record, I’m very much willing to make this change to mksh.

(0006160)
chet_ramey   
2023-02-20 21:14   
How, if at all, does this affect the behavior of `.'?

I assume that this interpretation intends that read errors during execution of `.' are treated as fatal special builtin errors similar to pathname not found. If the shell parses the contents of the file as a program, the shell should handle read errors as it would when reading a shell script and treat them as a fatal error for `.', with the consequences that implies. Is that the intent?

Another question is exactly what constitutes a `partial command'. If you have a line that reads

echo a; echo b; echo c

and you get a read error after the second `;', this isn't exactly a `partial command'. It's a perfectly valid list. Or is this more intended to address partial lines?

Getting EOF while parsing a compound command like `while' is already a syntax
error, so this doesn't seem to make a difference there. It's mostly lists and pipelines.
(0006161)
mirabilos   
2023-02-20 22:47   
The ‘.’ behaviour definitely needs specifying and testing, yeah. I like your interpretation of not terminating the outer/calling script but allowing it to handle the error.

As for “partial commands”… this part is indeed tricky.

I’d like for the specification of this to move away from partial commands and also not to partial lines (as in the mail discussion with Chet, Bart and Robert). This would complicate the implementation, at least for cases where the shell can use blocked/buffered reads.

Without consideration for lines, I’d implement it in mksh like this, if the read(2) fails, then I just terminate immediately with an error (instead of an EOF). Anything that happened prior to this was executed, anything that would be executed if it were an EOF wouldn’t.

Hmm, so maybe partial command is right-ish, except not command but shell-consumable (let’s not add this word to the standard but I’m using it here to brainstorm) (a command is only consumable once terminated, e.g. by ; or newline), but… hmm…

… anyway. I would just put it in the place where more input is read. I experimented with this right now, and I can just plug a yyerror() in there (i.e. treating it as a simulated syntax error) and it’ll DTRT (even for dot) although with errorlevel 1 not 126. So this _seems_ to DTRT…
(0006163)
kre   
2023-02-21 05:58   
Rather that trying to deal with what a "partial command" might mean,
I'd rather simply say that if exiting, the shell shall not execute
any commands not yet already executed, except for the exit trap (if
one has already been defined). If the shell is not exiting (for which
the only case I can currently imagine is "command . file" in a non-interactive
shell, or any "." command in an interactive one) then the exit status should
be non-zero (I'm not sure it matters much if we attempt to define 126 for
that, or just anything).

Note that even an interactive shell "shall exit" if it gets a read error
on its standard input, nothing else makes any sense.

So, apart from adding something about read errors in the file used for a '.'
command, I'd change note 4 (*4) being added in section 2.8.1 to say

   *4 If a read error occurs, and the shell is to exit, the shell shall
       execute no further commands, other than any specified in a previously
       defined EXIT trap action.

And for the case of a '.' command failing due to a read error

    *5 If a read error occurs reading the file specified as the argument
       to the '.' command, the shell shall execute no commands from that file
       it has not already executed. The read error is then treated as a
       failure of the '.' command.

Does that make sense to everyone? Is it sufficient?
(0006167)
McDutchie   
2023-02-22 17:25   
(edited on: 2023-02-22 17:32)
Re Note: 0006145: "[...] so we would like feedback from shell authors to indicate whether they are willing to make changes to follow these new requirements."

Absolutely. I will fix this in ksh 93u+m regardless of what POSIX decides, because a failure to read from a script after execution has commenced is a fatal error that warrants throwing a panic. The possible execution of a partial command is one reason for this, but partially executing a script is not better. Either way, an inconsistent state results.

(0006168)
McDutchie   
2023-02-22 17:39   
Re Note: 0006158: "Can we not standardise on a code here, if we’re changing things anyway? From the proposal, 126 looks the most palatable to me, so change 1–126 to just 126 (again, if everyone agrees)."

Status 126 indicates failure to execute. I think that would be a bit misleading as the real problem here is a script read error after execution has successfully commenced.

I think 128 is the best exit status for such panic or fatal error conditions. It is the highest non-signal exit status (signals are > 128), and is not currently specified for anything (regular errors are < 126), leaving it free to signify that something unusual happened that requires urgent attention.

A precedent is git, which uses status 128 for fatal errors.
(0006192)
hvd   
2023-03-05 11:20   
> Status 126 indicates failure to execute. I think that would be a bit misleading as the real problem here is a script read error after execution has successfully commenced.

I agree. If existing programs or scripts have any special handling of exit code 126, they would rightly assume that no action has yet taken place and the failed command can safely be retried in another way. For read errors in the middle of a script that already partially executed, that is inappropriate.

But we are talking about scripts on unreliable media. They are going to fail unpredictably. They may result in read errors, they may result in bogus reads resulting in syntax errors, they may result in bogus reads resulting in valid scripts that do something other than what is intended. Because of that, scripts cannot meaningfully install handlers for read errors of the top-level script. And because of *that*, personally, I am not seeing a real benefit to requiring a specific exit code, I cannot see that being used in any meaningful way.

Shells already do not agree on what exit code to use for syntax errors, for unsupported options, etc. Shells already do not even agree on the exit code for scripts not being found, despite that actually being defined by POSIX. Mandating a particular exit code for this that cannot be meaningfully used, but not for the other ones that can, I see no point to it.
(0006195)
hvd   
2023-03-06 19:07   
(edited on: 2023-03-06 19:13)
On the possible special handling for 'command .': it makes sense that this would be treated the same as a syntax error in a file read by the command, but shells are not in agreement on what to do there and POSIX is less clear than it could be.

  echo \< >test
  command . ./test
  echo still here

In a non-interactive shell, what is the expected behaviour? "Consequences of Shell Errors" says that a non-interactive shell shall exit on "Shell language syntax error". The description of the command builtin says "If the command_name is the same as the name of one of the special built-in utilities, the special properties in the enumerated list at the beginning of Special Built-In Utilities shall not occur." Exiting on a syntax error is not one of the special properties in that list, so by my reading, that rule remains in full effect even in 'command .' and the fact that many shells print "still here" contradicts what I believe POSIX requires (without comment on whether POSIX is right to require this).

That same reading also applies to the proposed wording in Note: 0006145; a read error encountered during 'command .' should cause the shell to exit. This is a change I would be willing to make. I would not be happy to have these two cases be treated differently without a good reason, but if this is not the intended interpretation, I would also be happy to implement to-be-written alternative wording that would require the shell to survive syntax errors *and* read errors alike in 'command .'.

However, in interactive shells, read errors in a '.' should definitely not require the shell to exit, only read errors in the top-level script should have that effect. If a user does e.g. '. /proc/self/mem' (reading from the start of /proc/self/mem will fail with EIO), there is no reason not to allow the user to read more commands, that fd is still perfectly fine. The suggested wording does require the shell to exit in that case.

(0006196)
geoffclare   
2023-03-09 17:29   
New proposed resolution...

Add a row (D2.1 p2330) to the table in 2.8.1 Consequences of Shell Errors:
Read error when reading commands | shall exit *4 | shall exit *4 | yes


and add a new note after the table:
4. If a read error occurs when reading commands, other than from the file operand of the dot special built-in, the shell shall execute no further commands (including any already successfully read but not yet executed) other than any specified in a previously defined EXIT trap action. A read error while reading from the file operand of the dot special built-in shall be treated as a special built-in utility error.

      
Add to the exit status section of the sh utility on P3155 after L107008:
    
128
A read error was detected while reading commands, except from the file operand of the dot special built-in.
    

    
Change P3155, L107009-107011 in the exit status section of the sh utility from:
1-125
A non-interactive shell detected an error other than command_file not found or executable, including but not limited to syntax, redirection, or variable assignment errors.

to:
1-125
A non-interactive shell detected an error other than command_file not found, command_file not executable, or a read error while reading commands (except from the file operand of the dot special built-in); including but not limited to syntax, redirection, or variable assignment errors.
(0006197)
hvd   
2023-03-09 17:44   
The new proposed resolution would require 'command . /some/file' to exit the shell on syntax errors, but would also require to not exit the shell on read errors. This is inappropriate. The new proposed resolution requires an exit status of 126. This is also inappropriate.
(0006198)
geoffclare   
2023-03-10 09:20   
> The new proposed resolution would require 'command . /some/file' to exit the shell on syntax errors, but would also require to not exit the shell on read errors.

True, and this is a defect for the syntax error case, as existing shells do not exit.

> The new proposed resolution requires an exit status of 126.

It requires 128, not 126. The consensus in the teleconference was to agree with the comments that said 126 would not be appropriate, and also with the comments that said 128 would be a good choice.
(0006199)
hvd   
2023-03-10 10:57   
> True, and this is a defect for the syntax error case, as existing shells do not exit.

Some existing shells do not exit. Others do.

> It requires 128, not 126.

Apologies, I noticed the change to require a specific exit status and not that it had been changed from 126.
(0006200)
kre   
2023-03-10 14:52   
Re Note: 0006197 Note: 0006198 Note: 0006199 :

I agree it is probably a problem that shells exit on syntax errors after
"command ." (also "command eval") but it is a problem in the sense that
it would be better if that isn't what happened - and it isn't just "some
shells" that exit, it is most of them.

I also agree it would be better for syntax errors and read errors to be
treated the same for this. That is where we get a problem - read error
requirements are new, and we can more or less do what we like, since
everyone has more or less agreed that "treat it like EOF" which just about
everyone did is not the right thing to do, and shells are going to have
to change anyway.

But for syntax errors, most shells are doing what shells always have, and
what the standard requires - there even might be applications depending upon
this behaviour (though I don't think I have seen many "command eval" and
even less, if any "command ." in real scripts - and bash and zsh don't bother
exiting (bash in non-posix mode anyway) even without "command" so probably
there aren't applications that will care, but we cannot know.

In any case, this isn't a problem with the proposed resolution of this
issue (read error behaviour) - a new bug needs to be filed and processed
to get the behaviour of "command ." and "command eval" altered to be
"not exit" (and for this, it may need to start out just being "may exit"
rather than "shall not exit" with a future directions indicating that the
stronger form will apply in a later version.

Incidentally, it appears there is no way to prevent a shell from exiting
on a syntax error in a trap command string (action) - those are run
      "in a matter equivalent to eval action"
which must include in the interpretation, as if by a special builtin,
so if there is a failure to parse the action, the shell is currently
required to exit (non-interactive shells) which is probably sub-optimal.
(I haven't yet tested to see what shells actually do for this).
(0006201)
chet_ramey   
2023-03-10 21:33   
I'm going to change the bash behavior to exit immediately with status 128 on read errors while reading commands from a script.

I'm going to hold off changing any other behavior. Bash already reads an entire `.' file before parsing and executing any commands in it, so that's not going to be a problem.

I'd like to see the behavior of `command .' and `command eval' standardized so shells don't exit if the builtin fails, even with a read error, but I'm willing to have the discussion.
(0006210)
geoffclare   
2023-03-20 16:21   
Add a row (D2.1 p2330) to the table in 2.8.1 Consequences of Shell Errors:
Unrecoverable read error when reading commands | shall exit *4 | shall exit *4 | yes


and add a new note after the table:
4. If an unrecoverable read error occurs when reading commands, other than from the file operand of the dot special built-in, the shell shall execute no further commands (including any already successfully read but not yet executed) other than any specified in a previously defined EXIT trap action. An unrecoverable read error while reading from the file operand of the dot special built-in shall be treated as a special built-in utility error.


Change P3155, L107009-107011 in the exit status section of the sh utility from:
1-125
A non-interactive shell detected an error other than command_file not found or executable, including but not limited to syntax, redirection, or variable assignment errors.

to:
1-125
A non-interactive shell detected an error other than command_file not found, command_file not executable, or an unrecoverable read error while reading commands (except from the file operand of the dot special built-in); including but not limited to syntax, redirection, or variable assignment errors.

      
Add to the exit status section of the sh utility on P3155 after L107014:
128
An unrecoverable read error was detected while reading commands, except from the file operand of the dot special built-in.
    

    
On D2.1 page 358 line 12462 section <stdlib.h> (RATIONALE), change:
Exit statuses of 126, 127, and greater than 128 are ambiguous in certain circumstances because they have special meanings in the shell (see [xref to XCU 2.8.2]).

to:
Exit statuses of 126 and greater are ambiguous in certain circumstances because they have special meanings in the shell (see [xref to XCU 2.8.2] and the EXIT STATUS section of [xref to XCU sh]).


On D2.1 page 359 line 12469 section <stdlib.h> (RATIONALE), delete:
The value 128 is disallowed for simplicity, making the allowed values 1 to 125 inclusive rather than 1 to 125 inclusive and 128.


After D2.1 page 531 line 18867 section _Exit() (APPLICATION USAGE), add a new paragraph:
Exit statuses of 126 and greater are ambiguous in certain circumstances because they have special meanings in the shell (see [xref to XCU 2.8.2] and the EXIT STATUS section of [xref to XCU sh]).


After D2.1 page 789 line 27009 section exit() (APPLICATION USAGE), add a new paragraph (after applying bug 1490):
See also _Exit().


On D2.1 page 2370 line 76769 section exit (RATIONALE), change:
As explained in other sections, certain exit status values have been reserved for special uses and should be used by applications only for those purposes:

126 A file to be executed was found, but it was not an executable utility.

127 A utility to be executed was not found.

>128 A command was interrupted by a signal.

to:
As explained in other sections, certain exit status values have been reserved for special uses and should be used by applications only for those purposes:

126 A file to be executed was found, but it was not an executable utility.

127 A utility to be executed was not found.

128 An unrecoverable read error was detected by the shell while reading commands, except from the file operand of the dot special built-in.

>128 A command was interrupted by a signal.

On page 3238 line 110033 section tsort (RATIONALE), after applying bug 1617 change:
Implementations are urged to set the implementation-defined maximum number of cycles reported via the exit status to at most 125, leaving 128 for other errors, and leaving 126, 127, and values greater than 128 to have the special meanings that the shell assigns to them. (An implementation that wants to distinguish other types of errors would need to set the maximum to less than 125 so that 128 is not the only code available for those errors).

to:
Implementations are urged to set the implementation-defined maximum number of cycles reported via the exit status to at most 124, leaving values above that maximum through 125 for other errors, and leaving values 126 and greater to have the special meanings that the shell assigns to them.




Viewing Issue Advanced Details
1628 [Online Pubs] Shell and Utilities Editorial Enhancement Request 2023-01-15 17:18 2023-01-22 19:29
mirabilos
 
normal  
New  
Open  
   
mirabilos
MirBSD
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/xargs.html [^]
xargs(1)
Add -o (reopen stdin) option to xargs(1)
Now that 243 is accepted, I would like to request the addition of another option to xargs(1) to make it really useful. It’s a BSD thing:

     -o Reopen stdin as /dev/tty in the child process before executing
             the command. This is useful if you want xargs to run an interac-
             tive application.

I’ve been using this a *lot*, as something like…

$ git find \*.h -print0 | xargs -0o $EDITOR

… (where https://github.com/mirabilos/git-find/ [^] is the tool in question), or with just a simple find, or a (git) grep -Z. I also have been able to successfully convince GNU coreutils to add precisely this (they also added a GNU --long-option but added it with -o for BSD compatibility). (I know I should use -0or but I lazily skip the -r if I know there’s at least one anyway.)
In SYNOPSIS, change -0ptrx to -0optrx.

In DESCRIPTION, where it says the results are unspecified if the utility reads from stdin, add unless the -o flag is given.

In OPTIONS, add:

.It Fl o
Reopen stdin as
.Pa /dev/tty
in the child process before executing the command.
This is useful if you want
.Nm
to run an interactive application.

In INPUT FILES, mention that -o also uses /dev/tty.

Possibly add a suitable example; do we have grep -Z yet in POSIX (it’s not in 243)? Otherwise, 'find . -name \*.h -print0 | xargs -0or $EDITOR' will probably do.
Notes
(0006111)
oguzismailuysal   
2023-01-15 17:57   
I don't think this is a good example:

    find . -name \*.h -print0 | xargs -0or $EDITOR

xargs is not even necessary there. See:

    find . -name '*.h' -exec "$EDITOR" {} +
(0006112)
stephane   
2023-01-16 08:12   
Note that with cmd1 | xargs -r0o cmd2 --, cmd2's stdin is /dev/tty even when that command is in a script and that script has its input redirected.

GNU xargs'

xargs -r0a <(cmd1) cmd2 --

Is better IMO as cmd2's stdin is the script's stdin, not the pipe nor /dev/null nor /dev/tty, though that needs a shell with process substitution support which is not in POSIX yet (and means the exit status of cmd1 is lost in most shells, even with the pipefail option on).

In any case, both can be done already with the current proposed spec albeit quite awkwardly:

cmd1 | xargs -r0 sh -c 'exec cmd2 -- "$@" < /dev/tty' sh

for the first

{ cmd1 3<&- | xargs -r0 sh -c 'exec cmd2 -- "$@" <&3 3<&-' sh; } <&0

for the second (where cmd1's exit status is not lost if using pipefail).
(0006117)
mirabilos   
2023-01-20 20:46   
oguzismailuysal wrote:

> find . -name '*.h' -exec "$EDITOR" {} +

Most people I know can never remember the -exec syntax and avoid advanced use of find(1). But the aforementioned “git find” as well as various greps etc. do not offer this anyway, and it’d be good to have it for symmetry. Using find(1) is just concocting an easy-to-remember example… *especially* as you can go from there to …-print0 | while IFS= read -rd '' file; do… immediately.


stephane wrote:

> xargs -r0a <(cmd1) cmd2 --

Yuk, that’s even GNU bash-specific.

> Note that with cmd1 | xargs -r0o cmd2 --, cmd2's stdin is /dev/tty even
> when that command is in a script and that script has its input redirected.

Yes, that’s a good thing.

> quite awkwardly:

Same thing as above: nobody’s going to remember these.

IIRC the people in GNU coreutils mentioned the same but decided to implement BSD’s -o nevertheless because of its utility in making things better for users and consistent across OSes.
(0006119)
gbrandenrobinson   
2023-01-20 21:12   
"Yuk, that’s even GNU bash-specific."

No, that goes back farther, at least to Tom Duff's rc shell, which was implemented more famously for Plan 9 from Bell Labs but also for Tenth Edition Research Unix (1989).

https://ftp.gwdg.de/pub/gnu2/rc/plan9.ps [^]
(0006121)
mirabilos   
2023-01-20 21:50   
I meant the use of the <(…) construct here that’s necessary to make this somewhat writabl…ish.

(But still not as good as the easily pluggable xargs solution; same argument as for -exec really, you can add xargs to inspect part of the pipeline, then put something else there instead.)
(0006129)
stephane   
2023-01-22 19:29   
(edited on: 2023-01-24 09:58)
Re: Note: 0006117

> > xargs -r0a <(cmd1) cmd2 --
>
> Yuk, that’s even GNU bash-specific.

There's nothing bash-specific in there. Process substitution is from ksh (first documented in ksh86), and is also found with that syntax in zsh (since 1990) and bash (since 1993). In yash, <(cmd) is process redirection, /dev/fd/3 3<(cmd) there works similarly to ksh's <(cmd).

rc, es, akanga, fish also have process substitution support, though with different syntaxes.

That's quite an essential feature.

I suspect one of the reasons it was not specified by POSIX back then was because in ksh88 at the time, it only worked on systems that had /dev/fd/x support. Other shells (including recent versions of ksh93) can resort to named pipe (zsh and Byron Rakitzis's rc clone originally were only using named pipe, likely because they were developed on systems without /dev/fd)





Viewing Issue Advanced Details
1627 [1003.1(2016/18)/Issue7+TC2] System Interfaces Objection Enhancement Request 2023-01-05 12:17 2023-01-20 20:54
kre
 
normal  
New  
Open  
   
Robert Elz
XSH 3/mktime
1331
44310-44332, 44361
---
XSH 3 / mktime() is woefully underspecified
Following on from notes added to bug:1614 and a lengthy
mailing list discussion, it is evident that the specification
of XSH/mktime is woefully inadequate.

New text is specified in the Desired Action to remedy those defects.

This is currently missing anything dealing with what should be done
if the input tm_isdst is not < 0, and does not agree (in sign, if 0
can be said to have a sign) with the final value for tm_isdst in the
struct tm on a successful return.

That's because my inclination is to simply do nothing in that case,
return the correct tm_isdst, but otherwise ignore it - but I admit that's
not how the implementations behave, and that may be being depended upon
by some applications (though the current behaviour is definitely not
required by any standard). So I will leave it for someone who cares
about that to add suitable text to (properly) specify what is to happen.

Also, given that it is too late now to consider adding a timegm()
function (an analog to mktime() which has existed for decades, but
never been standardised) I thought what might be possible would be
to specify enough in the FUTURE DIRECTIONS here to indicate that that
will happen (since it is being added to the C standard, it will happen,
eventually) and to indicate why using it is a much better idea when
the purpose is time_t arithmetic than using localtime()/mktime().
The intent is to get applications to start writing safe code, rather
than nonsense, and do that asap - since in practice, timegm() is
already widely available.

As usual, formatting and wording changes, which keep to the general
intent expressed below are welcome. One thing I considered, but
wasn't sure of a good way to handle, was to find some shorter way
to express "the converted value of the struct tm referred to by
timeptr" (or a field thereof) - which occurs far too often in the
text below, and is unwieldy.

Delete the (CX shaded) paragraph that starts (line 44310)

        A positive or 0 value for tm_isdst ...
and ends (line 44313)
        ... is in effect for the specified time.

Replace the (CX) shaded paragraph that starts (line 44315)

        The relationship between the tm structure ...
and ends(line 44321)
        ... the other tm structure members specified in <time.h>
        (excluding tm_wday).

with the following (presumably also CX shaded) paragraphs:

        The mktime() function will first convert the tm_sec, tm_min,
        tm_hour, tm_mon, tm_mday and tm_mon (again) fields of the tm
        structure referenced by timeptr (or a local internal copy thereof),
        in that order, so that their values become within the ranges specified
        by <time.h>, but also within the ranges applicable to a Gregorian
        Calendar date (tm_sec shall not be more than 59, and tm_mday shall
        not be more than the number of days in the month specified by
        the tm_mon field of the year specified by the tm_year field).

        If _field_ represents the field being converted, and _next_
        represents the field specified immediately after it in <time.h>
        then this shall be done, for each field, by an algorithm equivalent
        to:

                if (timeptr->_field_ < MINIMUM_VALUE) {
                        while (timeptr->_field_ < MINIMUM_VALUE) {
                                timeptr->_field_ += RANGE;
                                timeptr->_next_--; /* check overflow */
                        }
                } else if (timeptr->_field_ > MAXIMUM_VALUE) {
                        while (timeptr->_field_ > MAXIMUM_VALUE) {
                                timeptr->_field_ -= RANGE;
                                timeptr->_next_++; /* check overflow */
                        }
                } /* else do nothing, value of _field_ is OK */

        where MINIMUM_VALUE is the minimum allowed value for the
        field _field_ as specified in <time.h> MAXIMUM_VALUE is the
        maximum allowed value for the field _field_ as specified in
        <time.h> except that it shall be 59 where _field_ is tm_sec,
        and shall be the appropriate number of days in the specific
        month selected by the tm_mon and tm_year fields, where _field_
        is tm_mday, and thus is subject to change during each iteration
        of the loop, and RANGE is (MAXIMUM_VALUE - MINIMUM_VALUE + 1)
        (which is also subject to change, in each iteration of both loops
        above, where the field is tm_mday).

        Note that there is no requirement that the actual structure
        passed via *timeptr be the one being modified by this code.

        Should overflow (absolute value of the field becomes too large
        to be represented in an int) occur at the places indicated,
        the implementation shall return an error if the _next_ field is
        tm_year, and may return an error for other fields, though if
        _next_ is not tm_year, it may adjust the value of any later field,
        and reduce the magnitude of the _next_ field by an appropriate
        amount to compensate. Adjustments made this way should be chosen
        so as to minimise the effects of the adjustment upon the meaning
        of the later field, for example, if tm_hour were to overflow,
        the implementation might adjust tm_mday by 146101 (the number of
        days in a 400 year period - since in the Gregorian calendar, that is
        a constant) and reduce the magnitude of tm_hour by 3506424 (24*146101,
        the number of hours in 400 years). Alternatively it might alter
        tm_mon by 4800 (the number of months in a 400 year period), and
        adjust tm_hour by the same amount (3506424). Overflow produced
        when making any such adjustment should be handled in a similar
        way, including, if an adjustment to tm_mon requires an adjustment
        to tm_year, and that causes tm_year to overflow, then an error
        shall be returned.

        The tm_isdst field of the structure referred to by timeptr (or
        a local copy thereof) shall be converted by altering any
        value that is less than 0 to be -1, and any value that is
        greater than 0 to be 1. If supplied as 0, no change shall
        be made.

        Once all fields are within the appropriate ranges, the
        implementation shall determine if there is a unique value
        of the type returned by time() (which is expressed as a value
        in Coordinated Universal Time) which when converted to a
        struct tm by a function equivalent to localtime() would
        produce identical values for the tm_sec tm_min tm_hour tm_mday
        tm_mon and tm_year fields of the converted input struct tm.
        This may be accomplished by applying a formula, similar to
        that specified for Coordinated Universal Time in <xref XBD 4.17>
        adjusted to account for local timezone offsets, and time
        alterations, or by any other means.

        If such a unique result is found, then that shall be the
        result from mktime().

        If no result is found because the tm structure represents
        a value outside the range of values that can be represented
        by a value returned by time(), then an error shall be returned.

        Otherwise if no result is able to be found, then the local time
        specified represents a time which does not exist as a local time
        value. In this case, if the value of tm_isdst in the struct tm
        specified by timeptr is greater than or equal to 0, and there
        are two values or the type returned by time(), representing times
        that are one second apart, (t1 and t2, where t2 == t1 + 1 second)
        which can be found of the type returned by time(), such that
        one of those, when converted by a function equivalent to localtime()
        returns a time which occurs before the converted time referred to
        by timeptr, and the other returns a time which occurs later, and
        also one of those would produce a struct tm with tm_isdst == 0,
        and the other when converted by localtime would produce a struct tm
        with tm_isdst == 1, then if the application's converted tm_isdst
        field the same as that produced by t1, then the implementation
        shall calculate the difference, in seconds, between the converted
        time specified by timeptr, and that produced by a conversion of t1,
        add the number of seconds to t1, and that shall be the result of
        mktime. Otherwise, if the applications converted tm_isdst is
        the same as that produced by t2, the implementation shall
        calculate the difference (in seconds) between the struct tm
        produced by t2, and that specified by the converted struct tm
        referred to by timeptr, and subtract that number of seconds from
        t2, and that shall be the result from mktime(). In any other
        case the result is unspecified. The implementation may
        arbitrarily return one of the results as if it had been one of
        the two specified cases, or may return an error.

        If more than one possible result is found, then if there are
        exactly two possible results, and one of those, when converted by
        a function equivalent to localtime(), produces a value with tm_isdst
        having the same value as the converted value of that field in the
        struct tm referred to by timeptr, and the other does not, then
        the result of mktime() shall be the single unique result which
        produces a struct tm with the same tm_sec tm_min tm_hour tm_mday
        tm_mon tm_year and tm_isdst fields as the converted values in the
        struct tm referred to by timeptr. In any other case, the result
        is unspecified. The implementation may arbitrarily return any
        of the plausible ambiguous results, or may return an error.

This should then be followed by the new (bug 1613 inserted) text about
what happens to the struct tm in the case of a successful return. This
I believe has already replaced the "Upon successful completion, the values
of the tm_wday..." paragraph. If not, delete whatever is left of it.

A new paragraph (or just sentence perhaps) should be added after the 1613
inserted paragraph:

        When mktime() returns an error, the contents of the structure
        referred to by timeptr, after mktime() returns, shall be unspecified.

The RETURN VALUE section (lines 44327-9) should be replaced by:

        The mktime() function shall return the calculated time since the
        epoch, as specified in the DESCRIPTION, encoded as a value of
        type time_t. If an error is to be returned, then the function
        shall return the value (time_t)-1, and set errno to indicate the
        error.

The ERRORS section (lines 44331-2) should be replaced by

        The mktime() function shall fail if:

        [EOVERFLOW] The value of the time returned by time() which
                        represents the converted struct tm passed by
                        timeptr falls outside the range of values that
                        can be represented as a time_t.

        [EOVERFLOW] While correcting the values of the fields of the
                        struct tm referred to by timeptr to be within the
                        required ranges, a required adjustment of the tm_year
                        field caused that field to overflow.

        The mktime() function may fail if:

        [EOVERFLOW] Adjusting a field of the struct tm referred to
                        by timeptr caused an adjustment to be required to
                        another field, and that adjustment caused that other
                        field to overflow.

        [EINVAL] The converted struct tm referred to by timeptr
                        cannot be represented by a unique number of seconds
                        past the epoch, Coordinated Universal Time, and
                        the input values, and/or circumstances are not such
                        that an alternative is required to be selected.

In the FUTURE DIRECTIONS section (line 44361) replace "None." by

        A later edition of the standard is expected to add a timegm()
        function that is similar to mktime(), except that the struct tm
        referred to by timeptr represents a calendar time in Coordinated
        Universal Time (rather than the local time zone), where references
        to localtime() are replaced by references to gmtime(), and where
        there are no zone offset adjustments, or missing or ambiguous times,
        tm_isdst is always 0, and EINVAL cannot be returned. A combination
        of gmtime() and timegm() will be the expected way to perform
        arithmetic upon a time_t value and remain compatible with the C
        standard (where the internal structure of a time_t is not specified).
        Attempting such manipulations using localtime() and mktime() can lead
        to unexpected results.
Notes
(0006118)
mirabilos   
2023-01-20 20:54   
Don’t break mktime of a valid struct with tm_sec=60 pointing to a leap second, please.




Viewing Issue Advanced Details
1626 [Issue 8 drafts] Shell and Utilities Editorial Clarification Requested 2023-01-04 22:25 2023-03-10 10:51
illiliti
 
normal  
Applied  
Accepted As Marked  
   
Mark Lundblad
make
2945
98797
Note: 0006130
Reconsider CURDIR macro
0000338 rejected CURDIR macro due to lack of consensus. However, since current standard has no simple and reliable way to replicate it, I propose to reconsider this decision.

I've checked some implementations and found no serious incompatibilities that would prevent CURDIR from standardizing. The GNU make and smake(from schilytools) provide this macro as extension and both compatible with each other, whereas *BSD make requires leading dot(.CURDIR) and has special handling for PWD environment variable, but despite that it is semantically compatible with GNU make and smake because its CURDIR will always point to the current working directory and that's all we need. So BSD make can simply alias CURDIR to .CURDIR and be compatible with the rest implementations.

As of related -C option, I decided to omit it in this proposal because it requires more work regarding how -f option should work with it, how MAKE macro should be affected, etc... It is simply more than one addition and thus I believe it should be discussed in a separate proposal.
On page 2945 line 98797, add a new paragraph:


The CURDIR macro shall be treated specially. It shall be provided by make and set
to the pathname of the directory where make was executed. The CURDIR environment variable shall not affect the value of the CURDIR macro. If CURDIR is defined in the makefile or is specified on the command line, it shall replace the original value of the CURDIR macro, but shall not cause make to change its current working directory.
Notes
(0006130)
geoffclare   
2023-01-23 17:22   
On page 2944 line 98775 section make, change:
Other implementation-defined options and macros may also be added to the MAKEFLAGS macro.
to:
Other implementation-defined options and macros, with the exception of the CURDIR macro, may also be added to the MAKEFLAGS macro.

After page 2945 line 98797 section make, add a new paragraph:
The CURDIR macro shall be treated specially. It shall be provided by make and set to an absolute pathname of the current working directory when make is executed. The value shall be the same as the pathname that would be output by the pwd utility with either the -L or -P option; if they differ, it is unspecified which value is used. The CURDIR environment variable shall not affect the value of the CURDIR macro unless the -e option is specified. If the -e option is not specified, there is a CURDIR environment variable set, and its value is different from the CURDIR macro value, the environment variable value shall be set to the macro value. If CURDIR is defined in the makefile, present in the MAKEFLAGS environment variable, or specified on the command line, it shall replace the original value of the CURDIR macro in accordance with the logical order described above, but shall not cause make to change its current working directory.




Viewing Issue Advanced Details
1625 [1003.1(2016/18)/Issue7+TC2] Base Definitions and Headers Objection Omission 2023-01-04 02:18 2023-01-19 17:29
philip-guenther
 
normal  
Resolved  
Accepted  
   
Philip Guenther
OpenBSD
waitid
waitid
111
3066
---
waitid should be marked as aync-signal-safe and a memory-synchronization point
(I only have issue 7 on hand, so section and line references will be off)

I believe that, historically, waitid() has been implemented in a manner similar to waitpid(), with an underlying system call and synchronization inside the kernel. Because of that, it has had the same sort of intrinsic behaviors described for wait() and waitpid() in XBD 4.12, "Memory Synchronization" and in XSH 2.4.3's for async-signal-safe functions. However, when it was added to the standard it was not included in those lists.
Add waitid() to the lists of both the memory synchronization and async-signal-safe functions.
Notes
(0006097)
geoffclare   
2023-01-05 09:15   
Moved to 1003.1(2016/18)/Issue7+TC2 project so that the page and line numbers match the document.




Viewing Issue Advanced Details
1624 [Issue 8 drafts] System Interfaces Comment Clarification Requested 2022-12-22 11:20 2023-03-10 10:50
romanzilka
 
normal  
Applied  
Accepted As Marked  
   
Roman Žilka
getdelim()
1017-1019
34871-34961
Note: 0006114
getdelim() / getline() non-success reporting clarification
getdelim() and getline() are required (Draft 2.1, Issue 7 / 2018) to, among other things, set the stream error indicator "if an error occurs". The errors defined include EINVAL, ENOMEM and EOVERFLOW. These are conditions unrelated to I/O on the stream and there may be doubt whether the function should actually set the ferror. The current glibc implementation, for instance, will not set it for EINVAL, nor possibly for the other two. Please, clarify either here or in the standard.
I will leave this decision to the more experienced. As a user of these interfaces, I expect a deterministic means of finding out what happened when a call returns -1. If getdelim() is indeed supposed to set ferror (to make it short) on *all* errors, I can use ferror() / feof() to tell. If some errors only produce the -1 and an errno, but not ferror, I cannot tell for (feof() && ! ferror()), whether an error occurred as well and I can refer to errno. The example given for getline() in POSIX and the note about feof()/ferror() in Application Usage are thus not quite correct. They're incorrect, in fact, even for (! feof() && ! ferror()).

All this while I am assuming that the eof and ferror conditions are mutually exclusive. That is not explicitly stated anywhere in POSIX or C (not C99 anyway, that's the only one I have available), AFAIK, but the wording strongly suggests so in C99, 7.19.7.1 and in POSIX in the Application Usage in multiple functions. C literally mentions that "feof and ferror" can be used to tell the eof/ferror conditions apart, which sounds just a bit like one may need both, but let's suppose that either one is sufficient. POSIX talks about "ferror() or feof()", which leaves little space for doubt. Still, clarification may be in order in this matter, too.

Note, however, that this mutual exlusion may be impossible to maintain. A run of getdelim() may successfully read some data, advance to eof, so that feof()==true, and then encounter an error unrelated to I/O, e.g., ENOMEM allocating space for the '\0'. Another example is the eof condition at the very start of getline() while also EINVAL. A solution to the latter may be prioritizing an eof check before any error check in getline(), but that doesn't follow from POSIX and, once again, glibc won't do that.

Similar issues may be present in other stdio functions doing I/O on a stream. fgetc() seems to address the mut. ex. issue in saying outright in Description that an eof check is made prior to any reads. That's not sufficient, though, when other errors besides I/O ones can happen. Note also that fgetc() is required to set ferror if "a read error occurs", not just any error, as the section on getdelim() is putting it. One of the optional errors defined for fgetc() is ENOMEM, however, which brings us back to the beginning. Granted, I'm not sure how ENOMEM happens there.
Notes
(0006114)
geoffclare   
2023-01-19 17:19   
On page 851 line 28924 section fgetc(), and
page 855 line 29054 section fgets(), and
page 859 line 29223 section fgetws(), and
page 945 line 32390 section fscanf(), change:
If a read error occurs, the error indicator for the stream shall be set, ...

to:
If an error occurs, the error indicator for the stream shall be set, ...


On page 857 line 29144 section fgetwc(), change:
If a read error occurs, the error indicator for the stream shall be set, ...

to:
If an error other than an encoding error occurs, the error indicator for the stream shall be set, ...


On page 857 line 29145 fgetwc(), change:
    
If an encoding error occurs, the error indicator for the stream shall be set, ...

to:
    
If an encoding error occurs, [CX]the error indicator for the stream shall be set,[/CX] ...


On page 858 line 29174 section fgetwc(), change RATIONALE from "None" to:
The requirement to set the error indicator when an encoding error occurs is shaded CX because this is not required by the ISO C standard. However, the next revision of the ISO C standard is expected to add this requirement.


On page 921 line 31501 section fread(), change:
The fread() function shall return the number of elements successfully read, which shall be less than nitems only if a read error or end-of-file is encountered. If size or nitems is 0, fread() shall return 0 and the contents of the array and the state of the stream remain unchanged. Otherwise, if a read error occurs, the error indicator for the stream shall be set, [CX]and errno shall be set to indicate the error.[/CX]

to:
The fread() function shall return the number of elements successfully read, which shall be less than nitems only if an error or end-of-file is encountered, or size is 0. If size or nitems is 0, fread() shall return 0 and the contents of the array and the state of the stream shall remain unchanged. Otherwise, if an error occurs, the error indicator for the stream shall be set, [CX]and errno shall be set to indicate the error.[/CX]




Viewing Issue Advanced Details
1623 [Online Pubs] Main Index Editorial Omission 2022-12-09 08:17 2023-01-20 07:10
illiliti
ajosey  
normal  
Under Review  
Rejected  
   
Mark Lundblad
https://pubs.opengroup.org/onlinepubs/9699919799/ [^]
-
website inaccessible via ipv6
https://pubs.opengroup.org/onlinepubs/9699919799/ [^] is not reachable over ipv6.
Add AAAA DNS records to pubs.opengroup.org
Notes
(0006115)
ajosey   
2023-01-20 07:09   
I checked with our technical team apparently this is non trivial for
the mirrored, load balancing setup we have with AWS for the publications server.
(0006116)
ajosey   
2023-01-20 07:10   
As such we have no plans to make changes to our infrastructure at this time.




Viewing Issue Advanced Details
1622 [Issue 8 drafts] System Interfaces Editorial Enhancement Request 2022-12-04 04:55 2022-12-04 04:55
illiliti
 
normal  
New  
Open  
   
Mark Lundblad
System Interfaces
-
-
Standardize getpeereid function
This function provides a mechanism to get credentials of a peer that
created/initialized unix socket. Such mechanism is useful for AF_UNIX servers
and clients that need a reliable way to know each other's credentials to
implement e.g. accounting or authorization. See also: https://cr.yp.to/docs/secureipc.html [^]

It is quite portable and already implemented at least in QNX, AIX, FreeBSD,
NetBSD, OpenBSD, Cygwin. Linux and Illumos/Solaris provide similar interfaces,
though they don't look suitable for inclusion. Linux SO_PEERCRED is incompatible
with OpenBSD due to a different structure name, whereas Illumos/Solaris
getpeerucred() is just terrible; it allocates memory and requires a dedicated
function to free it.

I also evaluated LOCAL_PEERCRED from FreeBSD and LOCAL_PEEREID from NetBSD that
are used there to power getpeereid(). LOCAL_PEERCRED uses structure which has
platform-specific type in it, so I immidiately rejected it. As of LOCAL_PEEREID,
it looks fine, but I afraid if we going to standardize it, it'll cause friction
in systems that already provide similar(and potentially incompatible)interface in
getsockopt(). Therefore let's just add getpeereid.
Standardize getpeereid function. The following man page is a splice of OpenBSD
and NetBSD man pages with some modifications to take into the account other
systems.


NAME

getpeereid - get effective user and group identification of locally-
connected peer

SYNOPSIS

#include <sys/types.h>
#include <sys/socket.h>

int getpeereid(int socket, uid_t *uid, gid_t *gid);

DESCRIPTION

getpeereid() returns the effective user and group IDs of the peer connected
to a socket in the UNIX domain. If argument uid or gid is NULL, the behavior
is unspecified.

The argument socket shall be AF_UNIX socket of type SOCK_STREAM or
SOCK_SEQPACKET on which either connect(2) has been called, or one returned
from accept(2) after bind(2) and listen(2) have been called, or one returned
from socketpair(2).

The credentials returned to the accept(2) caller are those of its peer at
the time it called connect(2). The credentials returned to the connect(2)
caller are those of its peer at the time it called bind(2) and listen(2).
In the case of socketpair(), the returned credentials are those that were
at the time of the call to it.

RETURN VALUES

If the call succeeds, a value of 0 is returned and uid and gid are set to the
effective user ID and group ID of the connected peer. Otherwise, errno is set
and a value of -1 is returned.

ERRORS

On failure, errno is set to one of the following:

[EBADF] The argument socket is not a valid descriptor.

[ENOTSOCK] The argument socket is a file, not a socket.

[ENOTCONN] The socket is not connected.

[EOPNOTSUPP] The socket is not in the UNIX-domain.

[EINVAL] The argument socket does not refer to a socket of type SOCK_STREAM
         or SOCK_SEQPACKET, or the system returned invalid data.
There are no notes attached to this issue.




Viewing Issue Advanced Details
1621 [1003.1(2016/18)/Issue7+TC2] Base Definitions and Headers Editorial Clarification Requested 2022-12-02 17:30 2023-01-09 17:18
steffen
 
normal  
Resolved  
Accepted As Marked  
   
steffen
Definitions (3.250 + 1), System Interfaces (getdelim())
73, 1026
2121 + 1, 34991
---
See Note: 0006104.
Add "null terminator" definition, adjust getdelim(3) usage accordingly
The standard contains usages of "null terminator", documenting only "null byte" terminators. It uses "NUL terminator" at one place (added in Issue 7 for getdelim() said Geoff Clare on austin-group-l@ in Y4nXMYB9tFwxeYx5@localhost).

I mention i personally only ever used NUL (the "character" name in ISO 646 / LATIN1 / Unicode) for any such purpose, but the standard defines C-style "3.375 String"s indeed as "A contiguous sequence of bytes terminated by and including the first null byte".

So here the clarification request.
On page 73, insert after line 2121

 3.251 Null terminator
 A term used for the Null Byte of Section 3.248 when used as a terminator for String of Section 3.375 (on page REF).

On page 1026, for getdelim(3), change on line 34991

  Although a NUL terminator is always supplied after the line[.]

to

  Although a null terminator is always supplied after the line[.]
Notes
(0006104)
Don Cragun   
2023-01-09 17:16   
On page 73, insert after line 2121:
3.251 Null Terminator
 
A term used for the null byte when used as a terminator for a string.


On page 1026, for getdelim(3), change on line 34991:
Although a NUL terminator is always supplied after the line...
to:
Although a null terminator is always supplied after the line...




Viewing Issue Advanced Details
1619 [Issue 8 drafts] Base Definitions and Headers Comment Enhancement Request 2022-11-18 12:21 2023-01-17 11:45
geoffclare
 
normal  
Applied  
Accepted As Marked  
   
Geoff Clare
The Open Group
8.3
161
5616
See Note: 0006076
Add support for TZ=Area/Location
Support for TZ values that use the Area/Location format is very widespread and it should be added to the standard.
On page 161 line 5616 section 8.3, change:
The value of TZ has one of the two forms (spaces inserted for clarity):
:characters
or:
std offset dst offset, rule
If TZ is of the first format (that is, if the first character is a <colon>), the characters following the <colon> are handled in an implementation-defined manner.

The expanded format (for all TZs whose value does not have a <colon> as the first character) is as follows:
to:
The application shall ensure that the value of TZ has one of the three forms (spaces inserted for clarity):
:characters
or:
Area/Location
or:
std offset dst offset, rule
If TZ is of the first format (that is, if the first character is a <colon>), the characters following the <colon> are handled in an implementation-defined manner.

If TZ is of the second format (that is, if the first character is not a <colon> and the value includes one or two <slash> characters and no <comma>, <less-than-sign>, or <greater-than-sign> characters), Area and Location together indicate either a geographical timezone or a special timezone from an implementation-defined timezone database. If the value contains two <slash> characters, the separator between Area and Location is the first <slash> and the second <slash> is part of Location. Examples of geographical timezones that may be supported include <tt>Africa/Cairo</tt>, <tt>America/Indiana/Indianapolis</tt>, <tt>America/New_York</tt>, <tt>Asia/Tokyo</tt>, and <tt>Europe/London</tt>. The data for each geographical timezone shall include:

  • Whether Daylight Saving Time (DST) is observed, and if so the rules used to determine when the transitions to and from DST occur.

  • The offset from Coordinated Universal Time of the timezone's standard time and, if observed, of its DST.

  • The timezone names for standard time (std) and, if observed, for DST (dst) to be used by tzset(). These shall each contain no more than {TZNAME_MAX} bytes.
If there are any historical variations, or known future variations, of the above data for a geographical timezone, these variations shall be included in the database, except that historical variations from before the Epoch need not be included.

The database should incorporate the geographical timezones from the IANA timezone database and the implementation should provide a way to update it in accordance with RFC 6557; if these recommendations are not followed, an implementation-defined way to update the database shall be provided.

Implementations shall support the special timezone <tt>Etc/UTC</tt> and may support other special timezones from the IANA timezone database or additional implementation-defined special timezones. The behavior for <tt>TZ=Etc/UTC</tt> shall be identical to <tt>TZ=UTC0</tt> (see below).

The expanded form of the third format (without the inserted spaces) is as follows:

On page 3460 line 118332 section A.8.3, change:
Implementations are encouraged to use the time zone database maintained by IANA to determine when Daylight Saving Time changes occur and to handle TZ values that start with a <colon>. See RFC 6557.
to:
Implementations are encouraged to incorporate the IANA timezone database into the timezone database used for TZ values of the form Area/Location and to provide a way to update it in accordance with RFC 6557.

The TZ format beginning with <colon> was originally introduced as a way for implementations to support geographical timezones in the form :Area/Location as an extension, but implementations started to support them without the leading <colon> (as well as with it) and their use without the <colon> became the de-facto standard. Consequently when geographical timezones were added to this standard, it was without the <colon>. However, this format is only specified as being recognized when the value includes one or two <slash> characters; portable applications still need to include the <colon> in order to specify any geographical timezone value that does not include any <slash> characters.

Notes
(0006065)
steffen   
2022-11-18 21:44   
Area/Location, yes.

This is an all-english thing with sometimes strange names that are rather specific to IANA TZ, or for direct consumers of that as a citizen.

Just a suggestion.

The ICU project maintains several mappings that may serve actual users better.

For one there is one that includes countries. It is still all english, but translatable. The hypthetic America:Argentina:Buenos_Aires may serve users better.

There are also UN Locode mappings. UN Locode support should possibly be support ed or reserved as trade will continue to be the thing, i would suggest via leading @ plus the five letters which makes up a Locode entry.
I would presume these Locode IDs become known more and more in the future.

kre@ knows both much better and for longer, but IANA TZ over and over discusses the syntax and content of the Area/Location IDs as such, and whereas i would assume backward-compatibility will not be lost, i could imagine a new maintainer (the current one is on the austin ML and reads this, sufficient time provided) switches to a new format that serves ISO 3166 country codes much better, and ISO 3166 country codes are the base (root level) of UN Locodes.
(0006068)
kre   
2022-11-19 18:23   
Re Note: 0006065

Not so much English Language (though that is what the tz database uses)
as POSIX Portable Character Set (XBD 6) - which is all that implementations
are required to accept, and hence all that the standard can actually require.

I can accept the text in the Desired Action, though I would have specified
rather less about the new format, instead of requiring a '/' and no ','
I would have simply allowed any strng not starting with ':' (which remains
as it has been for ages) and which does not match
         ^[[:alpha:]]+[+-]?[[:digit:]]+
(as an ERE) (add ".*$" to make it anchored both ends if desired).
This is easy enough to specify in words, rather than as an ERE, if that
achieves a better result.

That would allow a large variety of naming schemes, rather than committing
to one, when the actual name is not all that important to anything,
what is more important is the data it provides, and the specification of
what is required for that looks OK.

For the specification, if this variation is reasonable, I'd make that
pattern be the 2nd case, and have it be one that matches the TZ value,
rather than one which does not (and then represents a current TZ specified
string ("std offset dst offset, rule") and then have the third case be "any
other string", and be the new one.
(0006073)
geoffclare   
2022-11-21 09:59   
(edited on: 2022-11-21 10:02)
Here's some alternative wording that disambiguates the 2nd and 3rd formats the way kre suggests (and swaps them round).

I don't have any preference between the original wording in the desired action and this alternative, although I can see that this one might be more future-proof.


On page 161 line 5616 section 8.3, change:
The value of TZ has one of the two forms (spaces inserted for clarity):
:characters
or:
std offset dst offset, rule
If TZ is of the first format (that is, if the first character is a <colon>), the characters following the <colon> are handled in an implementation-defined manner.

The expanded format (for all TZs whose value does not have a <colon> as the first character) is as follows:
to:
The application shall ensure that the value of TZ has one of the three forms (spaces inserted for clarity):
:characters
or:
std offset dst offset, rule
or:

A format specifying a geographical timezone or a special timezone.

If TZ is of the first format (that is, if the first character is a <colon>), the characters following the <colon> are handled in an implementation-defined manner.

The expanded form of the second format (without the inserted spaces) is as follows:

After page 163 line 5700 section 8.3, add:
If TZ is of the third format (that is, if the first character is not a <colon> and the value does not match the syntax for the second format), the value indicates either a geographical timezone or a special timezone from an implementation-defined timezone database. Typically these take the form
Area/Location
as in the IANA timezone database. Examples of geographical timezones that may be supported include <tt>Africa/Cairo</tt>, <tt>America/Indiana/Indianapolis</tt>, <tt>America/New_York</tt>, <tt>Asia/Tokyo</tt>, and <tt>Europe/London</tt>. The data for each geographical timezone shall include:

  • Whether Daylight Saving Time (DST) is observed, and if so the rules used to determine when the transitions to and from DST occur.

  • The offset from Coordinated Universal Time of the timezone's standard time and, if observed, of its DST.

  • The timezone names for standard time (std) and, if observed, for DST (dst) to be used by tzset(). These shall each contain no more than {TZNAME_MAX} bytes.
If there are any historical variations, or known future variations, of the above data for a geographical timezone, these variations shall be included in the database, except that historical variations from before the Epoch need not be included.

If the database incorporates the geographical timezones from the IANA timezone database, the implementation should provide a way to update it in accordance with RFC 6557; if this recommendation is not followed, an implementation-defined way to update the database shall be provided.

Implementations shall support the special timezone <tt>Etc/UTC</tt> and may support additional implementation-defined special timezones. The behavior for <tt>TZ=Etc/UTC</tt> shall be identical to <tt>TZ=UTC0</tt> (as described in the second format above).

On page 3460 line 118332 section A.8.3, change:
Implementations are encouraged to use the time zone database maintained by IANA to determine when Daylight Saving Time changes occur and to handle TZ values that start with a <colon>. See RFC 6557.
to:
Implementations are encouraged to incorporate the IANA timezone database into the timezone database used for TZ values specifying geographical and special timezones, and to provide a way to update it in accordance with RFC 6557.

The TZ format beginning with <colon> was originally introduced as a way for implementations to support geographical timezones in the form :Area/Location as an extension, but implementations started to support them without the leading <colon> (as well as with it) and their use without the <colon> became the de-facto standard. Consequently when geographical timezones were added to this standard, it was without the <colon>.


(0006075)
kre   
2022-11-21 14:38   
Re Note: 0006073

That version is, I think, better than the one in the desired action.
It contains more about the RFC specified database than is really
needed, but that's harmless (and does make the intent clear).

I would make three changes to what is there though.

First, the first requirement of the database:

   Whether Daylight Saving Time (DST) is observed, and if so the rules
   used to determine when the transitions to and from DST occur.

That is not what the tzdata database (generally) provides - what it
gives is when the transitions actually occurred, and when it is possible
a rule that can be used to predict the future (which is generally in the
form of an old style (2nd format here) TZ value). When that isn't possible
it will often guess future transition dates (that's often done when the
expected dates in the future depend upon, or are likely to be affected by,
astronomical or religious events - for which no simple 2nd format TZ string
can cover more than one future year). So, I would replace that
requirement with something less specific (and for this, I will inhibit my
usual attempt to substitute the more rational "summer time" for the ludicrous
"daylight saving")

    If daylight saving is or has been observed a method to discover the dates
    and times of transitions to and from daylight saving time, the new offset
    from UTC which applied or will apply during periods of daylight saving,
    and how that is represented as a label (abbreviation) in textual form,
    for times in the past, and predictions of the future.

That is, in the database there are records like:
    At time_t=X the offset became N, which is [not] daylight saving time,
    and is called EST (or EDT) (or whatever).
There is a record like that for every recorded transition. Simple zones
(like UTC) just say "Since the beginning of time, the offset is 0, not
daylight saving, called 'UTC'" and that is the entire datbase. From
that (if it was ever needed, and it isn't, as there is no interface provided
from which anyone can request this info) we can conclude that daylight
saving is not used in this zone, as there are no records that say "is
daylight saving". A zone which used summer time for one short period,
sometime in the past, as an experiment perhaps - presumably one which
failed - would have the transitions indicating when summer time started,
and ended (for whatever years the experiment lasted) - and then nothing
after that. Whether that is considered as "having daylight saving" is
kind of difficult to judge - some people might say yes, because it was
used once, others no, because it isn't now, and isn't expected in the
future. But it really doesn't matter.


Second, rather than:

   If the database incorporates the geographical timezones from the
   IANA timezone database, ....

I would say something more generic, like:

   If the format references an external database - that is, the value of
   TZ is not itself the specification of the timezone - the implementation
   shall provide an implementation defined method to allow the database to
   be updated, for example that specified by RFC 6557.

That is, it isn't only if an IANA format (tzdata) database is being
used that there needs to be a way to update it, anything which requires
external data (beyond the TZ string itself) needs the ability to be updated.

And, I would delete this paragraph:

     Implementations shall support the special timezone <tt>Etc/UTC</tt>
     and may support additional implementation-defined special timezones.
     The behavior for <tt>TZ=Etc/UTC</tt> shall be identical to
     <tt>TZ=UTC0</tt> (as described in the second format above).

That (or something similar) is needed in the version of the text in the
Desired Action, as that one bases the format around the Area/... concept,
and "Etc" cannot really be considered an area. In this updated version
that's not needed.

Other than to allow Etc/* to exist, there never was a reason to require
Etc/UTC to exist though - if someone desires UTC0 as their timezone, they
can always simply do: TZ=UTC0 - we do not need to mandate alternatives
also exist. Anyone using the tzdata files will get Etc/UTC (and just
UTC as well) but I see no reason to require any of those to exist.

For the purposes of testing (conformance tests) only the 2nd form of TZ
string should ever be used - while the other formats need to be tested,
one cannot write a test to determine correctness based upon those, as
we're not attempting (not even in the desired action version) to specify
what those actually mean (except that Etc/UTC special case). That is,
while one might expect America/New_York to give the data for the eastern
timezone of the US, there's no reason (not specified here, and nor should
we attempt to) that in some implementation that doesn't give the translation
data for Jedah or Auckland. No conformance test can rely upon anything there.

Beyond what the labels mean, the data referenced by them is subject to more
or less arbitrary changes, as corrections to what was believed to be
historically correct are made, or incorrect predictions for the future
are updated.

Lastly, do not allow the (likely) implementation of this method as a
reference to tzdata to influence any wording which may prohibit an
implementation from simply giving all of the needed data as the (possibly
encoded) value of the value of the TZ environment variable. All we
should be demanding is that implementations allow some method by which
real world timezone information can be passed to applications - particularly
via localtime() and mktime() using tzset(). How the implementation
chooses to do that should not matter. [But obviously using tzdata is far
and away the best/easiest method - at least currently.]


Personally I'd like to see more encouragement for support of historical
data (before the Epoch) when it can be determined, than "need not be
provided" suggests, but how much it is possible to encourage that, if
at all, I will leave for others to determine. There's no question but
that the further back in time one goes the less reliable is the data,
and of course, once one goes back before the introduction of standard time
(we don't even need to go back to the beginning of the Gregorian Calendar
in most jurisdictions for this) the whole thing becomes ludicrous - there's
no rational method of translating a local time into an offset from UTC (or
vice versa) when the local time was determined by someone looking at a shadow
and proclaiming "now it is noon, set the clock".
(0006076)
geoffclare   
2022-11-21 15:27   
In Note: 0006075 kre makes some valid points. Here is my attempt to apply them to my previous suggested wording.

I didn't include the "how that is represented as a label" part in the first (now second) bullet point, as I believe that is covered by a combination of the third bullet point and the part after the bullet list about historical variations.

I also omitted the text that talked about the value of TZ itself being the specification of the timezone, as implementations can use a TZ value beginning with colon to provide that ability.

On page 161 line 5616 section 8.3, change:
The value of TZ has one of the two forms (spaces inserted for clarity):
:characters
or:
std offset dst offset, rule
If TZ is of the first format (that is, if the first character is a <colon>), the characters following the <colon> are handled in an implementation-defined manner.

The expanded format (for all TZs whose value does not have a <colon> as the first character) is as follows:
to:
The application shall ensure that the value of TZ has one of the three forms (spaces inserted for clarity):
:characters
or:
std offset dst offset, rule
or:

A format specifying a geographical timezone or a special timezone.

If TZ is of the first format (that is, if the first character is a <colon>), the characters following the <colon> are handled in an implementation-defined manner.

The expanded form of the second format (without the inserted spaces) is as follows:

After page 163 line 5700 section 8.3, add:
If TZ is of the third format (that is, if the first character is not a <colon> and the value does not match the syntax for the second format), the value indicates either a geographical timezone or a special timezone from an implementation-defined timezone database. Typically these take the form
Area/Location
as in the IANA timezone database. Examples of geographical timezones that may be supported include <tt>Africa/Cairo</tt>, <tt>America/Indiana/Indianapolis</tt>, <tt>America/New_York</tt>, <tt>Asia/Tokyo</tt>, and <tt>Europe/London</tt>. The data for each geographical timezone shall include:

  • The offset from Coordinated Universal Time of the timezone's standard time.

  • If Daylight Saving Time (DST) is, or has historically been, observed: a method to discover the dates and times of transitions to and from DST and the offset from Coordinated Universal Time during periods when DST was, is, or is predicted to be, in effect.

  • The timezone names for standard time (std) and, if observed, for DST (dst) to be used by tzset(). These shall each contain no more than {TZNAME_MAX} bytes.
If there are any historical variations, or known future variations, of the above data for a geographical timezone, these variations shall be included in the database, except that historical variations from before the Epoch need not be included.

If the database incorporates an external database such as the one maintained by IANA, the implementation shall provide an implementation-defined method to allow the database to be updated, for example the method specified by RFC 6557.

On page 3460 line 118332 section A.8.3, change:
Implementations are encouraged to use the time zone database maintained by IANA to determine when Daylight Saving Time changes occur and to handle TZ values that start with a <colon>. See RFC 6557.
to:
Implementations are encouraged to incorporate the IANA timezone database into the timezone database used for TZ values specifying geographical and special timezones, and to provide a method to allow it to be updated in accordance with RFC 6557.

The TZ format beginning with <colon> was originally introduced as a way for implementations to support geographical timezones in the form :Area/Location as an extension, but implementations started to support them without the leading <colon> (as well as with it) and their use without the <colon> became the de-facto standard. Consequently when geographical timezones were added to this standard, it was without the <colon>.
(0006081)
kre   
2022-11-21 16:20   
(edited on: 2022-11-21 16:42)
Bugnote:6076 is OK.

The mention of the labels in conjunction with the transitions was
an attempt to make it clearer that there isn't necessarily just one
"standard" and "daylight" ("summer") time label (each) for a zone.
What the time is called can vary over time... But you're right,
there is probably no compelling need to make that point.

OK on the presuming a database is used in this format (in practice
it needs to be anyway, the specification for some zones needs quite
a lot of data, more than is likely to be reasonable in a TZ value
string) - further, if implementations do introduce some other method
(eg: having TZ reference some external server over the net, which then
means there's no local database that ever needs updating) then if needed
some later version of the standard can adjust things to allow that.

ps: "but implementations started to support them without the leading <colon>"
is a slight fib - implementations had been supporting them that way long
before the ':' variant of TZ was invented.

(0006113)
geoffclare   
2023-01-17 11:45   
When applying this bug I noticed a problem with the use of "forms" instead of "formats" in the introductory paragraph. Everywhere else they are referred to as "formats" and the phrase "The expanded form of the second format" only makes sense that way. So I change the introductory text from "has one of the three forms" to "is in one of the three formats".




Viewing Issue Advanced Details
1618 [Issue 8 drafts] Shell and Utilities Editorial Enhancement Request 2022-11-15 02:32 2023-01-17 11:33
illiliti
 
normal  
Applied  
Accepted As Marked  
   
Mark Lundblad
pax
3047
102685-102698
Note: 0006063
pax: extend substitution flags
It is very useful to have ability to skip substitutions for specific file type. For example, one possible use case might be replicating GNU tar '--strip-components=1' option. We can use pax -rs '|[^/]*|.|' for that and it works fine except the case where it breaks. If archive contains symlink which points to e.g. ../foo.h, pax will transform it into foo.h which is undesirable. To fix this incorrect behavior, pax should have additional substitution flags to control to which file types substitution should be applied.

Since both 's'/'S'('S' is not documented in man page, but 's' is) characters are reserved by NetBSD pax to disable symlink substitutions, we use 'l'/'L' instead in order to not introduce potentially breaking change. See: https://nxr.netbsd.org/xref/src/bin/pax/pat_rep.c?r=1.31#199 [^]

See also: https://www.mail-archive.com/austin-group-l@opengroup.org/msg08130.html [^]
On page 3047 line 102689, change:

-s /old/new/[gp]

to:

-s /old/new/[gphrlHRL]


On page 3047 line 102693-102698, change:

Any non-null character can be used as a delimiter ( '/' shown here). Multiple -s
expressions can be specified; the expressions shall be applied in the order
specified, terminating with the first successful substitution. The optional
trailing 'g' is as defined in the ed utility. The optional trailing 'p' shall
cause successful substitutions to be written to standard error. File or archive
member names that substitute to the empty string shall be ignored when reading
and writing archives.

to:

Any non-null character can be used as a delimiter ( '/' shown here). Multiple -s
expressions can be specified; the expressions shall be applied in the order
specified, terminating with the first successful substitution. The optional
trailing 'g' is as defined in the ed utility. The optional trailing 'p' shall
cause successful substitutions to be written to standard error. Optional trailing
'h', 'r', 'l' characters shall enable substitutions for hardlink targets, regular
filenames, symlink targets. Whereas 'H', 'R', 'L' characters shall disable them,
respectively. By default, if no hrlHRL flags were specified, substitutions shall
be applied to all types. File or archive member names that substitute to the
empty string shall be ignored when reading and writing archives.
Notes
(0006055)
geoffclare   
2022-11-17 12:36   
Since NetBSD only documents the s flag, they would probably be okay with us specifying S as having the opposite behaviour. I think that would preferable than using l and L instead.

The r and R flags are invention and I don't see the point of them as there is no "target" to apply the substitution to (or not) for regular files.

If neither h nor H is used it should be unspecified which is the default. Likewise for s and S. (Otherwise only one of each pair would be needed.)
(0006056)
kre   
2022-11-17 15:22   
I'm not sure that Note: 0006055 quite captures the intent of the -s
option, which (note: I am not particularly knowledgable about pax)
I believe is intended to alter the files that are in the archive - used,
I think, most commonly to remove/alter leading prefixes.

The 's' flag in NetBSD causes the substitution to apply only to the
archive member name, and not to its contents (the symlink target) in
the case that the archive member is a symlink.

The desired action seems confused to me, perhaps using "target" when
member name is meant (which would explain the r/R intent) - but then it
isn't clear just which substitutions are being allowed/suppressed, the
original archive member name, or the target when the member is a link or
symlink.

I am also not sure that all the variations make a lot of sense. There's
no point adding options simply with the intent of covering every possible
case, if there is no practical use for some of them. And that is what
it looks like here.

Generally the idea of -s seems to be to alter all the paths in the archive,
which generally will include hard link targets, as those are almost always
to other files in the archive. If the path of the target is altered when it
is extracted, then the link target needs to be altered as well. Being able
to suppress that seems useless. On the other hand, symlink targets are
sometimes intended to be to files that are not in the archive, or even
to "files" that are not intended to exist at all (the symlink is used for
readlink() only). Supressing altering the names of the files in the
archive, based upon file type, rather than matching the file name, seems
like a particularly useless endeavour - how would that be used?


I can ask the NetBSD community their opinion of all of this, but doing that doesn't make a lot of sense without a clear idea of just what is being
proposed.
(0006062)
illiliti   
2022-11-18 00:02   
Thanks everyone. Initially, I tried to be semantically compatible with GNU tar and bsdtar since they provide similar functionality. But you're right, that's redundant. Here's the updated proposal which only reflect symlink flags:

On page 3047 line 102689, change:

-s /old/new/[gp]

to:

-s /old/new/[gpsS]


On page 3047 line 102693-102698, change:

Any non-null character can be used as a delimiter ( '/' shown here). Multiple -s
expressions can be specified; the expressions shall be applied in the order
specified, terminating with the first successful substitution. The optional
trailing 'g' is as defined in the ed utility. The optional trailing 'p' shall
cause successful substitutions to be written to standard error. File or archive
member names that substitute to the empty string shall be ignored when reading
and writing archives.

to:

Any non-null character can be used as a delimiter ( '/' shown here). Multiple -s
expressions can be specified; the expressions shall be applied in the order
specified, terminating with the first successful substitution. The optional
trailing 'g' is as defined in the ed utility. The optional trailing 'p' shall
cause successful substitutions to be written to standard error. The optional
trailing 's' shall disable substitutions for symlink destinations, whereas 'S'
shall enable them. The application shall ensure that optional trailing 's' and 'S'
are mutually exclusive for each expression. If neither 's' nor 'S' is defined, the
behavior whether substitutions for symlink destinations shall be applied or not is
unspecified. File or archive member names that substitute to the empty string shall
be ignored when reading and writing archives.
(0006063)
geoffclare   
2022-11-18 15:34   
(edited on: 2022-11-21 16:35)
The following is a modified version of Note: 0006062 with wording that I think is more in keeping with other text in the standard, and the addition of a clarification about empty symbolic links. (I also removed some unchanged text.)

On page 3047 line 102689, change:
-s /old/new/[gp]
to:
-s /old/new/[gpsS]

On page 3047 line 102693-102698, change:
The optional trailing 'p' shall cause successful substitutions to be written to standard error. File or archive member names that substitute to the empty string shall be ignored when reading and writing archives.
to:
The optional trailing 'p' shall cause successful substitutions to be written to standard error. The optional trailing 's' and 'S' control whether the substitutions are applied to symbolic link contents: 's' shall cause them not to be applied; 'S' shall cause them to be applied. If neither is present, it is unspecified which is the default. If both are present, the behavior is unspecified. File or archive member names that substitute to the empty string shall be ignored when reading and writing archives. Symbolic link contents that substitute to the empty string shall not be treated specially.


(0006064)
kre   
2022-11-18 17:15   
Is there a need for the 'S' option and the "unspecified which is the default" ?

That is, is there any version of pax which (without the 's' flag or some
equivalent) fails to substitute in symbolic link contents? (Or on the
target of a hard link?)

The problem description suggests perhaps not - that is, the problem is
that when the archive member names are being altered, symbolic link
values (the name they reference) are being altered as well, and sometimes
should not be.

If that is true of all versions of pax (or almost all), absent some
additional flag to prevent that happening, then we can simply make
the substitutions apply to all link (hard and symbolic) contents, and
just add the 's' flag to suppress that for symbolic links.

That would be simpler, and better for applications I would have thought,
as there won't be a need to add 's' or 'S' flags on every -s arg, when
what exists now works fine.

Further, it would be better for NetBSD (which has the 's') - but where
all those flags ('p' 'g' and 's') are treated in a case independent way.
('p'=='P' 'g'=='G' 's'=='S' even though that's not documented. Making
that apply for p and g, but do the exact opposite for s would be annoying.

Note that in many (but perhaps not all) cases the problem described can
also be worked around by supplying a more specific pattern than just
-s '|[^/]*|.|' -- which might be needed in any case as a symlink whose
contents are essentially the same as what would be used as the target
for a hard link (the path name relative to the starting origin) should
probably get substituted, whereas one more like the ../foo.h example
should not.

A simple flag appended to the option cannot distinguish those cases.
(0006066)
illiliti   
2022-11-19 03:39   
Yes, "unspecified which is the default" is needed. I know nothing about pax implementations in commercial unix systems, but I know at least one open-source implementation that does not do substitutions on symlinks. It is pax from schilytools.

And no, there's no such substitution pattern that can work in generic way and not break symlinks. Therefore 's' flag to ignore symlinks is needed.

Also since we discarded r/h/R/H flags, should we make it more clear that 'S' flag should exclude regular and all other file types except for symlinks? I find it useful since user could pass two(or more) -s expressions to pax; one with 'S' flag would work only with symlinks and one with 's' flag with other file types. Thoughts?
(0006067)
kre   
2022-11-19 18:03   
OK, then I guess we need to stay with it as Note: 0006063 has it
specified, that or invent some other character instead of 'S' (which
is an invention anyway right, so there is no particular reason
except for symmetry with 's' for it to be that character).

However I am not sure that schilytools is, of itself, quite enough of
a blocker, if something different was desired.

But from Note: 0006066 I don't know what you mean by:
   should we make it more clear that 'S' flag should exclude regular
   and all other file types except for symlinks?

The -s expressions always apply to all archive member names. What file
type it is makes no difference. The issue is when the contents is also a
path name - which means just for links (hard and soft). Those are also
normally (without 's', and temporarily ignoring schilytools) also subject
to substitution. For hard links that is exactly what is wanted, since the
link contents is the path name of another file already added to the archive,
since that one's name would have been altered by a matching -s, the same
matching -s needs to be applied to the link's contents (the file to which to
which to link), or the link with either not be able to be made, or perhaps
might become a link to some other file entirely. So the 's'/'S' flags cannot
mean anything in that case either. That leaves only symlink contents, which
one might not want to apply the substitutions, so the 's'/'S' flags apply only
to that case - the content of a symbolic link archive member.

If you mean that 'S' should be defined to substitute only on symlink contents,
and not on other pathnames in the archive, then that looks to be pure
invention, and would then require another option (or lack of either the 's'
or 'S' flags) to mean substitute on both, choosing "no flag" for that would
be back to removing "if neither is given result is unspecified".

Lastly re:
    there's no such substitution pattern that can work in generic way
    and not break symlinks

I know, but I doubt there's a generic substitution pattern that can apply
to an arbitrary pax archive and expect to work in all cases (even when there
are no symlinks, or links of any kind) in the archive. The substitutions
need to be tailored to the needs of the archive. Even then it might be
hard to get matching patterns which deal with all cases (though the "match
once and stop" rule means that -s 's/thing/thing/' is an easy way to leave
some entries unaffacted, eg: for the symlink example, using -s '|^\.\./|../|'
before the -s '|[^/]*|.|' would avoid the issue shown there, but not
other possible problems. (Use '[.]' instead of '\.' if \ escaping isn't
expected to work.)
(0006069)
illiliti   
2022-11-20 01:25   
(edited on: 2022-11-21 11:57)
I'm fine with Note: 0006063 too.

> If you mean that 'S' should be defined to substitute only on symlink contents,
and not on other pathnames in the archive

Yes, that's what I meant. And I agree with you why it isn't worth it.

> I know, but I doubt there's a generic substitution pattern that can apply
to an arbitrary pax archive and expect to work in all cases (even when there
are no symlinks, or links of any kind) in the archive.

Practice shows that -s '|[^/]*|.|' with 's' flag is enough to cover common cases(e.g. software release tarballs).

(0006070)
philip-guenther   
2022-11-20 02:37   
I agree a new flag ('s') should be specified to disable substitution on symbolic link contents.

IMHO, if we have consensus on that, then I'm with kre in feeling that schilytools shouldn't be seen a blocker for specifying the default behavior: existing implementations that don't already have the new flag will be non-compliant until fixed, regardless of what their default behavior currently is. So, are there any implementations that already have an 's' flag *and* that default to that behavior? Alternatively, is there push back from an implementation that is going to add the new flag but doesn't want to change its default?

If not, then we can avoid specifying a new implementation-defined behavior, which would be a demerit to portability.
(0006071)
illiliti   
2022-11-20 06:06   
Just checked. pax from heirloom project and original pax by Mark H. Colburn also don't apply substitutions to symlink targets. So we have at least three pax implementations that differ from BSD pax: schilytools pax, heirloom pax and original pax.

Could someone check what z/OS, AIX, HP-UX, and other commerical unix systems do? I'm pretty sure they don't mangle symlinks as well since they (seemingly)use original pax as a base but checking that wouldn't hurt anyway. Just in case.
(0006072)
geoffclare   
2022-11-21 09:28   
Solaris and HP-UX do not apply substitutions to symlink targets. It's probably a safe bet that the same is true for AIX and z/OS.
(0006074)
illiliti   
2022-11-21 12:31   
Thanks for checking! Now we have a clear picture that we can't simply redefine implementation-defined behavior. Users probably rely on a behavior of their pax and redefining it might cause issues for them.

Given that, I think Note: 0006063 should be accepted as the best compromise. I know I know, users will have to define s/S flag for each expression, but personally I don't see any other option that would be compatible with current implementations.
(0006086)
stephane   
2022-11-28 20:15   
I'd welcome a way to be able to tell pax what the -s applies to: path, symlink target, hardlink target as the --xform option of GNU tar does. See https://unix.stackexchange.com/questions/726489/untar-file-if-exists-in-archive/726494#726494 [^] as an example of why not being able to do so can be undesirable.

But the --xform of GNU tar differs from POSIX pax' in that POSIX pax has that requirement that once a -s matches, all other -s's are disregarded, so if we implement GNU tar's rhsRHS, we likely need to add something like a q/Q flag to tell whether or not to stop processing more "s"ubstitutions if this one succeeds so one can apply different substitutions to paths and link targets.

Currently, it's not completely clear what should happen if an archive member has its symlink or hardlink target substituted with the empty string, but its path not (either not substituted at all or the substitution results in a non-empty string).

Maybe with the "p" flag, the output should also make it clear what is being substituted. ATM, with the pax found on Debian (from MirBSD), I see no output there for substitutions made on symlink targets (even when that results in the symlink target becoming empty and the member being discarded as a result).
(0006087)
stephane   
2022-11-28 20:37   
What it implies for pax -rw and pax -rwl should likely be reviewed as well. From vague memory for looking into it years ago, behaviours vary widely there.

Not sure if it's covered in the spec, but there's a whole range of vulnerabilities involving processing of malicious archives containing symlink/hardlink members followed by members with the same path that have affected most tar implementations in the past (I remember raising that one to Joerg about his "star" implementation of tar) that will get in the picture here. i.e. we'll likely need something like "if upon extraction, a member's path after "-s"ubstitutions have been applied is identical to the link target (after "-s"ubstitution) of an earlier member, behaviour unspecified" with a recommendation that the member should be discarded and an error message printed.
(0006088)
illiliti   
2022-11-28 23:10   
stephane, please consider submitting a proposal of what exactly should be added, fixed, reviewed or improved. Thanks.
(0006089)
geoffclare   
2022-11-29 09:13   
(edited on: 2022-11-29 09:22)
When this was discussed in the Nov 21 teleconference, we agreed that the s and S flags were the only additions that are suitable for inclusion at this time because s is the only one that has been implemented in an existing pax utility (and S is just the opposite of s, and is needed because the default differs between implementations). All of the other suggestions would be invention.

If you want to propose further additions you will need to persuade an implementation to add them first.





Viewing Issue Advanced Details
1617 [Issue 8 drafts] Shell and Utilities Objection Clarification Requested 2022-11-11 01:20 2023-01-17 11:31
illiliti
 
normal  
Applied  
Accepted As Marked  
   
Mark Lundblad
tsort
3237
109959
See Note: 0006098
what tsort should do with cycles?
The current standard is unclear what should happen when tsort encounters a cycle. Existing practice shows that some implementations might only print a warning and some might even exit with a non-zero status code. Essentially, that renders tsort unusable for portable applications due to the lack of a way to explicitly tell tsort how cycles should be handled.

Here is more detailed analysis what implementations do with cycles:

- GNU, sbase print a warning and continue traversing the graph, then exit with a non-zero status code.
- NetBSD, FreeBSD, Illumos print a warning and continue traversing the graph, then exit with a zero status code.
- OpenBSD has -w option to record the number of cycles in exit status code(zero cycles = zero status code).
Decide what to do. Either add an option to force specific behavior or clarify that tsort shall not be relied upon to detect cycles(but then what's the point of it nowadays?)
Notes
(0006051)
Don Cragun   
2022-11-14 16:52   
(edited on: 2022-11-14 19:06)
Add a new paragraph to the DESCRIPTION of tsort after D2.1 P3237, L109968:
If a cycle is found in the input, diagnostic messages shall be written to STDERR reporting that there is a cycle and indicating which nodes are in the cycle(s).


(0006052)
illiliti   
2022-11-14 17:15   
Hmm, but what about exit status code? Should cycle cause an error or not? If not, how to detect cycle using tsort in a portable shell script? That's the most important things to clarify; sorry if I didn't make it clear initially.
(0006053)
Don Cragun   
2022-11-14 19:01   
Re Note: 0006052:
By definition, diagnostic messages report errors that must result in an unsuccessful exit status. All that we require is that a non-zero exit status be returned in this case; we do not require that the number of cycles be reported in the exit status. (Note that there is always the theoretical possibility that counting cycles could result in a zero exit status due to overflow. This description does not allow that behavior; if the count wraps to zero, tsort must detect this condition and return a non-zero value.)
(0006054)
illiliti   
2022-11-14 19:56   
Thanks for the clarification. Still, I think proposed text should be adjusted to *explicitly* mention that cycle is an error and should result in non-zero status code. It's mainly needed to reduce confusion because some implementations don't exit with a non-zero exit status despite that they print diagnostic message to stderr.
(0006057)
Don Cragun   
2022-11-17 16:48   
(edited on: 2023-01-05 07:38)
Make the following changes:
Add a new paragraph to the DESCRIPTION of tsort after D2.1 P3237, L109968:
If a cycle is found in the input, diagnostic or warning messages shall be written to standard error reporting that there is a cycle and indicating which nodes are in the cycle(s). If a diagnostic message is written, the final exit status shall be non-zero.


Change the STDERR in tsort on P3238, L100001 from:
The standard error shall be used only for diagnostic messages.
to:
The standard error shall be used only for diagnostic and warning messages.


(0006059)
illiliti   
2022-11-17 20:31   
As a portable shell script writer, how do I know whether particular tsort implementation prints a warning or diagnostic message? How to know that there's a cycle if it's still unclear what exit status tsort returns? Sorry, the proposed text does not fix the problem with cycles and exit status but only aggravates it.
(0006060)
kre   
2022-11-17 21:01   
Re Note: 0006059

You don't know, just as you don't now. You can test, by creating
input with a cycle, running tsort, and seeing what happens.

What the standard is supposed to do is make it clear to applications
what they can expect, and what they cannot. As long as implementations
differ (by other than agreed bugs), there is no standard to state
beyond that applications cannot depend upon anything in particular
in this area.
(0006061)
illiliti   
2022-11-17 22:24   
Here's how I think this should be fixed(by adding -w option from OpenBSD):

On page 3237 line 109962, change:

tsort [file]

to:

tsort [-w] [file]



On page 3237 line 109968, add a new paragraph:

If a cycle is found in the input, diagnostic messages shall be written to standard error reporting that there is a cycle and indicating which nodes are in the cycle(s). It is unspecified whether the final exit status shall be zero or non-zero value.



On page 3237 line 109970, change:

None

to:

The tsort utility shall conform to XBD Section 12.2 (on page 199).

The following option shall be supported:

-w

Exit with the number of cycles after traversing the graph. If there are more cycles than maximum representation of the exit status code can hold, the application shall exit with a non-zero status code instead. If there are no cycles, the application shall exit with zero status code.
(0006098)
geoffclare   
2023-01-05 16:58   
On page 3237 line 109962, change:
tsort [file]
to:
tsort [-w] [file]


Add a new paragraph to the DESCRIPTION of tsort after D2.1 P3237, L109968:
If a cycle is found in the input, diagnostic or warning messages shall be written to standard error reporting that there is a cycle and indicating which nodes are in the cycle(s). If the -w option is specified, these messages shall be diagnostic messages. If a diagnostic message is written, the final exit status shall be non-zero.

    
On page 3237 line 109970, change OPTIONS from:
None

to:
The tsort utility shall conform to [xref to XBD Section 12.2].

    The following option shall be supported:

    -w
Set the exit status to the number of cycles found in the input, or to an implementation defined maximum if there are more cycles than that maximum. If no cycles are found, the exit status shall be zero unless another error occurs.


Change the STDERR in tsort on P3238, L100001 from:
The standard error shall be used only for diagnostic messages.
to:
The standard error shall be used only for diagnostic and warning messages.


On page 3238 line 110009 change:
>0 An error occurred.
to:
>0 An error occurred. If the -w option is specified and one or more cycles were found in the input, the exit status shall be the number of cycles found, or an implementation defined maximum if more cycles than that maximum were found.


Change RATIONALE at page 3238 line 110033 from "None" to:
At the time that the -w option was added to this standard, the only known implementation reported a maximum of 255 cycles via the exit status. This has the drawback that applications cannot distinguish, from the exit status, errors caused by cycles from other errors or (when tsort() is executed from a shell) termination by a signal. Implementations are urged to set the implementation-defined maximum number of cycles reported via the exit status to at most 125, leaving 128 for other errors, and leaving 126, 127, and values greater than 128 to have the special meanings that the shell assigns to them. (An implemenation that wants to distinguish other types of errors would need to set the maximum to less than 125 so that 128 is not the only code available for those errors).


Change FUTURE DIRECTIONS at line 110035 from "None" to:
A future version of this standard may require that when the -w option is specified, the maximum number of cycles reported through the exit status of tsort is at most 125 and that exit status values 126, 127, and greater than 128 are not used by tsort.




Viewing Issue Advanced Details
1616 [Issue 8 drafts] Shell and Utilities Editorial Enhancement Request 2022-11-08 23:03 2023-02-22 13:30
illiliti
 
normal  
New  
Open  
   
Mark Lundblad
Shell and Utilities
-
-
Standardize mktemp utility
The current standard has no reliable and convenient utility to create temporary file or directory, despite that low-level interfaces, mkstemp/mkdtemp, are available for this use case. The mktemp(1) utility is a perfect candidate to fill this gap. Its interface is fairly simple and mostly consistent across various implementations, however not without some differences. I evaluated GNU, LSB, NetBSD, FreeBSD, OpenBSD, Illumos, Solaris, sbase, toybox, busybox implementations and here is what I found:

- FreeBSD, NetBSD accept multiple templates. Others do not.
- FreeBSD does not specify -p option. Others do.
- LSB does not specify -d and -p options. Others do.
- FreeBSD, NetBSD accept parameter for -t option. Others do not.
- FreeBSD, NetBSD use -t option to specify prefix. Others use it to explicitly tell mktemp to create temporary file in temporary directory rather than in current directory.
- All have different default value for template.
- All have different requirements regarding how many Xs template should contain, but it seems they all accept six Xs.
- sbase, Illumos, Solaris override -p parameter with TMPDIR value if it is set. Others do not.
- GNU overrides -p parameter with TMPDIR value or /tmp if parameter is empty string. Others do not.
- OpenBSD, Illumos, Solaris(not sure), toybox do not allow '/' in template if -p option is passed. Others do.

Given that, I think mktemp interface is not completely lost and below is my attempt to make it portable.
Standardize mktemp utility. Here is the most minimal and portable example:

NAME
     mktemp - create temporary unique file or directory

SYNOPSIS
     mktemp [-dqu] [-p directory] [template]

DESCRIPTION
     mktemp creates a temporary file based on a template as if by calling
     mkstemp(3). If no template is specified, an implementation-defined value
     shall be used instead. If template does not contain exactly six Xs at the
     end, the behavior is unspecified. If template does not contain '/', the file
     shall be created in the current directory. Otherwise, the file shall be
     created by its path. The filename of created temporary file shall be written
     to the standard output.

OPTIONS
     -d Create directory instead of file as if by calling mkdtemp(3).

     -p directory
             Change directory where temporary file will be created. With this
             option, it is unspecified what happens if template contains '/'. If
             TMPDIR is set, it is unspecified whether its value take precedence
             over passed parameter or vice versa. If passed parameter is empty
             string, the behavior is unspecified.

     -q Fail silently if an error occurs.

     -u Operate in unsafe mode. A unique name is generated, but the
             temporary file shall be unlinked before mktemp exits. Use of this
             option is not encouraged.

SEE ALSO
     mkdtemp(3), mkstemp(3)
Notes
(0006038)
steffen   
2022-11-08 23:30   
While i accept it as natural as it is so widely used, please note that POSIX says for pathchk(1):

  The pathchk utility was new for the ISO POSIX-2: 1993 standard. It, along with the set −C(noclobber) option added to the shell, replaces the mktemp, validfnam, and create utilities that appeared in early proposals.

So what you do is

if ( set -C ) >/dev/null 2>&1; then
  set +C
else
  # For heaven's sake auto-redirect on SunOS/Solaris
  if [ -f /usr/xpg4/bin/sh ] && [ -x /usr/xpg4/bin/sh ]; then
    exec /usr/xpg4/bin/sh "${0}" "${@}"
  else
    synopsis 1 'sh(1)ell without "set -C" (for safe temporary file creation)'
  fi
fi

and then

old_umask=`umask`
umask 077
i=1
while :; do
  tmpfile="${tmpdir}/MYNAME-${i}.tmp"
  (
    set -C
    : > "${tmpfile}"
  ) >/dev/null 2>&1 && break
  i=`expr ${i} + 1`
  if [ ${i} -gt ${max} ]; then
    echo >&2 'Cannot create a temporary file within '"${tmpdir}"
    exit ${EX_TEMPFAIL}
  fi
done
trap "exit ${EX_TEMPFAIL}" HUP INT QUIT PIPE TERM
trap "trap \"\" HUP INT QUIT PIPE TERM EXIT; rm -f ${tmpfile}" EXIT
umask ${old_umask}

..after finding a tmpdir and doing some other setup.
(0006041)
illiliti   
2022-11-09 13:18   
Yeah, your example should work, but it is not simple. Look at how simple mktemp is:

tmpfile=$(mktemp)

or directory:

tmpdir=$(mktemp -d)

mktemp is impossible to misuse unlike shell. Plus it is already more-or-less portable and widespread on all open-source systems.

Also unrelated, but it seems that your example does not work with yash when tmpfile is a dangling symlink. Looks like a yash bug. Reported.
(0006166)
ormaaj   
2023-02-22 13:30   
(edited on: 2023-02-22 19:10)
Here's a few more data points.

The uutils mktemp is basically same as coreutils, as expected:

(ins)root 5 (7104) 0 ~ # uu-mktemp --help
create a temporary file or directory.

Usage: uu-mktemp [OPTION]... [TEMPLATE]

Arguments:
  [template]

Options:
  -d, --directory Make a directory instead of a file
  -u, --dry-run do not create anything; merely print a name (unsafe)
  -q, --quiet Fail silently if an error occurs.
      --suffix <SUFFIX> append SUFFIX to TEMPLATE; SUFFIX must not contain a path separator. This option is implied if TEMPLATE does not end with X.
  -p, --tmpdir [<DIR>] interpret TEMPLATE relative to DIR; if DIR is not specified, use $TMPDIR ($TMP on windows) if set, else /tmp. With this option, TEMPLATE must not be an absolute name; unlike with -t, TEMPLATE may contain slashes, but mktemp creates only the final component
  -t Generate a template (using the supplied prefix and TMPDIR (TMP on windows) if set) to create a filename template [deprecated]
  -h, --help Print help information
  -V, --version Print version information

Bash's "example" loadable mktemp:

(ins)root 5 (7104) 0 ~ # bash -c 'enable -f mktemp{,}; type mktemp; help mktemp'
mktemp is a shell builtin
mktemp: mktemp [-d] [-q] [-t prefix] [-u] [-v varname] [template] ...
    Make unique temporary file name

    Take each supplied filename template and overwrite a portion of it
    to create a filename, which is unique and may be used by the calling
    script. TEMPLATE is a string ending in some number of 'X's. If
    TEMPLATE is not supplied, shtmp.XXXXXX is used and $TMPDIR is used as
    the name of the containing directory. Files are created u+rw; directories
    are created u+rwx.

    Options, if supplied, have the following meanings:

        -d Create a directory instead of a file
        -q Do not print error messages about file creation failure
        -t PREFIX Use PREFIX as the directory in which to create files
        -u Do not create anything; simply print a name
        -v VAR Store the generated name into shell variable VAR

    Any PREFIX supplied with -t is ignored if TEMPLATE is supplied.

    The return status is true if the file or directory was created successfully;
    false if an error occurs or VAR is invalid or readonly.

And the AST libcmd builtin under ksh93 (edit: u+m also has this one):

(ins)root 5 (7104) 0 ~ # ksh93v -c 'builtin mktemp; type mktemp; mktemp --man'
mktemp is a shell builtin
NAME
  mktemp - make temporary file or directory

SYNOPSIS
  mktemp [ options ] [ prefix [ directory ] ]

DESCRIPTION
  mktemp creates a temporary file with optional base name prefix prefix. If prefix is omitted then tmp is used and --tmp is implied. A consecutive string of trailing X's in prefix is replaced by a pseudorandom combination of [0-9a-zA-Z]characters, otherwise the first 5 characters of prefix is catenated with a
  pseudorandom string to construct a file name component of 14 characters. If directory is specified or if prefix contains a directory prefix then that directory overrides any of the directories described below. A temporary file will have mode rw------- and a temporary directory will have mode rwx------, subject to
  umask(1). Generated paths have these attributes:
    * Lower case to avoid clashes on case ignorant filesystems.
    * Pseudo-random part to deter denial of service attacks.
    * Default pseudo-random part (no specific X... template) formatted to accomodate 8.3 filesystems.

  A consecutive trailing sequence of X's in prefix is replaced by the pseudo-random part. If there are no X's then the pseudo-random part is appended to the prefix.

OPTIONS
  -d, --directory Create a directory instead of a regular file.
  -m, --mode=mode Set the mode of the created temporary to mode. mode is symbolic or octal mode as in chmod(1). Relative modes assume an initial mode of u=rwx.
  -p, --default=directory
                  Use directory if the TMPDIR environment variable is not defined. Implies --tmp.
  -q, --quiet Suppress file and directory error diagnostics.
  -R, --regress=seed
                  The pseudo random generator is seeded with seed instead of process/system specific transient data. Use for testing only. A seed of 0 is silently changed to 1.
  -t, --tmp|temporary-directory
                  Create a path rooted in a temporary directory.
  -u, --unsafe|dry-run
                  Check for file/directory existence but do not create. Use this for testing only.

SEE ALSO
  mkdir(1), pathtemp(3), mktemp(3)

IMPLEMENTATION
  version mktemp (AT&T Research) 2012-12-12
  author Glenn Fowler <glenn.s.fowler@gmail.com>
  author David Korn <dgkorn@gmail.com>
  copyright Copyright (c) 1992-2015 AT&T Intellectual Property
  license http://www.eclipse.org/org/documents/epl-v10.html [^]

In addition ksh93 has the `>;word` redirect which opens a temporary file and renames it to word if the command returned success. It can serve a similar purpose.

The canonical method I thought everyone knew is m4's mkstemp ( https://mywiki.wooledge.org/BashFAQ/062#Using_m4 [^] )

Another reasonably widely-available tool - xfs_io from xfsprogs - can be used to open a file with O_TMPFILE. It works on several platforms including with some non-xfs filesystems.





Viewing Issue Advanced Details
1615 [Issue 8 drafts] Shell and Utilities Editorial Enhancement Request 2022-11-07 18:00 2022-11-30 16:39
illiliti
 
normal  
Applied  
Accepted  
   
Mark Lundblad
make
2940
98590-98591
make: allow slashes and hyphens characters in target names
It is very common to see Makefiles that use '-' character to separate action and object in target. For example, autotools generates install-strip target and may also generate install-bin, install-man and so on.

'/' character is also very common and useful. Rather than putting sources into a top-level directory, people usually put them into a src directory and then specify relative paths to them in top-level Makefile. This allows having more clean and organized project structure.

No make implementations that I am aware of have this restriction that current standard mandates. Here is the list of make implementations that I checked:

- NetBSD make
- FreeBSD make
- OpenBSD make
- GNU make
- AIX make
- Illumos make
- Schily SunPro make
Change:

"solely of periods, underscores, digits, and alphabetics from the portable character set"

to:

"solely of slashes, hyphens, periods, underscores, digits, and alphabetics from the portable character set"
There are no notes attached to this issue.




Viewing Issue Advanced Details
1614 [1003.1(2016/18)/Issue7+TC2] System Interfaces Objection Omission 2022-11-03 13:36 2022-11-10 10:28
kre
 
normal  
New  
Open  
   
Robert Elz
XSH 3/mktime
1331
44331-44332
---
XSH 3/mktime does not specify EINVAL and should
First, it is possible this is a duplicate bug report, if this issue
has already (or is to be already) handled by some other bug, and this
report doesn't add anything new, then please simply link this to that
as a duplicate, and then close this.

It is possible for the broken down local time passed to mktime() to
represent a time that never existed (eg: a time in the gap (most commonly
hour) when summer time commences, and the clock skips forward from
NN:59 to PP:00 (usually, gaps shorter than an hour exist, but for our
purposes here, as an example, that's not important) where PP==(NN+2)%24
and times MM:xx (usually for all xx) where MM==(NN+1)%24 simply never
existed (with appropriate adjustments to tm_mday, etc, if the %24 makes
any difference to the answer in each case).

If one specifies an input time of MM:20 that simply cannot be converted
to a time_t, it kind of represents NN:59 + 21 mionutes, except that local
time is really PP:20 not MM:20.

Note that tm_isdst does not help here, as the time simply does not exist,
it cannot be either summer or standard (or standard or winter as appropriate)
time. It is possible for an implementation to use tm_isdst as a hint
to what happened so cases like this work

    timeptr = localtime(&t);
    timeptr->tm_min += 20;
    t = mktime(timeptr);

where if tm_isdst should have changed value to represent the new time
calculated, but clearly here does not (and since timeptr came from
localtime, we know tm_isdst is 0 or 1) then the implementation might be
able to guess what was intended.

That does not always work however, there can be gaps in times for reasons
other than the tm_isdst changing seasonal adjustment, such as when a locality
decides to switch from one zone offset to another (eg: sometime, I am too
lazy to look up when, Singapore and Malaysia switched from UTC+0700 to
UTC+0800 (to align their clocks with Hong Kong, which was apparently
considered important - at least for Singapore). Neither used summer time,
before or after than change, tm_isdst is 0 in both zones - but there was
an hour there that never existed.

Similarly, when seasonal time ends, and time jumps backwards, there is an
hour (most commonly) of local time when the time runs twice. If one specifies
a time which is in (one of) those periods, along with a tm_isdst = -1, then
it is impossible to determine which time_t value should apply - EINVAL is
returned in that case.

Note that here, tm_isdst is used to handle this overlap when it is caused
by seasonal adjustments - but just as with the gap, that only works when
the duplicated time are for that reason, if Malaysia decided (which would be
odd, indeed, but could happen) that having their clocks match Thailand,
much of Indonesia (including Jakarta), and Laos and Cambodia, rather than
Singapore, they could decide to jump back to UTC+0700 by running one hour
twice - with tm_isdst==0 in both occurrences.

There is another way that (since bug 1533 was applied) could be considered
reasonable to handle the ambiguous case - one could use the value of tm_gmtoff
to determine which of the possible time_t's to return. This even handles
(never seen that I am aware of, and very unlikely to ever happen) cases
where a time runs more than twice, which tm_isdst cannot do.

It appears very tempting to make use of that to resolve this problem, but
I would strongly advise against it. Doing so would break current conforming
applications (which simple addition of the fields does not) as they currently
do not, and cannot (since the tm_gmtoff field does not appear in the existing
standard - it is not even as of the date of this report in a published draft
of an upcoming version of the standard) set that field, its value from such
an application will be unitialised (or perhaps 0), if mktime() were to attempt
to reference it, undefined behaviour might result. That's unacceptable.

It is not even OK to permit implementations to use tm_gmtoff by making its
use for this purpose unspecified, for the same reason - any implementation
that does risks undefined behaviour from a currently conforming application.
mktime() must not be permitted to reference that field (in the incoming
structure) at all.


An error code is required to handle this invalid or ambiguous input.
EINVAL is the usual one.
Between lines 44331 and 44332 (of I7 TC2) add:

    [EINVAL] The local time specified represents a local time which
               either did not exist in the past, or is not expected to exist
               in the future, or the local time specified represents a
               local time which existed, or is expected to exist in the
               future, more than once, and the value supplied in tm_isdst
               is unable to resolve the ambiguity.

It might also be (assuming that you all agree with my reasoning above)
a good idea to add something in the Rationale (line 44359, currently "None")
explaining why tm_gmtoff is not (at least now) considered appropriate to
use to resolve the ambiguous case. I will leave it up to you to determine
whether it would be worth adding a Future Direction indicating that that
might be changed at some future time (ie: advising applications to ensure
that they start setting tm_gmtoff before calling mktime() - it will currently
be ignored, but one day, might be essential in this odd case).

           
Notes
(0006022)
geoffclare   
2022-11-03 16:54   
I'm sure this has been discussed at least once before, but on the mailing list not in Mantis. When the specified time does not exist because it is in the gap created by the change to daylight saving time and tm_isdst is -1, mktime() is not allowed to fail. It must treat the time either as standard time or as daylight time and return the corresponding value. (The value of tm_isdst on output distinguishes the two.) Likewise when daylight saving time ends and times are ambiguous when tm_isdst is -1, mktime() must choose to treat it either as standard time or as daylight time. These cases are tested by one of the UNIX certification test suites.

If you know of an implementation where mktime() returns -1 under these conditions, please report it as a bug to the maintainers.

Cases such as Singapore and Malaysia moving to a different time zone are another matter, and I suppose mktime() could legitimately return -1. However, this would only happen with a TZ that specifies a location (rather than "std offset dst offset, rule"), and the behaviour of all functions that use TZ is implementation-defined in that case anyway, so I don't see the need to add an EINVAL error to the standard for this.
(0006025)
hvd   
2022-11-03 18:04   
> I'm sure this has been discussed at least once before, but on the mailing list not in Mantis. When the specified time does not exist because it is in the gap created by the change to daylight saving time and tm_isdst is -1, mktime() is not allowed to fail.

C does allow this to fail; this has been confirmed at <https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_136.html>. [^] It is valid for POSIX to require specific behaviour in areas that the C standard leaves unspecified, but I see nothing in the CX-marked additions in POSIX specifies the behaviour for this case.
(0006028)
kre   
2022-11-03 20:02   
(edited on: 2022-11-03 20:48)
Re Note: 0006022

   I'm sure this has been discussed at least once before,

I thought I remembered it as well, but did not find it, but if it was just
on the list that would explain it. But that's why I included the first
paragraph of the description.

But:
   When the specified time does not exist because it is in the gap created
   by the change to daylight saving time and tm_isdst is -1, mktime() is not
   allowed to fail.

That makes no sense at all. In the ambiguous case, I guess things could
be interpreted that way (the time runs twice), and in that case certainly
the tm_isdst value in the result can distinguish which was chosen (that is,
the implementation picks one if the application did not bother), but I do
not see anything in XSH 3/mktime which actually requires that to happen.
Certainly if the user sets tm_isdst to 0 or 1 in this case, then mktime()
must not fail, but return the appropriate value, but for the -1 case, all
I see in the standard is:

    A negative value for tm_isdst shall cause mktime( ) to attempt to
    determine whether Daylight Savings Time is in effect for the
    specified time.

Nothing there about it being required to pick one. Note that text I
proposed adding does not prohibit an implementation from picking one and
returning that, merely allows EINVAL if

     the value supplied in tm_isdst is unable to resolve the ambiguity.

If an implementation chooses to always pick one or the other (or even roll
the die, and randomly return one or the other) that's fine, in that case it
used the -1 input and used that to resolve the ambiguity, but I see nothing
which requires that kind of result.

But for the gap, the period where the local time specified never existed
at all, no result (except -1 with errno set) makes any sense at all. The
whole idea of mktime() is that localtime() applied to the time_t returned
will produce the same struct tm as that left in *timeptr my mktime() after
it has completed. The two are inverses of each other (to the extent that
EOVERFLOW does not apply, in one direction or the other, anyway). For a
broken down time (a struct tm) passed to mktime() which gives a value that
localtime() can never produce is simply broken. As best I can tell the
standard reference implementation of mktime() acts exactly like this.

Lastly, I have no sympathy at all for an argument by which POSIX deliberately
says that many places in the world don't need to be handled by the standard
TZ definition, and that anything that allows their time zone specification to
correctly translate their times is beyond the standard, and anything is
permitted, is simply outrageous (though this is not the place to debate XBD
8.3: TZ). But if things happen as they are looking like they might, this kind
of issue is likely to occur in the US, and Europe as well, if seasonal
variations are abandoned, and localities are permitted to pick which zone
they will remain in as their standard time - when that transition happens,
and it might not be far away, well before Issue9 of POSIX can possibly appear,
this exact problem will occur in places that the POSIX committee people cannot
simply dismiss as "we don't care what happens in that part of the world",
which seems to be the attitude now.

(0006030)
kre   
2022-11-03 20:27   
I meant to add in the previous note (but this is more than I think should
be done by just amending that), that an option (not one I believe correct,
but if it seems to be) would be that rather than adding EINVAL to the "shall
fail" case, at least in the ambiguous input (time runs twice) scenario,
that could be added as a "may fail" section following the current "shall fail".

For the "time in the never existing gap" case (which exists in all zones
which have summer time (also stupidly known as "daylight savings") no matter
what form they use to specify the TZ setting, there really is no option,
the only thing mktime() can do in that case is return an error, nothing else
is correct, that needs to be a "shall fail".
(0006031)
geoffclare   
2022-11-04 09:36   
(edited on: 2022-11-04 10:01)
Re Note: 0006025 Yes, POSIX is more strict than C here. The CX shaded text that matters is:
A negative value for tm_isdst shall cause mktime() to attempt to determine whether Daylight Savings Time is in effect for the specified time.
(C has something similar, but in a non-normative footnote.)

As I understand it, this requires that if mktime() determines that DST is in effect, it returns the same result as it would for tm_isdst=1, otherwise it returns the same result as it would for tm_isdst=0. That is how all certified UNIX and POSIX systems behave. Until now I thought it was how all mktime() implementations behave, but I see that the C DR that you cite mentions "Arthur David Olson's popular ``tz'' time zone software" as returning -1. That was back in 1994, so I wonder if it still does or if it has changed to behave like other implementations.

Re Note: 0006022

> But for the gap, the period where the local time specified never existed
> at all, no result (except -1 with errno set) makes any sense at all. The
> whole idea of mktime() is that localtime() applied to the time_t returned
> will produce the same struct tm as that left in *timeptr my mktime() after
> it has completed. The two are inverses of each other

If you just feed in a struct tm obtained from localtime(), or any equivalent source of valid date and time info, obviously the "gap" times will never occur. What you are missing here is that an important feature of mktime() is that you can do calculations using the tm members. That is the reason it specifically allows out-of-range values.

If an application uses mktime() to answer the question "What will the date and time be a month from now" (meaning when the wall clock time is the same as it is now, but on the day that is a month from now) by incrementing tm_mon and setting tm_isdst=-1, it is not helpful to get back the answer "that time won't exist". There are probably a very large number of applications that do this kind of thing that will break if ported from an implementation where mktime() does not return -1 to one where it does (if any exist). Worse still, they will only break under rare circumstances, so the problem could go unnoticed for years, decades even, before biting one day.

If we did decide to allow mktime() to return -1, ask yourself how would an application handle this error? The vast majority of applications will want to obtain a time they can use, rather than reporting an error; if that time is adjusted by an hour because it happens to occur right at a DST change, that's all well and good. So the obvious way for them to handle the error would be to repeat the mktime() call with tm_isdst=0 (or 1). This will produce the same result that the standard currently requires. So all that allowing this error will achieve is to force most application writers to add another mktime() call in order to get the same result they would have got before. If an application actually wants to verify whether a given time exists, it can so do simply by checking whether the tm_hour and tm_min values it gets back are the same ones it fed in. This is actually a more reliable method than assuming that a return of -1 with errno EINVAL indicates a non-existent time would be (if we allow it), because EINVAL could be caused for other reasons as well (e.g. an invalid TZ value).

> For a broken down time (a struct tm) passed to mktime() which gives
> a value that localtime() can never produce is simply broken.

I'm having trouble parsing that. If you are suggesting that passing the return value of mktime() to localtime() could produce different struct tm member values than those returned by mktime(), then that can never happen, since mktime() is required to set them the same way localtime() does.

> As best I can tell the standard reference implementation of mktime()
> acts exactly like this

What implementation do you believe to be a reference implementation? The function was invented by the ANSI C committee. As far as I'm aware they did not produce a reference implementation. In the absence of an implementation by the function's inventors, all implementations have equal standing and none is a reference implementation.

Actually, that's not quite true, because POSIX has additional requirements beyond the C standard, so implementations that only claim conformance to C and not POSIX have no standing in relation to the additional POSIX requirements.

> I have no sympathy at all for an argument by which POSIX deliberately
> says that many places in the world don't need to be handled by the
> standard TZ definition, and that anything that allows their time zone
> specification to correctly translate their times is beyond the standard

Perhaps we should add the Area/Location TZ format to POSIX (with no details, just a reference to another standard, maybe RFC 6557).

Re Note: 0006030

> For the "time in the never existing gap" case [...] there really is
> no option, the only thing mktime() can do in that case is return an
> error, nothing else is correct, that needs to be a "shall fail".

This would make every certified implementation non-conforming, along with most if not all implementations that claim POSIX conformance but aren't certified, and would break many applications. There is absolutely no way this change would achieve consensus.

(0006032)
kre   
2022-11-04 17:37   
(edited on: 2022-11-04 17:43)
Re Note: 0006031

I know this:

  A negative value for tm_isdst shall cause mktime() to attempt to determine
  whether Daylight Savings Time is in effect for the specified time.

and what your note says about it, but note that it says "attempt to determine"
not "determine" which it would not say if it were guaranteed to be able to
work (and I don't mean anything related to the unpredictability of what
might happen into the indefinite future, all we can possibly do is assume
that the current rules apply forever forward, until we discover differently).

If that attempt fails, what do you contend that mktime() should do?

   What you are missing here is that an important feature of mktime()
   is that you can do calculations using the tm members.

I don't think I was missing that, if you look back at the description
section, you'll see that it includes an example...

   It is possible for an implementation to use tm_isdst as a hint
   to what happened so cases like this work

    timeptr = localtime(&t);
    timeptr->tm_min += 20;
    t = mktime(timeptr);

and if you believe that is a requirement, then I don't object to that,
but I'd like a pointer to where in the standard this is stated as required.

But why would any code do, as you postulate:

    incrementing tm_mon and setting tm_isdst=-1,

why the "setting tm_isdst=-1" part? What would be the point?

If tm_isdst remained as localtime set it, then the implementation
can use that when normalising the numbers, to deduce what happened
if no time_t for the time can be produced, and further push the
time through the gap (altering tm_hour). But if we don't know what
tm_isdst applied before, how is the implementation supposed to
determine whether the tm passed to mktime() was produced by an
addition (time moving forwards) as in both your example, and mine,
or by a subtraction (looking for an earlier time). The expected
result in the two cases will be different (when we are crossing the
gap).

Paul Eggert's C query (from 1994) referenced by Harald in Note: 0006025
suggests that the test suites look for either of two answers, as long as
the implementation produces one of them, all is good. Surely you aren't
going to defend that as a practice? "We don't care whether the answer
you give is correct or meaningful, just as long as you give an answer"?

Really? Surely an error response is always better than an incorrect
answer passed off as being correct?

   There are probably a very large number of applications that do this kind
   of thing that will break if ported from an implementation where mktime()
   does not return -1 to one where it does (if any exist).

If there is any implementation where mktime() cannot return -1, it is
already non-compliant -- the standard is quite clear that mktime()
shall return -1 (with errno == EOVERFLOW) in some cases. Any application
that doesn't deal with a -1 return from mktime() is already defective,
whatever happens here.

What the application should do when it gets a -1 I cannot possibly
say - it entirely depends upon the needs of the application, but it
certainly needs to deal with the possibility (or just hope it never
happens, which would be a behaviour that would not need to be changed).

   So the obvious way for them to handle the error would be to repeat the
   mktime() call with tm_isdst=0 (or 1). This will produce the same result
   that the standard currently requires.

The question would be why they did not do that the first time? Why are
you imagining the tm_isdst=-1 being there? Note that even this cannot
handle all the cases (it certainly doesn't help with EOVERFLOW) ?

I am not going to debate application code writer's possible behaviours,
we don't have enough info to discuss that - using EINVAL to signal
"in the gap" as a message to them was never the purpose. Rather it
is a necessity for any implementation which seeks to provide only correct
answers, rather than "if we do this we pass the validation test, so that's
what we do, regardless of how stupid it is". And yes, implementers sometimes
do act just like that, under pressure.

Do you not see the incongruity of these two comments from your note:

    If we did decide to allow mktime() to return -1,
and
    EINVAL could be caused for other reasons as well (e.g. an invalid TZ value).

The second accepts that (even though it is not in the mktime() page,
mktime() can already return -1 with error == EINVAL.

But given all of that, note that tzset() is not actually allowed to
return an error, what happens with an invalid TZ is apparently unspecified,
but tzset() is apparently required to do something in that case, and not
return an error. So, I doubt that your "EINVAL could be caused for other
reasons as well" is actually the case (not that it matters here, a -1
return from mktime() is possible whatever happens as a result of this
issue, including nothing.

But hadn't you already decided that mktime() can return -1 ?? (and
even with errno==EINVAL)

wrt:

   I'm having trouble parsing that.

Sorry, that happens sometimes.

  If you are suggesting that passing the return value of mktime() to
  localtime() could produce different struct tm member values than those
  returned by mktime(), then that can never happen, since mktime() is
  required to set them the same way localtime() does.

what I meant is exactly what you say there is required. And I agree.

But mktime() only gets to adjust the input struct tm values (according
to what is written in the specification:

    the other components shall be set to represent the specified time
    since the Epoch, but with their values forced to the ranges indicated
    in the <time.h> entry;

That is, the "other components" (which means all of the relevant ones,
just not tm_wday and tm_yday which are irrelevant here) are set to
represent the specified time since the Epoch (that is: the time specified
by the caller of mktime()) but with any out of range values (according
to what is specified in <time.h>) adjusted so that are in range (and while
it does not say so, and probably should, I would interpret that to also
mean not having 31 days in November, even though 31 is within the range
permitted for tm_mday in <time.h>) but it doesn't say that they can be
adjusted for any other reason.

If we take Paul's example from C defect report #136 (the 1994 issue cited
by Harald in Note: 0006025) and the application create a struct tm, exactly
as he described it, what justification exists to allow mktime() to alter
any of the fields of the struct tm (except tm_isdst, as a -1 input is never
in range as an output value).

I see none. If the result is not -1, the resulting tm should be (for
the specified fields, other than tm_isdst) be identical to the one supplied.

Given that, if mktime() does not return -1 (if it does, what is in the
tm seems unspecified to me) then we have a case where mktime is (apparently)
required to leave the struct tm in a state which is something that localtime()
can never return - violating the requirement that we both agree should exist.

On the other hand, if it does return -1, which the C committee apparently
agree it can (and yes, I know that posix can make stricter requirements
than exist in C ... though I don't see anything in the spec for mktime()
which does so - only apparently in the broken validation suites) then
this is not an issue.

   What implementation do you believe to be a reference implementation?

I meant the one referenced in that defect report, which is (I believe) by
far the most widely used implementation (though often with minor variations)
existing at the minute, and is public domain. I believe that android
and probably macos both use it, I think all the BSDs use it, and linux.
Some of the commercial OSs use it as well.

   The function was invented by the ANSI C committee.

That is news to me, but I cannot dispute it, as I have no idea of
its origins. I do have vague memories of it in the very ancient
past though. The earliest BSD implementation (taken from the ado
code) I can find is in 4.3 Reno (1990) - but it must have existed
for quite a while before that, as that contains a version of mktime()
based upon one I had done earlier -- using an idea from Bob Kridle, when he
was still at UC Berkeley, Computer Centre -- the time_t desired is
determined by doing a binary search over the range of a time_t (works
for any possible time_t type - including floats) calling localtime on each,
comparing its resulting struct tm with the (already normalised) input
struct tm (and adjusting the upper or lower bound of the search as
appropriate) until equality is found.

When it becomes impossible to subdivide the range smaller (we'd need to
be producing sub-second intervals) if no match has been found, the tm
originally requested, simply cannot exist, and an error happens.

When I did my initial implementation of that, which was adopted (modified
to suit other requirements) in ado's implementation, I was replacing an
earlier algorithmic implementation (kind of like that in XBD 4.16 - but of
course, not nearly as simple as that makes it seem). I moved away from
unix work in the latter 1980's (87 or so) and more into networking and
the IETF for the rest of the century (before that environment became far
too political and commercial after the explosion of the internet in the
late 1990's). In any case, that would mean that there must have been at
least one freely available mktime() implementation around in the mid 1980's.

When did the C committee apparently invent it?

Aside: the advantage of the binary search algorithm is certainly not speed,
it is slower than an algorithmic implementation, usually a lot slower, but
it removes any knowledge of time peculiarities from mktime() - works
whatever (arithmetic) type time_t happens to be, and always guarantees
that one requirement that we agree on, locatime(mktime(tm)) == tm (not that
that is anything like valid C, but you know what I am getting at, and the
error case is being ignored there - that's only for valid time_t returns).
It also works (without adjustment) in environments using UTC, rather than
POSIX time_t (ie: where leap seconds are not simply imagined out of
existence), not that that aspect is relevant here.

While still considering this general point, also note that Paul's C defect
message, also includes this sentence:

    The ANSI C Rationale (corresponding to subclause 7.12.2.3) clearly lets
    mktime yield -1 in the ``fall-backward fold'' that will occur when the
    clock is turned back from 01:59:59 to 01:00:00 on October 30, 1994.

That's the case I have less problem avoiding a -1 result from, as while
it is ambiguous there which time_t is intended, either one will generate
the struct tm that was given to mktime() (and the input tm_isdst, if not -1,
can be used to select which - though there is no help available when the
input tm_isdst == -1) - but this is another case where an error return is
apparently allowed by C, the POSIX mktime() spec claims to defer to the C
standard, and nowhere (I have found) does POSIX say that it is more
restrictive in this area. Where do you believe these additional
requirements are stated?

I really believe that there is no option other than allowing EINVAL in
these cases (if you insist you could make both of them be "may fail if"
rather than "shall fail if") which would allow implementations which
return nonsense results, just because the (apparently broken) conformance
tests require nonsense results, to remain conforming, while still allowing
implementations striving for correctness to generate error returns when no
correct answer is possible.

On this last point:

    Perhaps we should add the Area/Location TZ format to POSIX
    (with no details, just a reference to another standard, maybe RFC 6557).

That would be a great idea. (Would need a new bug report though, it
doesn't belong in this one). "No details" I would agree with, and I'd
specify even less than you do there, I'd give some requirements on what
must be achieved, but no hints as to how to achieve that. Eg: I believe
that windows systems use the timezone data collected by the tz project,
(and probably more as well), but make use of it in a completely different
way, nothing like what that RFC specifies. No reason to prohibit that,
or even suggest it isn't the correct way - as long as it achieves the
correct results.

What matters is a TZ value, that isn't a valid POSIX TZ string (for what
use those are, which isn't much, in any meaningful zone) and doesn't
start with a ':' (which should remain as now), will (in an implementation
unspecified manner) provide access to information which allows any
time_t (ideally since standard time was adopted in a locality, and
certainly since the Epoch) to be converted to the appropriate time_t
(and back again) using the rules appropriate for that timezone at that
particular time. Requiring a '/' in the name isn't required I'd
expect, though in practice, all that matter (and aren't also POSIX
strings) meet that format.

(0006033)
hvd   
2022-11-04 23:23   
> Re Note: 0006025 Yes, POSIX is more strict than C here. The CX shaded text that matters is:

> A negative value for tm_isdst shall cause mktime() to attempt to determine whether Daylight Savings Time is in effect for the specified time.

> (C has something similar, but in a non-normative footnote.)

Note that this, despite being CX-shaded, is not actually an instance of POSIX being more strict than C. The C footnote, in full, is:

"Thus, a positive or zero value for tm_isdst causes the mktime function to presume initially that Daylight Saving Time, respectively, is or is not in effect for the specified time. A negative value causes it to attempt to determine whether Daylight Saving Time is in effect for the specified time."

The footnote makes it clear that this is considered to follow from the normative wording and there is therefore no need to have this as a separate requirement in the normative wording; the footnote is merely for clarification. I believe that thinking here is correct. Do you disagree?

I'm happy with POSIX choosing to spell this out in normative wording, but if it adds no new requirements, it cannot be the case that it specifies anything that isn't specified by the C standard as well. Either this is unspecified both in ANSI C and in POSIX, or this is defined in both ANSI C and POSIX.

(0006034)
geoffclare   
2022-11-07 12:33   
Re Note: 0006032 This discussion is becoming too long to hold in bugnotes. See my response on the mailing list.
(0006035)
geoffclare   
2022-11-07 12:42   
Re Note: 0006033

> The footnote makes it clear that this is considered to follow from the
> normative wording and there is therefore no need to have this as a separate
> requirement in the normative wording; the footnote is merely for
> clarification. I believe that thinking here is correct. Do you disagree?

Yes I disagree. The word "thus" is what makes it seems like this follows from normative text, but if you look at the normative text where the footnote marker is, there is nothing there from which the text in the footnote could be derived. So the use of "thus" is puzzling.

I believe the real reason that the text is in a footnote instead of normative is because, earlier on, the C standard says "The local time zone and Daylight Saving Time are implementation-defined." Since DST is implementation-defined the C standard can't have normative text requiring mktime() to behave a certain way with regard to DST; it is left to implementations to decide how to interpret tm_isdst.

In POSIX the DST rules are specified in the description of TZ, so there is no problem requiring mktime() to make use of them.
(0006036)
hvd   
2022-11-07 12:59   
> Yes I disagree. The word "thus" is what makes it seems like this follows from normative text, but if you look at the normative text where the footnote marker is, there is nothing there from which the text in the footnote could be derived. So the use of "thus" is puzzling.

There is. The footnote is attached to a sentence that states that the values on entry of tm_wday and tm_yday are ignored and that the other values not limited to their usual ranges. This tells us all values other than tm_wday and tm_yday are used, including tm_isdst. This means the value on entry of tm_isdst must be interpreted according to the earlier definition of tm_isdst, which is (in normative text) "The value of tm_isdst is positive if Daylight Saving Time is in effect, zero if Daylight Saving Time is not in effect, and negative if the information is not available." The only way to use the value on entry of tm_isdst that is consistent with that definition is what the footnote describes.

It may not be exactly clear, but it's a legitimate reading and one that the wording in the footnote tells us is the intended reading.
(0006037)
geoffclare   
2022-11-08 15:24   
Re Note: 0006036

> The only way to use the value on entry of tm_isdst that is consistent
> with that definition is what the footnote describes.

Here's where we disagree. As you say, negative tm_isdst means DST information is "not available"; however, there is nothing in the normative text that says how mktime() must behave when it is told that DST information is not available. The footnote is what does that, but it's non-normative.
(0006039)
hvd   
2022-11-09 00:01   
> however, there is nothing in the normative text that says how mktime() must behave when it is told that DST information is not available.

We know that on a successful return of mktime(), "the other components are set to represent the specified calendar time". These other components again include tm_isdst, which thus must be set according to the description quoted earlier. If the implementation knows that Daylight Saving Time is in effect for the specified date and time, it must set tm_isdst to a positive value. If the implementation knows that Daylight Savings Time is not in effect for the specified date and time, it must set tm_isdst to zero.

It's one thing to think that this isn't clear from the C standard. It's quite another when it has specifically been stated by the C standard committee that this is how the normative text is meant to be read to argue that it doesn't say that. It doesn't matter whether you're right that it doesn't say that: we have zero doubt about the intent, so even if you can convince the committee that they're wrong, we know the outcome would just be to clear up the wording. We save ourselves a whole lot of time by just treating it as settled now.
(0006042)
geoffclare   
2022-11-09 17:07   
Re Note: 0006039

> If the implementation knows that Daylight Saving Time is in effect for the
> specified date and time, it must set tm_isdst to a positive value. If the
> implementation knows that Daylight Saving Time is not in effect for the
> specified date and time, it must set tm_isdst to zero.

Where is the normative text that says that? I can see nothing in C99 that forbids mktime(), or localtime() for that matter, returning a negative tm_isdst because "the information is not available".
(0006043)
hvd   
2022-11-09 17:40   
> Where is the normative text that says that? I can see nothing in C99 that forbids mktime(), or localtime() for that matter, returning a negative tm_isdst because "the information is not available".

When we're talking about the cases where that information is available to the implementation, it's right there, "the information is not available" does not apply to that case. Of course, in situations where that information truly is unavailable, a negative tm_isdst could be appropriate, and that is consistent with the footnote and with the POSIX wording, as "attempt to determine" allows for the possibility that the determination fails.
(0006044)
kre   
2022-11-09 21:15   
Re Note: 0006042 and Note: 0006043

You're right, in C99 it is possible for tm_isdst to be returned with the
value -1, if the implementation has no information on whether summer time
applies or not.

But here we tend to (also) live in a POSIX conforming environment, and then
this issue cannot arise. A conforming POSIX environment always has some
known timezone information, and always knows if summer time ever applies,
and if it does apply, always knows when the transitions occur. Those are
requirements to be conforming.

Any time_t value (which represents a year which will fit into the tm_year
field of a struct tm) will always be able to be converted to a struct_tm
with tm_isdst ==0 or tm_isdst == 1 -- -1 as a return value cannot happen.
(0006045)
hvd   
2022-11-09 23:18   
> But here we tend to (also) live in a POSIX conforming environment, and then
> this issue cannot arise.

I was referring to the edge cases this issue is about there, the edge cases for which you have been arguing the most reasonable behaviour is for mktime() to return -1, but other implementations do return valid positive time_t values. I did not want to rule out the possibility of implementations setting tm_isdst to a negative value in those cases. We are in agreement that it should not happen in the normal cases.
(0006046)
kre   
2022-11-10 10:19   
Re Note: 0006045

No, that possibility is already ruled out. The "missing paragraph"
from C99 that didn't make it into the POSIX spec of mktime() makes
it quite clear that that cannot happen - the struct tm returned from
a successful call of mktime() is required to be identical to a struct
tm that would be returned by a call of localtime() on the result of
mktime (and also, a second call of mktime() using the struct tm returned
from the first must not alter the struct tm, and must return the same
result. Since localtime() can (in POSIX) never return with tm_isdst == -1
mktime() cannot either.
(0006047)
kre   
2022-11-10 10:28   
Further re Note: 0006045

Also, if we were in a situation where we don't know whether or
not summer time applies (or perhaps when it applies) in a particular
timezone (somehow) then the "edge cases for which I have been arguing..."
cannot occur either. If we don't know that summer time will commence
(or end), or we don't know when that will happen, then we cannot possibly
determine that a time is in the gap or foldback.




Viewing Issue Advanced Details
1613 [Issue 8 drafts] System Interfaces Objection Omission 2022-11-03 12:53 2022-11-30 16:50
kre
 
normal  
Applied  
Accepted As Marked  
   
Robert Elz
XSH 3/mktime
1311
43850-43854, 43865-43866, 43867-43870
Note: 0006049
XSH 3/mktime was not updated by the resolution of bug 1533, but should have been (++)
Note while submitted against I8 D2.1 this should really have been
filed against D2.2 or D3 (whichever is to appear next) as it relates
to the resolution of bug 1533, which did not appear in D2.1

So... D2.1 it is.

The specification of mktime() says (lines 43850-4)

    The mktime( ) function shall convert the broken-down time, expressed as
    local time, in the structure pointed to by timeptr, into a time since the
    Epoch value with the same encoding as that of the values returned by
    time( ). The original values of the tm_wday and tm_yday components of
    the structure shall be ignored, and the original values of the other
    components shall not be restricted to the ranges described in <time.h>.

That is, it specifies which fields of struct tm (as defined in <time.h> and
the XBD page that defines it, are to be used, by simply (more or less) saying
"all except tm_yday and tm_wday".

That was OK (if a little lazy) before bug 1533 was applied, but is no longer
as now struct tm has two additional members (tm_gmtoff and tm_zone) which
should also be ignored by mktime().

That bug does not specify any changes to XSH 3/mktime to correct this.
Change lines 43850-43854 from the text given above in the description
to something like:

    The mktime( ) function shall convert the broken-down time, expressed as
    local time, in some fields of the structure pointed to by timeptr, into
    a time since the Epoch value with the same encoding as that of the values
    returned by time( ).

    The mktime( ) function shall make reference only the tm_year, tm_mon,
    tm_mday, tm_hour, tm_min, tm_sec, and tm_isdst components of the
    structure pointer to by timeptr, which values shall not be restricted
    to the ranges described in <time.h>.


Also, change in lines in 43865-43866 the text

    calculated from the other tm structure members specified in <time.h>
    (excluding tm_wday).

to say instead

    calculated from the components of the tm structure specified above,

Also change lines 43867-43870 from

    Upon successful completion, the values of the tm_wday and tm_yday
    components of the structure shall be set appropriately, and the other
    components shall be set to represent the specified time since the Epoch,
    but with their values forced to the ranges indicated in the <time.h>
    entry; the final value of tm_mday shall not be set until tm_mon and
    tm_year are determined.

into (something like)

    Upon successful completion, the components of the structure pointed
    to by timeptr specified above shall be set to represent the resulting
    time since the Epoch, but with their values forced to the ranges
    indicated in the <time.h> entry; the final value of tm_mday shall not
    be set until tm_mon and tm_year are determined. Other components of
    the structure shall be set to appropriate values to represent that
    time since the Epoch.

Notes
(0006023)
steffen   
2022-11-03 17:56   
I thought it is redundant since mktime says clearly

  Local timezone information shall be set as though mktime( ) called tzset( )

Which implies that the mentioned fields cannot have a meaning in this regard?

P.S.: regarding the NetBSD ML thread on mktime(3), i did not send the letter

I have not followed this thread really, but just to note that
POSIX says "Local timezone information shall be set as though
mktime( ) called tzset( )."
"In such cases" (i do have no business here, mind you) i look at
musl. I _think_ the thread started due to that however...
But wanted to note that POSIX added no wording for mktime(3) with
the addition of gmtoff etc. musl does

  long long t = __tm_to_secs(tm);

^ Plain arithmetic that ignores timezone.

  __secs_to_zone(t, 1, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);

^ "Sets zone" (1).

  if (tm->tm_isdst>=0 && new.tm_isdst!=tm->tm_isdst)
          t -= opp - new.__tm_gmtoff;

  t -= new.__tm_gmtoff;
  if ((time_t)t != t) goto error;

  __secs_to_zone(t, 0, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);

^ Does not (0).

  if (__secs_to_tm(t + new.__tm_gmtoff, &new) < 0) goto error;

  *tm = new;
  return t;
(0006029)
kre   
2022-11-03 20:21   
Re Note: 0006023

Steffen, just ignore the NetBSD mailing list thread, that's just a couple of
people (one really) who have no idea at all what they're talking about and
are proposing utter nonsense which will never happen. That's gibberish.

I know the line you quoted from the standard (which is in both mktime() and
strftime()) about calling tzset (that applies to the NetBSD list discussion -
though the people there don't care what POSIX specifies, just that those
functions do what they are presuming that they should always do ... I intend
to post one last time there, soon, if things have finally calmed dowm and
both include that line from the standard, and show the fringe that NetBSD
already has (non-POSIX) interfaces that do exactly what they want, which
are in our manual pages, which they are obviously not bothering to read, but
while things are running hot, that would not go down well).

You may be correct that musl's broken (non-conforming) implementation here
may have been what triggered that discussion originally, but isn't what
added the heat. I don't think discussing implementation code details is
really appropriate here however.
 

But that line doesn't impact this current issue - there's no question but
that mktime() (and strftime) are required to treat the time as local time,
but local time can have more than one tm_gmtoff (and does, in any zone when
summer time applies) - and an implementation could use tm_gmtoff to help
it select which of the ambiguous time values in the "end of summer time,
time runs twice" situation.

My point here is that implementations must not do that, as doing so can
cause existing conforming applications to produce undefined behaviour.

While I am here, I see a line in the "Desired action" where I managed to make
two typos... (but neither of the form a spell checker can detect).

The line:
    structure pointer to by timeptr, which values shall not be restricted
should have said
    structure pointed to by timeptr, in which values shall not be restricted

Regular users are able to edit their own notes, like this one, but not the
problem description, nor desired action, so ...
(0006049)
geoffclare   
2022-11-10 17:02   
(edited on: 2022-11-10 17:05)
Change lines 43850-43854 from:
The mktime() function shall convert the broken-down time, expressed as local time, in the structure pointed to by timeptr, into a time since the Epoch value with the same encoding as that of the values returned by time(). The original values of the tm_wday and tm_yday components of the structure shall be ignored, and the original values of the other components shall not be restricted to the ranges described in <time.h>.
to:
The mktime() function shall convert the broken-down time, expressed as local time, in some members of the structure pointed to by timeptr, into a time since the Epoch value with the same encoding as that of the values returned by time( ). The mktime() function shall make use of only the tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, and tm_isdst members of the structure pointed to by timeptr; the values of these members shall not be restricted to the ranges described in <time.h>.

Also, change in lines in 43865-43866 the text:
calculated from the other tm structure members specified in <time.h> (excluding tm_wday).
to:
calculated from the members of the tm structure specified above.

Also change lines 43867-43870 from:
Upon successful completion, the values of the tm_wday and tm_yday components of the structure shall be set appropriately, and the other components shall be set to represent the specified time since the Epoch, but with their values forced to the ranges indicated in the <time.h> entry; the final value of tm_mday shall not be set until tm_mon and tm_year are determined.
to:
[CX]Upon successful completion, the members of the structure shall be set to the values that would be returned by a call to localtime() with the specified time since the Epoch as its argument.[/CX]






Viewing Issue Advanced Details
1612 [Issue 8 drafts] System Interfaces Objection Error 2022-11-03 11:19 2022-11-30 16:48
kre
 
normal  
Applied  
Accepted As Marked  
   
Robert Elz
XSH 3/strftime
1997
64827
See Note: 0006048.
XSH strftime() new (I8) %s conversion requires too much of the struct tm
strftime() says of the (newly added in Issue 8) %s conversion (lines 64826-7)

     Replaced by the number of seconds since the Epoch as a decimal number,
     calculated as described for mktime( ).

That is fine.

After that it adds (as with all other conversions) the fields of its struct tm
arg which are used by that conversion. For %s (line 64827) that says

    [all members]

That is incorrect. Checking XSH 3/mktime() we see (page 1311, lines 43852-3)

    The original values of the tm_wday and tm_yday components of
    the structure shall be ignored,

Hence, as the %s conversion is required to operate as specified for mktime()
and mktime() is prohibited from using tm_wday or tw_yday as part of its
calculation, it cannot possibly be necessary for those fields to be set
in a struct tm passed to strftime() for the %s conversion, hence it is
incorrect to say that all members must be set.

There is another potential problem, but that really occurs in mktime()
and so will be deferred to later issue report, related to it. Either
of the proposed resolutions below would avoid that problem (for the 2nd
alternative, provided the mktime() issue is fixed).

Either list the members that are used by mktime()

   tm_year tm_mon tm_mday tm_hour tm_min tm_sec and tm_isdst

instead of "all members", which would be consistent with the
other specifications,

or (since the algorithm does) simply defer to XSH 3/mktime via an
XREF in the brackets.

Either way works.
Notes
(0006048)
Don Cragun   
2022-11-10 16:36   
Change strftime() DESCRIPTION on P1997, L64827 from:
[all members]
to:
[tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_isdst]




Viewing Issue Advanced Details
1610 [1003.1(2016/18)/Issue7+TC2] System Interfaces Objection Clarification Requested 2022-10-21 08:07 2022-11-08 14:18
geoffclare
 
normal  
Applied  
Accepted  
   
Geoff Clare
The Open Group
pthread_mutexattr_getprotocol()
1687
55047
---
Scheduling requirements when unlocking a prioceiling mutex
The description of pthread_mutexattr_setprotocol() includes the following:
While a thread is holding a mutex which has been initialized with the PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT protocol attributes, it shall not be subject to being moved to the tail of the scheduling queue at its priority in the event that its original priority is changed, such as by a call to sched_setparam(). Likewise, when a thread unlocks a mutex that has been initialized with the PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT protocol attributes, it shall not be subject to being moved to the tail of the scheduling queue at its priority in the event that its original priority is changed.

As discussed on the mailing list, it is thought that the intention of the second sentence is that a thread should be able to lock and unlock a priority ceiling mutex without the implicit yield that any resulting priority changes would normally cause as a side effect.

Since these statements are creating exceptions to the normal scheduling rules, it would be better to state them in the same place as those rules instead of on the pthread_mutexattr_getprotocol() page.

Also, there are problems with the related rationale in B.2.8.4, namely that it conflicts with the normative text and with itself regarding when the head of a ready list is removed, and it still only talks about processes whereas the normative text has been updated to talk about threads.
Delete the quoted paragraph.

After page 508 line 17723 section 2.8.4, add a new paragraph:
While a thread is executing at a temporarily elevated priority as a consequence of owning a mutex initialized with the PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT protocol (see [xref to pthread_mutexattr_getprotocol()]), the effects of the above requirements on thread priority shall apply only to the thread's normal priority, not to its elevated priority, and those of the above requirements that describe the thread being placed on any thread list as a result of a priority change shall not apply. Likewise, when such a thread reverts to its normal priority as a consequence of unlocking such a mutex, those of the above requirements that describe the thread being placed on any thread list as a result of a priority change shall not apply.

On page 3610 line 122991 section B.2.8.4, change:
relevant to process scheduling; see also [xref to B.2.9.4].
to:
relevant to process and thread scheduling; see [xref to B.2.9.4] for additional rationale relevant to thread scheduling.

On page 3610 line 122992 section B.2.8.4,
and page 3611 line 122993,122997,123001 section B.2.8.4, change:
processes
to:
processes or threads

On page 3611 line 122999 section B.2.8.4, change:
process sequencing
to:
process and thread sequencing

On page 3611 line 123005 section B.2.8.4, change:
In an operating system supporting multiple concurrent processes, the system determines the order in which processes execute and might force long-running processes to yield to other processes at certain intervals. Typically, the scheduling code is executed whenever an event occurs that might alter the process to be executed next.
to:
In an operating system supporting multiple concurrent processes or threads, the system determines the order in which threads (including those that are the only thread in a single-threaded process) execute and might force long-running threads to yield to other threads at certain intervals. Typically, the scheduling code is executed whenever an event occurs that might alter the thread to be executed next.

On page 3611 line 123009 section B.2.8.4, change:
Whenever a process becomes runnable, it is placed on the end of a ready list. The process at the front of the ready list is executed until it exits or becomes blocked, at which point it is removed from the list.
to:
Whenever a thread becomes runnable, it is placed on the end of a ready list. When processing resources become available, the thread at the front of the ready list starts or resumes execution and is removed from the list. This thread is executed until it exits or becomes blocked, at which point the processing resources used to execute it become available to execute another runnable thread.

On page 3611 line 123015-123029 section B.2.8.4, change all occurrences of "process[es]" to "thread[s]".

On page 3611 line 123020 section B.2.8.4, change:
Further, if a process elects to alter its priority, it is removed from the ready list and reinserted, using its new priority, according to the policy above.
to:
Further, if a running or runnable thread's priority is altered, it is removed from the ready list for its old priority (if present in the list; that is, not running) and is inserted into the ready list for its new priority, according to the policy above, except that threads executing at a temporarily elevated priority as a consequence of owning a mutex initialized with the PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT protocol are exempted from this in order to ensure that a thread can lock and unlock such as mutex without the implicit yield that any resulting priority changes would normally cause.

On page 3611 line 123031 section B.2.8.4, change:
all processes are well-behaved realtime applications
to:
all threads belong to well-behaved realtime applications

On page 3611 line 123034 section B.2.8.4, change:
POSIX.1-2017 specifies a linear scheduling model. In this model, every process in the system has a priority. The system scheduler always dispatches a process that has the highest (generally the most time-critical) priority among all runnable processes in the system. As long as there is only one such process, the dispatching policy is trivial. When multiple processes of equal priority are eligible to run, they are ordered according to a strict run-to-completion (FIFO) policy.
to:
For process scheduling, POSIX.1-202x specifies a linear scheduling model. In this model, every process in the system has a priority. The system scheduler always dispatches a process that has the highest (generally the most time-critical) priority among all runnable processes in the system. As long as there is only one such process, the dispatching policy is trivial. When multiple processes of equal priority are eligible to run, they are ordered according to a strict run-to-completion (FIFO) policy. Thread scheduling is similar, except that the scheduling policy can be applied just to the threads within one process (PTHREAD_SCOPE_PROCESS scheduling contention scope) or to all threads system-wide (PTHREAD_SCOPE_SYSTEM scheduling contention scope). This and other considerations specific to thread scheduling are the subject of [xref to B.2.9.4]; the remainder of this section is described in terms of process scheduling but is also relevant to thread scheduling when read in conjunction with [xref to B.2.9.4].

There are no notes attached to this issue.




Viewing Issue Advanced Details
1609 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Objection Omission 2022-10-18 11:24 2022-11-01 15:24
geoffclare
 
normal  
Applied  
Accepted  
   
Geoff Clare
The Open Group
localedef
2911
96190
---
consequences of giving localedef a bad charmap
The EXTENDED DESCRIPTION on the localedef page says:
When conflicts occur between the charmap encoding values specified for symbolic names of characters of the portable character set and the implementation-defined assignment of character encoding values, the result is unspecified.

There are two omissions here:

1. It should make clear that "conflicts" include omissions. XBD 6.1 requires each supported locale to include the portable character set. The localedef page should say what happens if a user or application tries to create one that omits one or more characters from the portable character set.

2. If the result is unspecified, this means an allowed result is that localedef creates the locale. The description should address what happens if such a locale is used (or attempted to be used).
Change the quoted paragraph to:
When conflicts (including omissions) occur between the charmap encoding values specified for symbolic names of characters of the portable character set and the implementation-defined assignment of character encoding values, the result is unspecified. If the result is that localedef creates the specified locale, any attempted use of that locale by an application or utility results in undefined behavior.

After page 2912 line 96227 section localedef, add a paragraph to RATIONALE:
When conflicts (including omissions) occur between the charmap encoding values specified for symbolic names of characters of the portable character set and the implementation-defined assignment of character encoding values, it is recommended that localedef treats this as an error in order to prevent the undefined behavior that results if localedef creates the specified locale and an application or utility attempts to use it.
There are no notes attached to this issue.




Viewing Issue Advanced Details
1608 [Issue 8 drafts] Base Definitions and Headers Comment Enhancement Request 2022-10-14 11:27 2022-11-08 14:45
dannyniu
 
normal  
Applied  
Accepted As Marked  
   
DannyNiu/NJF
Individual
sysconf
--
--
Note: 0006008
Suggesting informative texts for bug-id339
Although creating as many threads as there are CPU cores is a simple way to maximize CPU usage, there are subtleties that make it not always the case. As explained in my proposed addition texts in the desired action.
Add informative texts to appropriate sections in sysconf:

Although the queries _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN provide a way for a class of "heavy-load" application to "guess" the optimal number of threads that can be created to maximize CPU usage, real-world environments have complications that affects the actual efficiency that can be achieved. For example:

- there may be more than one "heavy-load" application running on the system,
- the system may be battery power, and applications should co-ordinate with the system so as to ensure long-running task can pause, resume, and successfully complete even in the event of power outage.

In case where a strictly standard-conforming instance of "heavy-load" application wants to avoid the use of vendor-specific APIs, they may wish to create threads based on the logical partition of the long-running task, or utilize heuristics such as the ratio between execution-time and real-time.
Notes
(0006008)
geoffclare   
2022-10-20 15:58   
After D2.1 page 2061 line 66817 section sysconf(), add:
Although the queries _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN provide a way for a class of "heavy-load" application to estimate the optimal number of threads that can be created to maximize throughput, real-world environments have complications that affect the actual efficiency that can be achieved. For example:

  • There may be more than one "heavy-load" application running on the system.

  • The system may be on battery power, and applications should co-ordinate with the system to ensure that a long-running task can pause, resume, and successfully complete even in the event of a power outage.


In case a portable "heavy-load" application wants to avoid the use of extensions, its developers may wish to create threads based on the logical partition of the long-running task, or utilize heuristics such as the ratio between CPU time and real time.




Viewing Issue Advanced Details
1607 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Editorial Clarification Requested 2022-09-26 12:22 2022-11-01 15:22
nmeum
 
normal  
Applied  
Accepted As Marked  
   
Sören Tempel
ed
2691
87825
---
Note: 0005984
Operator associativity for address chain operator is not specified
The ed specification does not specify the operator associativity for the address chain operators (i.e. , and ;) in a normative section. The rationale section (which is in my understanding only informative) mandates the following address handling rules in the provided table in line number 87825 and 87834:

Address Addr1 Addr2
7,5,    5     5
7;5;    5     5

As such, it seems that the address chain operators are right-associative. That is, the address 7,5, must be evaluated as 7,(5,) and not as (7,5), since the latter would yield the address 1,$. However, to the best of my knowledge, this is never explicitly stated in the specification.

I already mentioned this as a side note in https://austingroupbugs.net/view.php?id=1582 [^] but it seems to me that this issue was overlooked and thus not addressed as part of the proposed interpretation, hence I am creating a separate bug report for it.
After the sentence starting in line 87370 add an additional sentence which clarifies that the <comma> and <semicolon> operators are right-associative and not left-associative.
Notes
(0005975)
kre   
2022-09-26 14:01   
(edited on: 2022-09-26 19:46)
I would agree that perhaps a better specification of address chains might
be required, but I don't believe that defining some kind of associativity
is the way to do it, the , and ; aren't operators as such, they're separators.

ed addresses are evaluated left to right, in order, and then the last N (where
the value of N depends upon the command being executed) are used.

It really is as simple as that.

When the separator is a ';' "." is set to the value of the preceding address
before the following one is evaluated.

I have no idea where the:
      That is, the address 7,5, must be evaluated as 7,(5,) and not as (7,5),
      since the latter would yield the address 1,$.
1,$ conclusion can possibly originate - where does the 1 come from? A first
address (7,5) would be 5 and 5, (as the table at lines 87376-82 shows)
 ==> 5,5 not 5,$ On the other hand 7,(5,) would be 7,(5,5) which would
be (if it meant anything at all) 7,5 which is eventually going to produce an
error if the command needs 2 addresses.

(0005976)
nmeum   
2022-09-26 16:54   
> I have no idea where the: 1,$ conclusion can possibly originate - where does the 1 come from?

Apologies if I am misunderstanding the specification here, but isn't this a question of applying the omission rules? According to the omission rules "," is expanded to "1,$" (line number 87377). Therefore, I assumed 7,5, to be evaluated (left to right) as follows when grouped from the left:

  7,5, -> (7,5), -> (7,5)(1,$) -> 1,$

Since 7,5 is already a valid address there are no omission rules to apply. As such, you would then expand "," to "1,$" (line number 87377) and then discard address until the "maximum number of valid addresses remain" (line number 87368). Assuming the command takes two addresses my understanding would be that one thus ends up with "1,$" with left to right evaluation order. This is, of cause, in violation with line number 87825, thus I assumed the specification requires grouping from the right:

  7,5, -> 7,(5,) -> 7,5,5 -> 5,5

> A first address (7,5) would be 5 and 5, [...]

Why would "(7,5)" be "5" and "5,"? Is this a typo and you mean "7" and "5,"? If so: Are you not grouping from the right then? Or do you mean that 7,5 should evaluate to 5? If so: where is this stated in the spec?
(0005977)
kre   
2022-09-26 19:30   
Re Note: 0005976

OK, I see now how you got the "1,$" but that's not the way things work.

    but isn't this a question of applying the omission rules?

Eventually, yes.

   Since 7,5 is already a valid address there are no omission rules to apply.

It is actually 2 addresses, but yes, that's correct otherwise.

   As such, you would then expand "," to "1,$"

No, that rule only applies when there is no address before (or after)
the ',', but that's not the case here, here there is an address before
the ',', "5" (and another before that, but that one is irrelevant now).
What we have is "5," not a bare "," and in that case line 87379 applies.

When you do: 7,5, -> (7,5), -> (7,5)(1,$)

you have managed to make 4 addresses (7 5 1 and $) with only 2
separators, and that makes no sense at all. There are 3 addresses,
you cannot invent a new one.

You wouldn't do that kind of transformation with arithmetic, you
don't do it here either -- consider 2*3*4 - treated as (2*3)*4 you
cannot make that into (2*3)(0*4) or even (2*3)(1*4) it just makes
no sense. We would end up with (6)(0) (or (6)(4)) - so should the
answer be either 60 or 64? I hope not.

    Why would "(7,5)" be "5" and "5,"?

No, not a typo, 7,5 is two addresses, when we proceed to the next addr,
only the 2nd of those means anything, hence "5" the separator is ","
so we are now evaluating "5," and line 87379 applies.

   where is this stated in the spec?

That goes back to the first sentence of my Note: 0005975 .. it probably
is not stated, and should be. But it is very dangerous to ever claim
something is not in the standard, one would need to know every word of
all of it, to be sure of that, and I don't think anyone claims that
ability. This doesn't mean that sections can't be improved, even if
that is not strictly necessary.

I suspect this might be one of those "everyone just knows" kinds of
things, no-one who really knows ed can even imagine address chains
being evaluated any other way. This is not the only time this
(apparently) has led to sloppy wording.

Perhaps the best demonstration of what is intended is this sentence,
also from the Rationale (and so, as you surmised, not normative, not
really a part of the standard - though it is possible to use to
resolve ambiguities).

From lines 87815-8:

    For example, the command "3;/foo/;+2p" will display the first
    line after line 3 that contains the pattern foo, plus the next
    two lines. Note that the address "3;" must still be evaluated
    before being discarded, because the search origin for the
    "/foo/" command depends on this.

["/foo/" is not a command, but an address, and that ought be fixed,
but that isn't the point here.]

If you attempt to apply your method to this address chain you will
absolutely not get the desired result.

But if you do simple left to right address evaluation, where the
',', or in this case ';' (do note that an address chain can use both
',' and ';' as separators) marks the division between the addresses
(only when not in a pattern of course) the result is obvious.

First address, "3" that's a simple case, line 3. Separator is ';'
so set '.' to 3. Second address "/foo/" search forward from '.'
looking for the r.e. (in this case, just a string) "foo"). Let's
assume that is found in line 12. Next separator is ';' so set '.'
to 12. Third address "+2" which means ".+2" or 14. So the
evaluated addr chain is 3 12 14

The 'p' command takes only (max of) 2 addresses, so the 3 is
ignored at this stage, and we print lines 12 13 and 14 (ie:
the first line after line 3 containing "foo" and the two following
lines, just as the text says will happen).

ed really is a very simply beast, if there is an easy way to explain
how something might work, and a complex one, the easy one will be
correct every time.
(0005978)
kre   
2022-09-26 19:55   
While we are here, playing with wording in ed - and at just about
the place a change ought to be made, there's another piece of
bizarre (though not incorrect) wording:

Lines 87365-6

    If more than the required number of addresses
    are provided to a command that requires zero addresses,
    it shall be an error.

"more than the required number of addresses ... to a command
that requires zero addresses"

Really!

Could this be changed into

    If addresses are provided to a command that takes zero addresses...
(0005979)
nmeum   
2022-09-27 08:59   
Thank you for your detailed comments.

> That goes back to the first sentence of my Note: 0005975 .. it probably is not stated, and should be.

But in that case we both agree that the specification currently does not describe how an address chain like "7,5," should be evaluated, that is the point of this clarification request. I think the discussion here clearly demonstrates that "reverse-engineering" the evaluation algorithm from examples such as "3;/foo/;+2p" or "7,5," can obviously lead to wrong results. All I am asking for is a clarification of this algorithm in a normative section. Grouping separators from the right was just me trying to make sense of the example chains in the rationale section.

> I suspect this might be one of those "everyone just knows" kinds of things, no-one who really knows ed can even imagine address chains being evaluated any other way. This is not the only time this (apparently) has led to sloppy wording.

I would just propose adding an additional sentence to the paragraph in line number 87370 to describe the address chain evaluation algorithm that "everyone just knows" but isn't stated in the specification currently.

> But it is very dangerous to ever claim something is not in the standard [...]

The "Addresses in ed" section (line number 87317), or more specifically, the paragraph in 87370 - 87373 (where the "," and ";" separators are introduced) is where I would have expected the algorithm to be described. As far as I can tell, it is not described in this section. For the purpose of clarification, it makes sense to describe the algorithm in this section.
(0005980)
geoffclare   
2022-09-27 09:24   
The relevant part of "Addresses in ed" is 87366-87369:
if more than the required number of addresses are provided to a command, the addresses specified first shall be evaluated and then discarded until the maximum number of valid addresses remain, for the specified command.

Once this rule has been followed there are no extra addresses and so the question of associativity simply never arises.
(0005981)
nmeum   
2022-09-27 12:39   
Feel free to close this issue if you feel that this is sufficiently specified. Maybe it is just me.
(0005982)
kre   
2022-09-27 16:06   
(edited on: 2022-09-27 16:12)
Re Note: 0005980

I agree the question of associativity never arises, but for a different
reason - it doesn't apply because the ',' and ';' are not operators
(the text is quite clear already that they are separators), the idea
that they could associate one way or the other would mean treating an
address chain as some kind of expression, which it isn't. Each address
is an entity in itself.

Re Note: 0005981

I am not sure that there is nothing to change however. In particular,
considering the words that Geoff quoted, which have an obvious meaning
to anyone who already knows what that obvious meaning is, are by no means
clear.

   the addresses specified first shall be evaluated and then discarded

might be

  (the addresses specified first) shall be evaluated and then discarded
or
   the addresses specified (first shall be evaluated and then discarded)

and in neither case does that say which order the addresses should be
evaluated, though lines 87371-2 say

   In the case of a <semicolon> separator, the current line ('.') shall
   be set to the first address,
that part isn't important for the current issue, but..
   and only then will the second address be calculated.
this is, as it requires the the first addr be calculated before the
second. But this only applies to ';' separators.

Consider
          /foo/;+2,/bar/

In ed, we all (or most of us) know that we search from . to find foo,
set . to that (and addr#1), addr#2 is addr#1+2, and then we search
forward from . (the updated .) to find bar, which gives us addr#3.
Then we use addr#3 (for one addr commands) or addr#2 and addr#3 for
two addr commands.

But nothing I see in the normative text requires that. If we first
evaluate the addresses, in some unspecified order except where the
separator is ';', then why not evaluate /bar/ first? Then /foo/
and finally +2 ? Then we discard the unnecessary ones (but which?)
Where does the normative text prohibit that?

This should be easy to fix, just change those lines 87366-87369
from

    if more than the required number of addresses are provided to
    a command, the addresses specified first shall be evaluated and
    then discarded until the maximum number of valid addresses remain,
    for the specified command.

into

    if more than the required number of addresses are provided to
    a command, the addresses shall be evaluated from first to last, and
    then discarded, until the maximum number of valid addresses remain,
    for the specified command.

And as well as doing that, in lines 87365-6 make the change suggested in
Note: 0005978 or something similar.

And third, in line 87818 change the word "command" to "address".

(0005984)
geoffclare   
2022-09-29 11:05   
Suggested changes ...

On page 2680 line 87365 section ed, change:
Commands accept zero, one, or two addresses. If more than the required number of addresses are provided to a command that requires zero addresses, it shall be an error. Otherwise, if more than the required number of addresses are provided to a command, the addresses specified first shall be evaluated and then discarded until the maximum number of valid addresses remain, for the specified command.
to:
Commands accept zero, one, or two addresses. If one or more addresses are provided to a command that accepts zero addresses, it shall be an error. Otherwise, if more than the maximum number of accepted addresses are provided to a command, the addresses shall be evaluated from first to last and then discarded, until the maximum number of accepted addresses for that command remain.

On page 2691 line 87812 section ed, change:
Any number of addresses can be provided to commands taking addresses; for example, "1,2,3,4,5p" prints lines 4 and 5, because two is the greatest valid number of addresses accepted by the print command.
to:
More than the maximum number of accepted addresses can be provided to commands taking addresses; for example, "1,2,3,4,5p" prints lines 4 and 5, because two is the maximum number of addresses accepted by the print command.

On page 2691 line 87818 section ed, change:
the search origin for the "/foo/" command depends on this.
to:
the search origin for the "/foo/" address depends on this.




Viewing Issue Advanced Details
1606 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Objection Clarification Requested 2022-09-23 23:11 2022-11-01 15:20
Clausecker
 
normal  
Applied  
Accepted As Marked  
   
Robert Clausecker
Zuse Institute Berlin
find
2761
90456–90458
---
Note: 0006009
find: is a directory loop considered to be an error?
The find(1) utility is specified to print a diagnostic message upon encountering a directory loop:

> The find utility shall detect infinite loops; that is, entering
> a previously visited directory that is an ancestor of the last file
> encountered. When it detects an infinite loop, find shall write
> a diagnostic message to standard error and shall either recover
> its position in the hierarchy or terminate.

What is not specified is if the find(1) utility shall consider this to be an error and return a non-zero exit status. While the Utility Description Defaults seem to indicate that a non-zero exit status shall be returned for any diagnostic message printed, it is not entirely clear if this applies to this case.

GNU find and SunOS find do. FreeBSD find(1) and Jörg Schilling's libfind/sfind neither print a diagnostic message nor return a non-zero exit status.

This situation most commonly occurs when operating with -L and a symbolic link to a directory up the hierarchy is encountered. Such cases seem to be benign and can easily be backed out of. Other cases (e.g. a true directory loop through misuse of hard links) may indicate a problem in the file system. It may be convenient for the user to search through symbolically linked directory hierarchies without the search failing through a case that doesn't really affect the search.

See also https://codeberg.org/schilytools/schilytools/issues/27 [^]
Please clarify if the find(1) utility is meant to consider a directory loop to be an error condition causing exit with a nonzero exit status. If it is intended to specify if it is, please add appropriate language, e.g.

> When it detects an infinite loop, find shall write
> a diagnostic message to standard error and shall either recover
> its position in the hierarchy or terminate. In either case,
> the exit status shall be nonzero.

If it is intended that the implementation is free to consider this to be an error condition or not, please add appropriate language to RATIONALE indicating that this.
Notes
(0005974)
geoffclare   
2022-09-26 10:54   
Since find is not allowed to write to standard error (except for the -ok prompt) when its exit status is zero, the requirement to write to standard error when an infinite loop is detected automatically brings with it a requirement that the exit status be nonzero.

See XCU 1.4 Utility Description Defaults -> STDERR -> Default Behavior.

However, it would make sense to state this explicitly, along the lines suggested in the desired action.
(0006009)
geoffclare   
2022-10-20 16:09   
After:
When it detects an infinite loop, find shall write a diagnostic message to standard error and shall either recover its position in the hierarchy or terminate.
add a new sentence:
In either case, the final exit status shall be non-zero.




Viewing Issue Advanced Details
1605 [1003.1(2016/18)/Issue7+TC2] System Interfaces Editorial Omission 2022-09-13 15:34 2022-11-01 15:09
steffen
 
normal  
Applied  
Accepted As Marked  
   
steffen
bind
626
21642ff
---
Note: 0005967
bind: AF_UNIX: extend EADDRINUSE description beyond "symbolic link"
bind(2) fails for AF_UNIX sockets if the desired name (path) already exists, regardless of the file type.
I'd presume the symbolic link case is already mentioned due to "following is forbidden" policies.
On page 626, line 21642ff change

If the address family of the socket is AF_UNIX and the pathname in address names a symbolic link, bind( ) shall fail and set errno to [EADDRINUSE].

to

If the address family of the socket is AF_UNIX and the pathname in address names an existing file, including a symbolic link, bind( ) shall fail and set errno to [EADDRINUSE].
Notes
(0005967)
geoffclare   
2022-09-13 15:56   
It seems odd to have this error specified in DESCRIPTION instead of ERRORS.

I think the intention was that the existing generic EADDRINUSE entry in ERRORS ("The specified address is already in use") covered most file-exists cases for AF_UNIX and only the symbolic link case needed special mention.

A better solution would be to spell out how the two relate. I'd suggest changing:
If the address family of the socket is AF_UNIX and the pathname in address names a symbolic link, bind() shall fail and set errno to [EADDRINUSE].
to:
If the address family of the socket is AF_UNIX and the pathname in address names an existing file, including a symbolic link, bind() shall treat the address as already in use; see ERRORS below.
(0005968)
steffen   
2022-09-13 20:28   
Yes, much smoother, much better. Thank you.




Viewing Issue Advanced Details
1604 [Issue 8 drafts] Shell and Utilities Editorial Clarification Requested 2022-09-12 16:56 2022-11-01 15:08
Don Cragun
 
normal  
Applied  
Accepted As Marked  
   
Don Cragun
stty utility
3188
108231-108235
Note: 0006010
stty default output for control characters
This is copied from austin-group-l e-mail sequence number 34789 posted by наб.

Issue 7 and Issue 8 Draft 2.1 say this (XCU, stty, STDOUT, last para.):
 If control characters are written as part of the default output, or if
 the −a option is specified, control characters shall be written as:
   "%s = %s;", <control-character name>, <value>
 where <value> is either the character, or some visual representation of
 the character if it is non-printable, or the string undef if the
 character is disabled.

undef is italicised, and matches the argument to character-valued
attributes like kill. On first glance, this makes sense.

However, every BSD release on the CSRG CDs since 3BSD,
SysIII, and SysVr{1,2,3,4} ‒ that is, every historical system /with/ a
disabling functionality ‒ as well as modern BSD, Illumos,
and the GNU system, render this as "<undef>".

This is very curious! /I/ was very curious, at least.

XPG3 stty (same as XPG2's) does not define the output format
(stty's primary purpose isn't to generate text,
so that fits with the XPG's "don't rely on this format" clause).

The XPG3-XPG4 migration guide lists some changes,
but none of them relevant here.

POSIX.2 Draft 11.2 (the only one extant on the internet :/) says:
 If control characters are written as part of the default output,
 or if the −a option is
 specified, control characters shall be written as:
   "%s = %s;", <control-character name>, <value>
 where value is either the character, or some visual representation
 of the character if it is nonprintable,
 or the string <undef> if the character is disabled.

And <undef> is monospace here!
This is "correct": it matches every implementation.

XPG4.2/SUSv1 in its change history cites
 Aligned with the ISO/IEC 9945-2: 1993 standard.
for Issue 4 amd says:
 If control characters are written as part of the default output,
 or if the −a option is specified,
 control characters will be written as:
   "%s = %s;", <<control>-character name>, <value>
 where value is either the character,
 or some visual representation of the character if it is non-printable,
 or the string <undef> if the character is disabled.

With <undef> in normal font
(this matches the formatting of its own control-character-argument table,
which has ^- and undef in normal font as well).

SUSv2/Issue 5 matches SUSv2 (except for the ^- in the table).
Its FUTURE DIRECTIONS says something about interpretations of P1003.2b,
but in draft 12 of that I didn't see anything relevant to this.

SUSv3/Issue 6 is the first one that formats this in the problematic way
described: both undef in the control-character-argument table and in the
STDOUT section are no-<> and italic:
 If control characters are written as part of the default output,
 or if the -a option is specified,
 control characters shall be written as:
   "%s = %s;", <control-character name>, <value>
 where <value> is either the character, or some visual representation
 of the character if it is non-printable, or the string undef if the
 character is disabled.

The only diff items for Issue 6 seem to be removing legacy items and
fixing the description of nl and -nl in XCU/TC1/D6/37.

I only checked the HTML version, but the formatting and wording are the
same for Issue 7 (HTML) and Issue 8 Draft 2.1 (PDF).

My naive interpretation of this is that, after loss of monospacing from
POSIX.2 to SUSv1, at some point in Issue 6's creation, "<undef>" was
taken to mean literal undef, i.e. italic undef, which is wrong,
but makes sense since use of <>s is very common to mean
"enclosed literal" or "literal symbol".

The fix would be to simply change italic undef on line 108235 (D2.1)
to monospace <undef> or bold <undef>.
Notes
(0005996)
geoffclare   
2022-10-18 11:32   
Two further editorial problems on the stty page have been reported by наб on the mailing list and could be addressed in this bug. I won't repeat the problem descriptions here. The requested changes are:

(mail sequence 34874)
Change "values" on line 107979 and 107982 to "value".

(mail sequence 34875)
On ll. 108152, 108155 replace "icanon" with "−icanon".
(0006010)
geoffclare   
2022-10-20 16:20   
Change italic undef on line 108235 (D2.1) to <tt>"<undef>"</tt>

Change "values" on line 107979 and 107982 to "value".

On ll. 108152, 108155 replace "icanon" with "−icanon".




Viewing Issue Advanced Details
1603 [Issue 8 drafts] Base Definitions and Headers Editorial Enhancement Request 2022-08-30 23:34 2022-11-01 15:05
calestyo
 
normal  
Applied  
Accepted As Marked  
   
Christoph Anton Mitterer
4.14 Pathname Resolution
94
2850 ff
Note: 0005952
minor error in the pathname resolution
Hey.

Pathname resolution says:
"A pathname that contains at least one non-<slash> character and that ends with one or more trailing <slash> characters shall not be resolved successfully unless the last pathname component before the trailing <slash> characters names an existing directory or a directory entry that is to be created for a directory immediately after the pathname is resolved."

But shouldn't it also resolve successfully when the last pathname component before the trailing <slash> characters names a symbolic link pointing to a existing directory?

Not sure if one should also allow a dangling symlink if the directory is to be created? I guess rather not because e.g.
$ ln -s non-existing dangling
$ mkdir -p dangling/sub

fails and probably should do so
In line 2852, after:
   "names an existing directory"
insert
   " or symbolic link that points to such"
Notes
(0005950)
calestyo   
2022-08-30 23:50   
(edited on: 2022-08-30 23:51)
I think there are further such cases:
- line 2840, "in the pathname fragment a/b, file b is located in directory a", a might not be a directory, but also a symlink pointing to such
- line 2875, "If the resulting pathname does not begin with a <slash>, the predecessor of the first filename of the pathname is taken to be the directory containing the symbolic link."... the predecessor could be a symlink, so shouldn't it somehow say that it's taken to be the target of such, if it is one?


Cases where I think it's really just directory:
- always when it says "directory entry"
- line 2839, "Each filename in the pathname is located in the directory specified by its predecessor", because of the "specified" which a symlink also does


Unsure:
- line 2842, "root directory of the process" ... I'd assume the process root dir is always resolved already to a true directory?, just as the current working directory in line 2845? ... Similar in line 2888

So better some expert check these :-) (thx)

(0005951)
calestyo   
2022-08-30 23:51   
(put one point into the wrong category in comment 0005950 ... so please take the edited version from the website, not any email)
(0005952)
geoffclare   
2022-09-01 08:23   
On the mailing list Lawrence Velázquez asked "Do lines 2857 through 2877 not address this sufficiently?" and Oğuz replied "They do".

Whilst I agree that the requirements are clear when those lines are taken into account, I think some minor wording changes would be helpful. I suggest:

On page 94 line 2839 change:
Each filename in the pathname is located in the directory specified by its predecessor (for example, in the pathname fragment a/b, file b is located in directory a).
to:
Each filename in the pathname is located in the directory specified by its predecessor (for example, in the pathname fragment a/b, file b is located in the directory specified by a).

On page 94 line 2851 change:
unless the last pathname component before the trailing <slash> characters names an existing directory or a directory entry that is to be created for a directory immediately after the pathname is resolved.
to:
unless the last pathname component before the trailing <slash> characters resolves (with symbolic links followed - see below) to an existing directory or a directory entry that is to be created for a directory immediately after the pathname is resolved.

I have not included any change for line 2875 - I believe "the directory containing the symbolic link" is fine. If this directory was arrived at via a symbolic link, it makes no difference as it is the directory itself that the text is referring to.
(0005953)
calestyo   
2022-09-01 13:20   
Hmm I guess it's clear for anyone who knows how it works, but maybe not so 100% in the definite sense.

Take my original message about:
"A pathname that contains at least one non-<slash> character and that ends with one or more trailing <slash> characters shall not be resolved successfully unless the last pathname component before the trailing <slash> characters names an existing directory or a directory entry that is to be created for a directory immediately after the pathname is resolved."


That says basically: "if the last component before the trailing / is not a directory, then don't succeed"
Now it's ambiguous at that point whether "names and existing directory" includes such referenced via a symlink or not.

Sure, lines 2857 through 2877 explain what happens with symlinks, but they come only *after* the above paragraph.

So - other than by knowing how it works - how could one tell that the symlink-rules still apply, and that resolution didn't already fail&stop because of the above?



As for your proposed changes: It's IMO not really defined what "specified" means here.
What would think about using a phrase like "in the directory named respectively referenced by a"?
That kinda would indicate a bit more that there's two kinds here.

Or perhaps the "resolves (with...) [to]" that you used in the other change?
(0005954)
geoffclare   
2022-09-01 13:46   
Re Note: 0005953 (last part), in Note: 0005950 you said that the part of line 2839 before the parentheses was okay «because of the "specified" which a symlink also does», so I proposed changing the text inside the parentheses to match that. Seems fine to me.
(0005956)
kre   
2022-09-01 16:17   
Re Note: 0005953

The whole standard needs to be read as a unit, it isn't a tutorial, and
you cannot simply pick a small section and read it in isolation and
expect to correctly understand what it is saying.

Paths are resolved left to right, the only way one discovers that
something doesn't exist, is by attempting to find it in its parent
directory. When that happens, if what is found is a symlink, then
the symlink resolution rules apply, and we replace the symlink (and
perhaps all that came before it) with the "value" of the symlink,
and go back to resolving again. At this point we haven't looked
beyond the '/' that terminated this pathname component, and have no
idea at all that nothing more follows. That we only determine later.

Normally anything followed by a '/' (after symlinks have been resolved)
must be a directory, and must exist (obviously, or we would not know that
it was a directory). But people, for reasons I never understood (I'd
simply prohibit the practice) want to be able to do "mkdir /path/newdir/"
when what they really mean is "mkdir /path/newdir".

The final component, the one not followed by a '/', not existing when
we are making something is normal, that is the name we want to create,
not one that exists (though sometimes creating something which already
exists is allowed, like open(path, O_CREATE)) and needs no special
handling. mkdir /path/newdir/ is a very special weird case, which that
paragraph quoted is dealing with. But nothing about the general process
of pathname resolution varies, we still resolve what we can, just that
special case applies, if a trailing "/" appears, then the preceding
component is treated as the final one, instead of the empty string after
the '/'.

FWIW I agree with the people on the mailing list, no changes are needed for
this one at all, not the ones proposed in Note: 0005952, nor any other.

That doesn't mean that there's anything wrong with the Note: 0005952
proposed wording, though the 2nd proposed change reads rather clumsily,
just that the changes aren't really needed.




Viewing Issue Advanced Details
1602 [Issue 8 drafts] Shell and Utilities Objection Omission 2022-08-23 16:33 2022-11-08 14:43
kre
 
normal  
Applied  
Accepted As Marked  
   
Robert Elz
XCU 2.14 exit XCU 2.14 return
2369, 2379
76750, 77069
Note: 0006012
No definition of "executed in a trap action"
This defect report could also be filed against issue 7 TC2, and
probably earlier versions as well, but the wording has changed
so much in this area that going back to discuss text which has already
been altered seems pointless. Hence filed against draft 2.1.

The wording of exit, when dealing with the case that no specific
status to use is given, is:

    If n is not specified, the result shall be as if n were specified
    with the current value of the special parameter '?' (see Section 2.5.2),
    except that when exit is executed in a trap action, the value for the
    special parameter '?' that is considered ``current'' shall be the value
    it had immediately preceding the trap action.

The wording for return is substantially the same, though the effects, and
required interpretation, are different.

So, first to consider exit. It seems likely (this requires some guesswork)
that the idea here, is that when an EXIT trap (or others, will come to those
soon) is executed, if the trap command says just "exit" - which will then
cause the shell to terminate, the status it terminates with should be the
status that it would have exited with had there been no EXIT trap, and
the shell had simply exited. That's fine, understandable, and the way
shells have behaved for a long time.

Doing the same for other traps is more likely just a "the way we run the
trap command is like this, so this is what happens" which is also OK,
though for the other traps actually depending upon this for anything is
kind of pointless, as the script writer can never know exactly where the
script will be when the trap needs to be taken, so the exit status would
be more or less random at that point.

That all seems good, but it is only meaningful because of the phrase I
included above (which is not anywhere in the standard), "which will then
cause the shell to terminate". Consider an alternative use of exit:

cleanup() {
    # various stuff not relevant
    if (cd /somewhere || exit; # cleanup stuff in /somewhere )
    then # do some more cleanup stuff
    else report cleanup failed, manual cleanup required
    fi
}

(Ignore the syntax error caused by the ')' being treated as part of
what is a comment, that comment would really be code in a real script).

and then

    trap 'echo Finishing; cleanup; exit' EXIT

(in which the exit is pointless, but makes for a better discussion).

Now assume that the code in the script, sometime later, does "exit 0"
That sets the status ($?) to 0, and then runs the EDIT trap before the
shell goes away.

There's no real question but that the wording in question applies to
exit that is in the string passed as the arg to the trap command, but
what about the one, executed in a subshell, in the cleanup function.

In that one, we may assume that perhaps the function was written long
ago, when no traps were being used, and the usage was

    cleanup; exit 0

that being a pattern (perhaps with different values for the exit status
throughout). In that case, it is clear, the exception of being in a
trap action does not apply, there is none, and the exit in cleanup returns
the status of the the failed cd command (we know it failed, or the exit
would not being executed). But then someone decided that it would be
cleaner to use an EXIT trap, remove all the calls to cleanup (perhaps there
were some exit's in the code, rarely encountered, which had omitted the
cleanup, and that bug is being fixed). Now cleanup is being executed in
a trap action. That's clear. But is the exit within the subshell within
cleanup also "executed in a trap action" or only text that is actually in the
trap action string? If were were to decide that it is the latter, then
let's assume that instead of just returning, cleanup ended with "exit".
That one, not being in a sub-shell, would cause the shell to terminate.
But with what status, the status from the last command in cleanup() which
is likely what the author of that function intended, or the value of $?
that was current when the EXIT trap was taken?

We don't know, because nothing in the standard (or nothing I can find)
tells us.

For return, things get even messier. That's because in general, return
is only defined when executed in a function. Simply executing a random "return" in a trap string (like was done with exit) is only meaningful if
we caqn guarantee that the trap will only fire while a function is running.

That's certainly possible to do, but not all that common. In practice
most 'return's that get executed are to return from a function which has
just been called.

That is
    func_performed=false
    func() {
        if $func_performed; then return; fi
        # perform whatever the function does
        func_performed=true
    }

In that func() will return 0 every time, the return will, as $? at
that point will be 0, because we know that $func_performed must have
been true or the return would not be being executed.

Now imagine that func() is called by some tree of function calls,
perhaps several times in different circumstanced. The root of that
set of functions iis a function done() (not shown here).

If we were to now do "trap done INT"

what does that mean to that return in func() - it has no impact at all
on the final value of $? when the trap action completes (that's controlled
by the done() function) and nothing here has any impact at all upon any
function that may have been executing when the trap occurred. To do
that there would need to be a an explicit "return" in the trap string,
anything in any function that is called applies only to that function.

Is the return in func() now executed in a trap action, and so required to
return whatever status was in $? when the SIGINT trap occurred? That
might not have been 0, so (depending upon how func() is used inn unshown code,
might alter the execution flow in unexpected ways --- the commented code
from func() might even have "return N" for some N != 0, with the intent to
alter the flow - but the one shown was not planned to do that.

Again, we cannot answer that question, as the standard does not tell us
what "executed in a trap action" actually means.

Further there have been different interpretations of all of this, it isn't
(any longer anyway) simply a case of "well it is obvious, we just didn't write
it down" as (some, at least one) shell authors have taken that wording, and
actually made their shell do (what is really) absurd things, because of it
(when it had previously been sane).

There was a thread on the mailing list

   https://www.mail-archive.com/austin-group-l@opengroup.org/msg06011.html [^]

in which this was briefly discussed, but none of the participants in
that discussion were people able to actually change the wording.

Hence this defect report, to force some attention by those who matter.
For exit, it should probably be "an exit command executed while a trap action
is being performed, which will cause the shell environment executing the
trap action to terminate".

That's closer to what might be workable, but even that isn't perfect.

Given that exit & return need two quite different definitions, the
magic phrase should probably simply be deleted from the standard,
and replaced inline by the appropriate definition.
Notes
(0005941)
kre   
2022-08-23 18:11   
Ugh, Mantis... I had to cut & paste my entire report, as the first time
I tried to submit it, Mantis claimed a "security violation" or something,
(suggested I may have submitted already - which obviously, I did not),
which I suspect was caused simply by the (lengthy) period it took me to
fill in the form for this one (it was over an houir for sure). I have
encountered similar before.

Anyway, I managed to miss cutting the first paragraph of the desired
action, which was intended to be:

  For "return" the definition of "executed in the trap action" probably
  should be "appears literally in the argument action to the trap command"
  which established the trap action now being taken. No other return should
  be considered.

I also ended up having had enough of this one, and didn't proof read
the report (almost at all) - consequently there are errors all over
the place (but I think the meaning is reasonably clear, despite that).

Pity Mantis has no way for ordinary mortals to edit their defect reports,
like it does for notes that were added, or I'd go back and clean up some
of the worst typos...

I wonder if I ever mentioned what I think of Mantis?
(0005942)
kre   
2022-08-23 18:27   
A way to word things might be:

for exit, rather than "except when exit is executed in a trap action" say
"except when exit is executed in the same execution environment as that in
which a trap action was invoked, that trap action is still executing, and
the exit would cause that execution environment to terminate"

and for return, rather than "except when when return is executed in a trap
action" say instead "except when return is executed in the same execution
evnironment as that in which a trap action was invoked, while that trap action
is still executing, and the return would cause a function that was executing
when the trap was invoked to be terminated"

I believe those produce sane results, and allow the "executed in a trap
action" remain undefined, as those words will no longer appear (unless of
course they're also somewhere else I'm not aware of, in which case that part
of the standard, whatever it is, will need fixing as well).
(0005943)
hvd   
2022-08-25 01:10   
Your proposed behaviour actually does suggest the same behaviour for exit and return, and the same wording could be used for both. Something along the lines of simply

  If the [exit/return] command would cause the end of execution of a trap action, the last command is considered to be the command that executed immediately preceding the trap action.

would cover it. I agree that this behaviour would be sane and if POSIX is changed to require or allow this, I have no problem changing my shell to implement this. However, while it is unclear to me what the POSIX wording currently requires, I believe there is no legitimate reading of the current wording that matches your expectations; this would be a change, not a clarification.

Note that your proposed behaviour is to say that

  trap ':; (exit); echo $?' EXIT; false

will be required to print 0, as exit is not executed in the same execution environment as that in which the trap action was executed. My shell does print 0, yours prints 1 (tested with the system shell of yesterday's NetBSD amd64 installation CD image), as does dash (which my shell is based on). Please actually check before dismissing others' work as absurd or insane.
(0005945)
kre   
2022-08-25 15:20   
Three responses to issues in Note: 0005943 (in a different order than
they appear there).

First, wrt the proposed wording - yes, that looks like it would work, I
didn't ever consider it that way. Provided that we actually want the
wording for exit & return to be the same (which risks the later
interpretation "we know what those words mean in case A, case B uses
the same words, so they must mean the same thing there" which is OK if
that really is the intent, but we need to be certain that the two are
really meant to be identical in all respects, otherwise it can be better to
use slightly different wording, and avoid that problem (that's why I varied
the wording I used just a little, in the exit and return cases).

Second, it wasn't anyone's work I was dismissing as absurd or insane, it
is the result produced. That's is as true of the NetBSD sh doing it as
any other shell - our shell (not mine, I'm just the current (major) maintainer
but I wrote only a tiny fraction of the code in there) has done absurd things
many times in the past, and almost certainly still does. They get fixed,
eventually, when discovered, and if possible.

But yes, I should have done a lot more testing of various shells, but
other than using the EXIT trap (which cannot be used to test everything)
actually running tests for this is difficult, as in a script, there's no
way I know of, to force the "value for the special parameter '?' that is
considered ``current'' shall be the value it had immediately preceding
the trap action." to be any known value - and if we don't know what it is,
we cannot test that it is being used when required (whenever we believe that
to be). This is just due to the nature of the conditions which invoke
trap actions, other than EXIT, when they occur is unpredictable.

Interactively it is possible, as one can set an exit status, and then
just do nothing, until after the trap action has occurred (sending the
occasional \n to cause new prompts to be written, and allow the trap
to happen). That works, but is ***slow*** and tedious to do. Hence I
was prevaricating ... this defect report was discussed (in other places,
and in private e-mail, in the early days of this month - and I had promised
(just private e-mail I think) to submit this back then ... but waiting for
me to get the energy to do more testing (or almost any testing) kept delaying
it, and since there was no end in sight to that problem, I thought I should
just go ahead anyway - test results can always be added as a note (like this)
by me later (or by anyone else who can add notes, like hvd, as one example).



And third, for the most complex one to reply to - this is going to take some
time (ie: many lines following...)

I think the current wording can be read to to meet my expectations, perhaps
with just one minor change (I'd prefer to be incompat with any possible
reading in this one way, but if that's unacceptable, it would not be fatal).

Start by accepting that "executed in a trap action" might mean "the
exit (or return, as appropriate) must appear literally in the action
string of the trap command, for the condition which occurred, such that
the action is invoked. Whether it does mean that is unknown, but since
we are just looking for "any legitimate reading" this is certainly one
possibility.

Two problems arise from this, the first is the one I mention just above,
which is that if we had

    func()
    {
         # do something, then perhaps conditionally
         exit
    }

and we then do

    trap func $CONDITION

then by this reading, that exit in func would not be one that is executed
in the trap action, and so would exit with the status of the final command in
"do something" rather than the status from before the action was invoked,
which my proposed wording (and your version of that) would require.

So, yes, that would be a change. But we do not have to make that change,
we could define "executed in the trap action" to mean just what I said is
one possible reading, and leave it at that.

Applications which wanted to write code like the above is intended to be
would need instead to write


    func()
    {
         # do something, then perhaps conditionally
         exit $1
    }

    trap 'func $?' $CONDITION

where, since nothing has happened in the action when $? is expanded,
the value produced by expanding it must be the value it had immediately
before the trap action was invoked, just as it would be in

   (exit 13)
   eval 'func $?'

which is exactly what is supposed to happen with the (most recent) trap
command above, assuming that $CONDITION happened to arise just when (exit 13)
was finishing. $? will be 13, and func (as modified) will do exit 13.

I'd prefer not to have to go that route, but if we were to be required to
simply be explaining what the words have always meant, and we just didn't
know it, rather than changing anything, this would be one way.

The second issue is your example

    trap ':; (exit); echo $?' EXIT; false

In that, the "exit" is literally in the action string, so it might
seem that that one would be required (in this example) to do exit 1
(as you say the NetBSD sh currently does, and which I have just confirmed,
and which I can certainly change - but won't do until I at least get a
sense of the likely outcome of this defect report) rather than the exit 0
which you (correctly) interpreted as being the intent of my proposed
resolution (also your version).

Howver "might seem" is not "necessarily is". There that exit is
(quite clearly) executed in a subshell environment. That subshell
is executed in the trap action, but what is the state of the subshell
environment wrt "executing in a trap action". This is where we can get
creative (but still remain legitimate).

XCU 2.12 (on page 2350 in Issue 8 draft 2.1) defines what the shell
execution environment is. Whether or not a trap action is currently
executing is not in the list. Hence, that status is not part of the
shell execution environment.

XCU (also in 2.12, but this time on page 2351 of the same draft)
says of subshell environments

    A subshell environment shall be created as a duplicate of the shell
    environment, except that:

None of the exceptions is material here. Since the "executing in a
trap action:" is (as just discovered) not part of the shell execution
environment, there is no requirement that that status be duplicated in
the subshell environment. Hence doing exit 0 as your shell does (apparently)
is perfectly legitimate as the text is written now.

Further, you're not the only shell to act that way - bash bosh yash and zsh
all do as well, so does an ancient pdksh. But mksh and ksh93 do not
(nor as you point out do ash derived shells - other than yours). mksh and ksh93
are actively maintained (ksh93, in a sense) so it is reasonable to assume might
have been updated to match an apparent reading of this requirement in the
standard - but perhaps not the correct (intended) reading. Who knows?
I have no idea what ksh88 does with that, I'd kind of guess, based upon pdksh
and bosh's behaviour, that it might print 0 as well.

For return there are no issues like this, to cause the executing function
to return, the "return" in question must be literally in the action string
(and not in a subshell) so for this reading of what the current words
mean (or at least can be interpreted to mean) the proposed resolution for
return has no problems.
(0005946)
kre   
2022-08-25 15:49   
There is another defect that we might want to fix as part of this issue.

XCU 2.14/trap says

   The value of "$?" after the trap action completes shall be the value
   it had before the trap action was executed.

yet it is quite clear (from any reading) that XCU 2.14/exit and XCU2.14/return
mandate, than when given an explicit status to return, those two commands
do alter the value of "$?" after the trap action completes (when one of those
commands is the last executed in the trap action).

That's deliberate, it allows an trap action like the following

     trap 'cleanup || exit 1' EXIT

when invoked by

     exit 0

to cause the script to exit with status 1, rather than 0, in the event that
cleanup failed. That is intended, and desirable, I think.

The same applies to a trap action whose purpose is to make a function
return with a specific value, regardless of what the value of $? might
have been at the point in the function where the action was invoked.

The wording above (from XCU 2.14/trap) needs to be corrected.
(0006012)
geoffclare   
2022-10-24 15:31   
(edited on: 2022-10-24 15:37)
On page 2369 line 76750 section 2.14 exit, change:
when exit is executed in a trap action
to:
if the exit command would cause the end of execution of a trap action


On page 2379 line 77069 section 2.14 return, change:
when return is executed in a trap action
to:
if the return command would cause the end of execution of a trap action






Viewing Issue Advanced Details
1601 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Objection Error 2022-08-23 15:09 2022-11-08 14:13
kre
 
normal  
Applied  
Accepted  
   
Robert Elz
XCU 2.14 cd
2562
82969 - 82971
---
See Desired Action
when cd sets OLDPWD not all shells export it to the environment
The cd utility description includes thus

   If, during the execution of the above steps, the PWD environment variable is
   set, the OLDPWD environment variable shall also be set [...]

(what it gets set to is not the issue). The same sentence appears in Issue 8
draft 2.1 (lines 82512-4)

For OLDPWD to be an "environment variable" (as defined in XBD 8.1) it needs to
be exported in shell terminology. Otherwise it would simply be a variable
(as for example used in the getopts and read utilities).

It turns out that only about half the shells I have available to test
cause OLDPWD to be exported. The ash derived shells all do, as does
ksh93 and zsh. But bash, bosh, pdksh, mksh, and yash do not. I don't
know what ksh88 does.

The simple test is:
     unset OLDPWD; # so it is not exported from the current environment
     cd /anywhere/that/exists
     env | grep OLDPWD

All shells I tested set the variable OLDPWD in this case, they just
don't all export it (to make it become an environment variable).

One could also discuss PWD in a similar vein, but for PWD things become
unspecified if the user/application sets or unsets it, so that one gets
to be impossible to easily test.
Change the sentence above by deleting the word "environment" after OLDPWD,
and then add another sentence

    It is unspecified whether, when setting OLDPWD, the shell also causes
    it to be exported if it was not already.

Or something like that.

Alternatively, if the standard really is intending to require implementations
to export OLDPWD when it is set by the cd command, then it clearly needs to be
more explicit in how it states that.
There are no notes attached to this issue.




Viewing Issue Advanced Details
1600 [1003.1(2016/18)/Issue7+TC2] Rationale Comment Error 2022-08-23 09:28 2022-11-08 14:41
geoffclare
 
normal  
Applied  
Accepted As Marked  
   
Geoff Clare
The Open Group
C.1.7 Built-In Utilities
3716
127366
---
See Note: 0006015.
Problems with the suggested single-line shell script: $0 "$@"
On the mailing list, Jakub Wilk reported a problem with the rationale in C.1.7 that talks about implementing the 16 (sic) regular built-ins as a single-line shell script:
$0 "$@"

As he pointed out, "This wouldn't actually work: $0 is the absolute path, so the script would recurse indefinitely."

Another problem is that these external utilities are supposed to be exec-able using "the exec family of functions", which means all six functions not just execlp() and execvp(), so the script needs a #! line (and can only meet the requirements on systems that support #!).

Finally, the number 16 is out of date, as there are now 20 utilities in the table in XCU 1.7.
Change:
However, it has been pointed out that all 16 utilities in the table can be provided with 16 links to a single-line shell script:
$0 "$@" 
to:
However, it has been pointed out that, on systems that support the (non-standard but ubiquitous) "#!" mechanism to make scripts executable by the exec family of functions, all of the utilities in the table can be provided as links to a two-line shell script:
#! /path/to/sh
${0##*/} "$@"

Notes
(0005940)
kre   
2022-08-23 14:32   
(edited on: 2022-08-23 14:36)
I will start with the completely irrelevant, and just point out that
this bug is filed against Issue7 TC2, in which there is no XCU 1.7 to
have a table to have grown more entries... Further in the drafts
for Issue 8, in which there is an XCU 1.7, which does have a table
showing a list of built in utilities, at least in D2.1, that table has
16 entries, not 20, but has absolutely nothing to do with the subject
of this issue.

That said, I agree, it is not a good idea to specify a specific number
of utilities here, XCU 1.6 (both issues) where the requirement is specified
doesn't say how many, it just says everything except the special built-in
utilities, so removing the explicit number from XRAT is a wise decision.

However, it while giving an example using #! /..../sh as a means to
implement this requirement provides one means to satisfy the requirements,
the standard doesn't mandate #!, and it might be possible, perhaps, for
there to be a system somewhere which doesn't support it. As best I can work
out, the only other ways that the applicable utilities (or most of them)
can be implemented is to make them links to the shell, (or some shell)
and have that shell use argv[0] to decide what to do. That is, if
argv[0] == "cd" (assuming C had a comparison operator that worked on strings
that way) then simply execute its built in cd command. Or, to write
a simple C program, which amounts to just

     main(int argc, char **argv)
     {
          char *command = NULL;
          size_t len = 1;

          while (argc-- >= 0) {
              command = realloc(command, (len += strlen(*argv) + 3));
              strcat(command, " '");
              strcat(command, *argv++);
              strcat(command "'");
          }
          execl("/path/to/sh", "-c", "--", command, NULL);
      }

Of course, with error checking, and the quoting dealing with the possibility
that one (or more) of the args might contain ' characters (that's all just
programming, not design). That or something functionally similar.

Assuming that is correct (I shall explain why just below) then XRAT probably
should also give examples that show implementing it those ways, or at least
mention them as an implementation technique.

In the first case (links to sh which then uses argv[0]) it would also need to
explain what to do if the shell was given shell type arguments along with
an argv[0] which refers to a built in command, which has precedence, and if it
is to be argv[0] what happens when it is neither "sh" nor one of the
built in commands (which I'd assume would just be unspecified).

The reason for these (or perhaps something else very much the same I'm unable
to think of at the minute) is that to implement (at least most of) the
normally built in utilities (as opposed to things like test, echo, printf and
pwd, which the shell often has built in just because they are used so much
in scripts, but which always also exist as filesystem commands) requires
that they be running in a shell environment. There are a few exceptions,
but they are rare.

There is also kill which is also always available as an external command,
though it also needs to be built into the shell to perform all its functions.

It isn't just to do what they are supposed to do which makes this
a requirement, the standard actually mandates it.

Eg: in XCU 2.14/alias (one of the affected built in commands), we see:

   An alias definition shall affect the current shell execution environment

"shall" so it is mandatory, and to affect the current shell execution
environment, there must be a current shell execution environment to affect.

And bg:

    If job control is enabled (see the description of set -m), the bg
    utility shall resume suspended jobs from the current environment

Of course, there will be no jobs to resume, but there must be a current
environment to not find any in, and that environment must have a "set -m"
which can enable job control. Because there will no jobs to resume,
the later wording, which is even more explicit, probably doesn't apply.

cd:
    The cd utility shall change the working directory of the current shell
    execution environment

command:
    The command utility shall cause the shell

fc:
    The fc utility shall list, or shall edit and re-execute, commands
    previously entered to an interactive sh.

Then fg, which is, unsurprisingly, very similar to bg

getopts:
    Each time it is invoked, the getopts utility shall place the value
    of the next option in the shell variable

hash:
    The hash utility shall affect the way the current shell environment

jobs:
    The jobs utility shall display the status of jobs that were started
    in the current shell environment;

kill is mentioned above.

read:
    The read utility shall read a single logical line from standard input
    into one or more shell variables.

type is the very rare case of a built in command, not always implemented
as a filesystem command, which actually could be, without there being a shell.
Its results would be meaningless however, as how a command name is interpreted
depends upon the environment of the shell which is interpreting it (what
is a built in command in one shell might be an alias in another, and a file
system command in a third, and defined as a function in a fourth - a shell
agnostic type command cannot possibly do more than test whether the name exists
in PATH, which while not completely useless, isn't of much benefit either.

ulimit is another rare case, perhaps the one normally built in command
(required to be built in, it is one of the intrinsic commands which the table
in XCU 1.7 lists) which it is possible to implement properly outside a
shell (the options which change limits affect only the ulimit process itself,
so they're useless, but the limits can be reported).

umask:
    The umask utility shall set the file mode creation mask of the current
    shell execution environment

unalias:
    The aliases shall be removed from the current shell execution environment;

wait:
    If the wait utility is invoked with no operands, it shall wait until all
    process IDs known to the invoking shell

That's 16. To get to 20 we'd need to add some of (not sure which
were the blessed extra 4) true false printf pwd echo (and perhaps other
commands which are sometime built in - basename dirname expr). Perhaps
Geoff will list the (currently) 20 utilities he believes the requirement
to apply to (here, not in the standard).

The magic 16 happen (not by coincidence I expect)_ to be exactly the ones
required to be intrinsic in Draft2.1 XCU 1.7 table 1-5. And aside from kill
(which is always avalable as a filesystem command), and perhaps ulimit,
and type - all required a shell environment in order to be implemented.

Aside from kill (which I agree should remain implemented as a filesystem
coimmand) it really makes no sense at all to implement the others that way,
and it is fanciful (even absurd) to imagine scripts running "nohup bg" or
"find ... -exec cd {} \;" or anything else like that, in any productive way
(as opposed to simply testing whether or not they can).

So, please, can we change the wording of XCU 1.6 so that it exempts the
utilities required to be intrinsic by the standard, other than kill,
from the requirement that they be implemented so as to be able to be
exec()'d ?

There's no point to it, and they almost all require a shell.

Other standard utilities built into a shell (whether declared by the
implementation to be intrinsic or not) can remain required to be available
via exec (and always are I believe). The relevance of this to this defect
report, is that if the standard were to be changed this way, there is no
need for any of this in XRAT at all. No-one needs to be told how to
implement printf, echo, true (even kill) any more than they need to be told
how to implement awk or cut or ls. No need to attempt to justify the
(really) unjustifiable, and no need to give implementation examples to show
how it might be done (to no-one's benefit) Just remove the lot.

(0006015)
geoffclare   
2022-10-27 15:17   
Change:
However, all of the standard utilities, including the regular built-ins but not the special built-ins described in [xref to 2.14], shall be implemented in a manner ...
to:
However, all of the standard utilities other than:

  • The special built-ins described in [xref to 2.14]
  • The intrinsic utilities named in [xref to Table 1-5], except for kill
shall be implemented, regardless of whether they are also implemented as regular built-ins, in a manner ...


On page 3615 line 124885-124906 section C.1.7, change:
All of the regular built-in utilities [...] These arguments were ultimately the most effective.
to:
Earlier versions of this standard required that all of the regular built-in utilities, including intrinsic utilities, could be exec-ed. This was always a contentious requirement, and with the introduction of intrinsic utilities the standard developers decided to exempt the utilities that this standard requires to be intrinsic, with the exception of kill. The kill utility is still genuinely useful when exec-ed, only lacking support for the % job ID notation, whereas examples given of uses for the other utilities that are now exempted were considered contrived (such as using cd to test accessibility of a directory, which can be done using test -x). If an application needs exec-able versions of some of the exempted intrinsic utilities, it can easily provide them itself, on systems that support the (non-standard but ubiquitous) "#!" mechanism to make scripts executable by the exec family of functions, as links to a two-line shell script:
#! /path/to/sh
${0##*/} "$@"
(0006016)
kre   
2022-10-28 04:37   
Thanks for that resolution, it should come as no surprise
that I support it completely.




Viewing Issue Advanced Details
1599 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Objection Error 2022-08-15 10:26 2022-11-08 14:10
geoffclare
 
normal  
Applied  
Accepted  
   
Geoff Clare
The Open Group
strings
3259
109562
---
Unspecified behaviour for "strings -" too narrow
The strings DESCRIPTION says:
If the first argument is '-', the results are unspecified.

However, many implementations also treat '-' as special when it is not the first argument. They handle it as if it were a -a option, so:

strings -n 1 - file

is equivalent to:

strings -n 1 -a file

On Solaris, macOS, and HP-UX, this includes still recognising options after '-', e.g. for:

strings -n 1 - -t x file

the -t x is recognised as an option. (Whereas GNU, with POSIXLY_CORRECT, reports that files named -t and x were not found.)

GNU, Solaris, and HP-UX also treat an operand of '-' that is not the first argument as special. (For GNU it turns on -a for later files; for Solaris it turns on -a for all files; for HP-UX it is treated as a file named '-a'!)
On page 3259 line 109562 section strings, change:
If the first argument is '-', the results are unspecified.
to:
If any argument is '-', the results are unspecified.

There are no notes attached to this issue.




Viewing Issue Advanced Details
1598 [1003.1(2016/18)/Issue7+TC2] System Interfaces Editorial Enhancement Request 2022-08-06 17:37 2022-11-08 14:09
alanc
 
normal  
Applied  
Accepted As Marked  
   
Alan Coopersmith
Oracle Solaris
putenv
(page or range of pages)
(Line or range of lines)
---
Note: 0006013
putenv should be allowed to fail with EINVAL
setenv() is required to fail and return EINVAL if "The envname argument points
to an empty string or points to a string containing an '=' character." in
order to keep the environment in the expected "name=value" format.

putenv() currently states 'The string argument should point to a string of the form " name= value ".' but does not state what happens if that is not true.

Some implementations currently accept invalid values while others check and
reject them.

GNU libc has added an extension to accept strings without an '=' character as
an alias to unsetenv(), but does not seem to check for empty strings or
otherwise generate EINVAL errors:
   https://man7.org/linux/man-pages/man3/putenv.3.html [^]
   https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/putenv.c [^]

musl libc does the same as GNU libc:
   https://git.musl-libc.org/cgit/musl/tree/src/env/putenv.c?h=v1.2.3 [^]

OpenBSD returns -1 and sets errno to EINVAL if the string does not contain
an '=' character:
   https://man.openbsd.org/putenv.3 [^]
   https://github.com/openbsd/src/blob/master/lib/libc/stdlib/setenv.c [^]

FreeBSD is similar to OpenBSD but also generates EINVAL if the string is NULL,
or the '=' is the first character of the string:
   https://www.freebsd.org/cgi/man.cgi?query=putenv&sektion=3&format=html [^]
   https://cgit.freebsd.org/src/tree/lib/libc/stdlib/getenv.c?h=release/13.1.0#n614 [^]

NetBSD performs the same checks as FreeBSD:
   https://man.netbsd.org/putenv.3 [^]
   https://github.com/NetBSD/src/blob/trunk/lib/libc/stdlib/putenv.c#L59-L63 [^]
   https://github.com/NetBSD/src/blob/trunk/lib/libc/stdlib/_env.c#L123-L148 [^]

illumos only checks for the string containing an '=', and if not, follows
GNU libc in passing it to unsetenv() and does not ever generate EINVAL:
   https://github.com/illumos/illumos-gate/blob/master/usr/src/lib/libc/port/gen/getenv.c#L337-L351 [^]
   https://illumos.org/man/3C/putenv [^]

Solaris prior to Solaris 11.4.27 performed no checks on the string and would
never generate EINVAL:
   https://docs.oracle.com/cd/E86824_01/html/E54766/putenv-3c.html [^]
This has changed in Solaris 11.4.27 and later, in which Solaris will return
-1 and set errno to EINVAL if the string is empty or starts with '=', and
pass the string to unsetenv() if the string has a variable name but no '='.
(The man page changes documenting this are in process and not yet published.)
Add to the 'The putenv() function may fail if:' list in the ERRORS section:

[EINVAL]
    The string argument is not a pointer to a string of the form "name=value".

Listing this as "may" fail instead of "must" fail maintains compatibility with
all of the implementations discussed above, including those with the extension
to unsetenv a name provided with no '=value'.
Notes
(0005926)
geoffclare   
2022-08-08 09:02   
The EINVAL error is already allowed courtesy of the general rules for additional errors (XSH 2.3). However, adding it is worth doing so that implementations can't choose a different error value instead of EINVAL for this condition. (Although the suggested wording is not quite right as it also covers, for example, a null pointer.)

More importantly, just adding the EINVAL error is not sufficient to allow the new Solaris behaviour (and Illumos, glibc and muslc). The first sentence of the putenv() description is `The putenv() function shall use the string argument to set environment variable values.' Notice the word set. This would not be a problem if it later said `The application shall ensure that the string argument points to a string of the form "name=value"', as the absence of an "=" would then be undefined behaviour, but because it only says `should', putenv() is required only to set, never unset, environment variables if it succeeds.

To allow putenv("name") to remove "name" from the environment, a more extensive rewording will be needed. I think it should explicitly only allow two behaviours (removing "name" or failing with EINVAL).
(0006013)
geoffclare   
2022-10-25 10:56   
Suggested changes...

On page 1751 line 56642 section putenv(), change:
The putenv() function shall use the string argument to set environment variable values. The string argument should point to a string of the form "name=value". The putenv() function shall make the value of the environment variable name equal to value by altering an existing variable or creating a new one. In either case, the string pointed to by string shall become part of the environment, so altering the string shall change the environment.
to:
The putenv() function shall use the string argument to set, or optionally unset, an environment variable value:

  • If the string argument points to a string of the form "name=value", where name is a valid name, the putenv() function shall make the value of the environment variable with that name equal to value by altering an existing variable or creating a new one. In either case, the string pointed to by string shall become part of the environment, so altering the string shall change the environment.

  • If the string argument points to a string containing a valid name, the putenv() function shall either remove the environment variable with that name (if it exists) from the environment or fail with errno set to [EINVAL].

  • Otherwise, the behavior is unspecified.

After page 1751 line 56652 section putenv(), add:
[EINVAL]
The string argument points to a string that is not of the form "name=value", where name is a valid name.




Viewing Issue Advanced Details
1597 [1003.1(2016/18)/Issue7+TC2] Base Definitions and Headers Editorial Error 2022-08-05 02:44 2022-11-08 14:07
dannyniu
 
normal  
Applied  
Accepted  
   
DannyNiu/NJF
Individual
<time.h>
426
14475-14481
---
clockid_t are not usable with the clock() function and the text should say clock*() functions.
In this header, it is mistakenly said that a few identifiers with
value assignment-compatible with clockid_t can be used with
clock() and timer*(), when in fact, the clock() function doesn't
take an arguement.
Change:

CLOCK_PROCESS_CPUTIME_ID
The identifier of the CPU-time clock associated with the process making a
clock() or timer*() function call.

...

The identifier of the CPU-time clock associated with the thread making a
clock() or timer*() function call.
CX The <time.h> header shall define the following symbolic

To:

CLOCK_PROCESS_CPUTIME_ID
The identifier of the CPU-time clock associated with the process making a
clock*() or timer*() function call.

...

The identifier of the CPU-time clock associated with the thread making a
clock*() or timer*() function call.
CX The <time.h> header shall define the following symbolic
There are no notes attached to this issue.




Viewing Issue Advanced Details
1595 [Issue 8 drafts] Base Definitions and Headers Editorial Error 2022-07-31 14:43 2022-08-19 15:30
dennisw
 
normal  
Applied  
Accepted  
   
Dennis Wölfing
unistd.h
436-437
15215-15222
_SC_TRACE* symbolic constants should have been removed
When the POSIX Tracing option was removed as part of 0001330 the _SC_TRACE* symbolic constants were removed in the description of the sysconf() function but they were not removed from <unistd.h>.
On pages 436-437 delete lines 15215-15222:
_SC_TRACE
_SC_TRACE_EVENT_FILTER
_SC_TRACE_EVENT_NAME_MAX
_SC_TRACE_INHERIT
_SC_TRACE_LOG
_SC_TRACE_NAME_MAX
_SC_TRACE_SYS_MAX
_SC_TRACE_USER_EVENT_MAX
There are no notes attached to this issue.




Viewing Issue Advanced Details
1594 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Comment Error 2022-07-29 11:06 2022-08-19 15:13
geoffclare
 
normal  
Applied  
Accepted  
   
Geoff Clare
The Open Group
command, env, nice, nohup, time, xargs
2598 and more
84368 and more
---
App usage about exit code 127 is wrong
The command, env, nice, nohup, time, and xargs utilities all have a paragraph in APPLICATION USAGE that begins:
The command, env, nice, nohup, time, and xargs utilities have been specified to use exit code 127 if an error occurs so that applications can distinguish ``failure to find a utility'' from ``invoked utility exited with an error indication''.

This statement is only true for the command and nohup utilities where exit status 127 is described as:
An error occurred in the command utility or the utility specified by command_name could not be found.
(and likewise for nohup).

For all of the others, the exit status when an error occurs in the utility itself is specified as 1-125.

Note that the suggested new text matches that proposed for the new timeout utility in bug 1586 Note: 0005920. If it is changed here it will need to be changed there as well.
On page 2598 line 84368 section command, and
page 2694 line 87948 section env, and
page 3028 line 100764 section nice, and
page 3041 line 101203 section nohup, and
page 3299 line 111054 section time, and
page 3450 line 116526 section xargs, change:
if an error occurs
to:
if a utility to be invoked cannot be found

On page 2598 line 84370 section command, and
page 3041 line 101205 section nohup, after:
... ``invoked utility exited with an error indication''.
add:
However, the command and nohup utilities also use exit code 127 when an error occurs in those utilities, which means exit code 127 is not universally a ``not found'' indicator.

There are no notes attached to this issue.




Viewing Issue Advanced Details
1592 [Issue 8 drafts] Shell and Utilities Comment Enhancement Request 2022-07-15 08:36 2022-11-08 14:38
geoffclare
 
normal  
Applied  
Accepted  
   
Geoff Clare
The Open Group
printf
3085
104307
Add %n$ support to the printf utility
During the work on adding gettext, it was suggested that we should also add support for %n$ in format strings to the printf utility, to allow argument reordering by translators.

This is not as straightforward as it might seem, as per the email thread "Adding %n$ conversions to the printf utility" in Sept 2021.

One of the points raised in the thread was that it would be preferable for printf to treat a missing argument as an error when %n$ is used. The suggested changes recommend this (via the use of "should") but also allow the null/zero behaviour that happens for unnumbered argument conversions.
On page 3085 line 104307 section printf, insert a new item 8:
Conversions can be applied to the nth argument operand rather than to the next argument operand. In this case, the conversion specifier character '%' is replaced by the sequence "%n$", where n is a decimal integer in the range [1,{NL_ARGMAX}], giving the argument operand number. This feature provides for the definition of format strings that select arguments in an order appropriate to specific languages.

The format can contain either numbered argument conversion specifications (that is, ones beginning with "%n$"), or unnumbered argument conversion specifications, but not both. The only exception to this is that "%%" can be mixed with the "%n$" form. The results of mixing numbered and unnumbered argument specifications that consume an argument are unspecified.

and renumber the later items.

On page 3085 line 104307 section printf, change:
For each conversion specification that consumes an argument, the next argument operand shall be evaluated and converted to the appropriate type for the conversion as specified below.
to:
For each conversion specification that consumes an argument, an argument operand shall be evaluated and converted to the appropriate type for the conversion as specified below. The operand to be evaluated shall be determined as follows:

  • If the conversion specification begins with a "%n$" sequence, the nth argument operand shall be evaluated.

  • Otherwise, the evaluated operand shall be the next argument operand after the one evaluated by the previous conversion specification that consumed an argument; if there is no such previous conversion specification the first argument operand shall be evaluated.

If the format operand contains no conversion specifications that consume an argument and there are argument operands present, the results are unspecified.

On page 3085 line 104310 section printf, change:
9.
The format operand shall be reused as often as necessary to satisfy the argument operands. Any extra b, c, or s conversion specifiers shall be evaluated as if a null string argument were supplied; other extra conversion specifications shall be evaluated as if a zero argument were supplied. If the format operand contains no conversion specifications and argument operands are present, the results are unspecified.
to:
10.
The format operand shall be reused as often as necessary to satisfy the argument operands. If conversion specifications beginning with a "%n$" sequence are used, on format reuse the value of n shall refer to the nth argument operand following the highest numbered argument operand consumed by the previous use of the format operand.
11.
If an argument operand to be consumed by a conversion specification does not exist:

  • If it is a numbered argument conversion specification, printf should write a diagnostic message to standard error and exit with non-zero status, but may behave as for an unnumbered argument conversion specification.

  • If it is an unnumbered argument conversion specification, any extra b, c, or s conversion specifiers shall be evaluated as if a null string argument were supplied and any other extra conversion specifiers shall be evaluated as if a zero argument were supplied.

and renumber the later items.

After page 3087 line 104372 section printf, add a new paragraph:
Unlike the printf() function, when numbered conversion specifications are used, specifying the Nth argument does not require that all the leading arguments, from the first to the (N-1)th, are specified in the format string. For example, "%3$s %1$d\n" is an acceptable format operand which evaluates the first and third argument operands but not the second.

On page 3089 line 104455 section printf, change:
The EXTENDED DESCRIPTION section almost exactly matches the printf() function in the ISO C standard, although it is described in terms of the file format notation in [xref to XBD Chapter 5].
to:
The format strings for the printf utility are handled differently than for the printf() function in several respects. Notable differences include:

  • Reuse of the format until all arguments have been consumed.

  • No provision for obtaining field width and precision from argument values.

  • No requirement to support floating-point conversion specifiers.

  • An additional b conversion specifier.

  • Special handling of leading single-quote or double-quote for integer conversion specifiers.

  • Hexadecimal character constants are not recognized in the format.

  • Formats that use numbered argument conversion specifications can have gaps in the argument numbers.

Although printf implementations have no difficulty handling formats with mixed numbered and unnumbered conversion specifications (unlike the printf() function where it is undefined behavior), existing implementations differ in behavior. Given the format operand "%2$d %d\n", with some implementations the "%d" evaluates the first argument and with others it evaluates the third. Consequently this standard leaves the behavior unspecified (as opposed to undefined).

On page 3089 line 104471 section printf, change FUTURE DIRECTIONS from:
None.
to:
A future version of this standard may require that a missing argument operand to be consumed by a numbered argument conversion specification is treated as an error.

Notes
(0005890)
kre   
2022-07-16 08:23   
(edited on: 2022-07-16 08:57)
It is probably no big surprise, but I am opposed to this as it
stands currently.

I accept that having %n$ in printf is close to essential for
handling internationalised scripts, but it does not need to be
as described.

I also find it weird, that from the mailing list discussion, the one
issue considered worthy of adoption was the:
   "it would be preferable for printf to treat a missing argument as an error"
issue, which defeats the one and only potential solution to the real problem
with this proposal.

That is, while a script which uses this mechanism controls the arg list
which is presented to printf (so, after the format is removed, $1 is
something known to the invoking script, as are $2 ...) but what it does
not control is the format. That comes from the message translator, who
provides the text of the format string, and interpolates whatever of the
arguments are needed for that particular translation, in the order that
is appropriate for the culture and language being presented.

In the most extreme case, a script might call printf with several args
which it believes would be useful to present to the user, but the
translator simply provides a constant translation of the intent of the
message, which uses none of the args.

That would currently (both with, and without %n$ being added) run foul of the

    If the format operand contains no conversion specifications that
    consume an argument and there are argument operands present,
    the results are unspecified.

restriction. That can be defeated (in an extremely ugly fashion) by
adding a %999$s conversion somewhere in the format - knowing that there
won't be 999 args given, so if we can rely on an undefined arg presenting
an empty string to a %s conversion, that can be used anywhere, with no
effect on the output.

But if that's allowed to be an error, even that won't work.

I believe it is time to remove that "results are unspecified" and change
the "no conversions with args" to result in "print the format string once,
and exit, ignoring unused args" - this change isn't really required for
normal printf, where the situation normally shouldn't occur. But once
we lose control of the format string, all bets are off.

For the same reason, this:

     The format operand shall be reused as often as necessary to satisfy the
     argument operands. If conversion specifications beginning with a "%n$"
     sequence are used, on format reuse the value of n shall refer to the nth
     argument operand following the highest numbered argument operand consumed
     by the previous use of the format operand.

does not work either. Since we have no idea which %n$ values will be used
in a particular translation, we cannot supply args that are correct for
this to work as desired

Consider:
         printf trfanslated-format 10 36.3 string 5 19.4 word

where one translation of the format is

         "text %1$d %3$s # %2$5.2f\n"
another "total %2$%7.1g for %$1d %$3s\n"
and "That will be %2$.2f for %1$ objects\n"

(all in diverse languages of course). Consider what the proposed rule
does with the 3rd format.

Again, the %999$s trick could save things - essentially it causes the format
string to be used exactly once, which for cases where we don't control what
is in the format, is really what we need.

The best solution is simply to not reuse the format string when any %n$
conversions are present. That avoids all kinds of issues. Further,
it is hard to imagine a sane case for the need for that.

Reusing the format is not used all that often, when it is, it tends to be
for simple formats like
      printf " %s" "$@"
where internationalization is not an issue. or for tabular data, like

      printf '%5d\t%-12s\t%c\t%5d\n' ......

again, where there is not really anything in the format to translate
(on the other hand, the args, particularly strings, might want to be
translated, but that's a side issue).

So, I'd suggest changing things so the format is not reused if there has
been any %$n arg used, forbid it to be an error to refer to an arg that
doesn't exist (for at least for one conversion, even if a new made up one,
which converts nothing -- %Z could be guaranteed to print an empty string,
but we could still use %20$Z to make this a format using %n$, and thus
assuming the other change is accepted, not make it undefined to not
reference any args.

Without changes like these, the proposal is simply unworkable - which is
why I have resisted implementing %n$ in NetBSD printf. It would be truly
easy to simply do what the other implementations have done, and do the
easy thing (parsing and implementing it is trivial) but if the result is
as hopeless as all of those are, I am not at all interested.

(0005891)
geoffclare   
2022-07-18 11:17   
Re Note: 0005890

The reason the behaviour is unspecified when there are arguments but no conversions is because some implementations write a warning message about the unused arguments. If it stops being unspecified they will have to change.

A better work-around than %999$s is %1$.0s i.e. consume the argument(s) without them producing any contribution to the output. A similar trick also solves the "repeat the format" situation where a translator only wants to use two of three arguments - they can insert %3$.0s anywhere so that the third argument in each triple is consumed.

You say "it is hard to imagine a sane case for the need for" format reuse with numbered arguments, but in the mailing list discussion someone (Stephane I think) said they often use it for reordering columns and would object to this feature being disallowed.

The restrictions for the printf utility as proposed are already less stringent than the printf() function, where if you consume the Nth argument you must also consume all arguments from 1 to (N-1). Translators seem to have been able to cope with the printf() restrictions for many years, so they should be able to do so equally well for the printf utility. The only "extra" problem if printf is used with translated formats in a similar fashion to printf() is the arguments-but-no-conversions issue and as I said above there is a simple work-around for that (%1$.0s)
(0005892)
bhaible   
2022-07-18 14:14   
The proposed specification looks perfectly OK to me.
It marks a couple of cases as unspecified or error, that
would not be needed in practical uses, and thus avoids
backward-incompatible changes in existing implementations.

There is no handling for a width or precision that comes from an
argument, unlike in C, because POSIX printf(1) already does not
support this. Example:
LC_ALL=C printf '%.*f %s\n' 2 3.1415926 pi
So this is OK as well.

Replying to Robert Elz's comment:

> having %n$ in printf is close to essential for handling
> internationalised scripts

No. There can be different ways to internationize a shell script.
For example, these four statements do all the same thing:

1) pid=$$; eval_gettext "Running as process number \$pid."; echo
2) printf_gettext "Running as process number %d." $$; echo
3) printf "`gettext 'Running as process number %d.'`" $$; echo
4) printf $(gettext 'Running as process number %d.') $$; echo

GNU gettext currently implements only the first one. When POSIX
printf(1) comes with %n$ support, it will be possible for GNU
gettext to support the three others as well. Namely, when
preparing a template PO file from the given script, xgettext
will add a marker '#, sh-printf-format' to the extracted message:

#, sh-printf-format
msgid "Running as process number %d."
msgstr ""

When translators then submit localizations, the '-c' option
of 'msgfmt -c' will ensure that the msgstr must consume the
same arguments, with the same formats. For example,

#, sh-printf-format
msgid "Running as process number %d."
msgstr "Laufe als Prozess Nummer %1$d."

will pass, whereas

#, sh-printf-format
msgid "Running as process number %d."
msgstr "Laufe als Prozess Nummer %1$s."

will be rejected (conversion specifier does not match), and

#, sh-printf-format
msgid "Running as process number %d."
msgstr "Laufe als Prozess Nummer."

will be rejected as well (number of consumed arguments does not match).

This checking of format strings is essential for C, because badly
localized printf(3) format strings would make the program crash.
The same mechanism, applied to printf(1) format strings, will prevent
the script from running into the unspecified/error cases of the
specification.

In other words, for the purpose of internationalization, it does not
really matter what the specification says about these corner cases,
because 'msgfmt -c' will ensure that these corner cases are not
exercised.

The important point is that POSIX defines the syntax with %n$ at all;
this will be the foundation for the format string checking of
'#, sh-printf-format' in msgfmt.

> In the most extreme case, a script might call printf with several args
> which it believes would be useful to present to the user, but the
> translator simply provides a constant translation of the intent of the
> message, which uses none of the args.

'msgfmt -c' will prevent this.

> what it does
> not control is the format. That comes from the message translator

This is intentional. When printing an amount of money, for example,

#, sh-printf-format
msgid "Price: %.2f"
msgstr "Preis: %.3f"

is OK, since the translator knows better than the program whether
amounts of money should better be printed with 2 or with 3 decimals.

> and "That will be %2$.2f for %1$ objects\n"
> Consider what the proposed rule does with the 3rd format.

'msgfmt -c' will reject that translation (number of consumed
arguments does not match).
(0005893)
bhaible   
2022-07-18 14:51   
Replying to Robert Elz:
> the one issue considered worthy of adoption was the:
> "it would be preferable for printf to treat a missing argument as an error"
> issue

Format strings in C also have the same restrictions that:
  (A) Numbered and unnumbered arguments cannot be used in the same format string.
  (B) Missing arguments in a format string with numbered arguments are an error.

Restriction (A) has the purpose to ensure a clear specification, and also to catch some kinds of unintentional programmer/translator mistakes.

Restriction (B) exists in C, because sizeof(argument) can only be deduced from the conversion specifier. In languages where each argument is merely a pointer, such as Awk, Boost, JavaScript, Ruby, Tcl, this restriction is unnecessary. For shell programming, where each argument is a plain string, it is unnecessary as well.




Viewing Issue Advanced Details
1590 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Objection Error 2022-06-20 10:57 2022-08-19 15:09
geoffclare
 
normal  
Applied  
Accepted As Marked  
   
Geoff Clare
The Open Group
pr
3109
103939
Approved
See Note: 0005866.
requirement for pr on an empty file doesn't match implementations
The description of pr does not allow it to behave differently if an input file is empty. I could not find any implementation that behaves in the required manner, i.e. writes a header followed by a sequence of <newline>s (or a <form-feed> if -F or -f is specified).

Solaris and HP-UX report it as an error.

GNU, macOS, and FreeBSD exit with status 0 but write nothing (no header and no <newline>s).
On page 3109 line 103939 section pr, after:
The input files shall be text files.
append:
An empty input file may be treated as an error.

On page 3109 line 103964 section pr, change:
The pr utility output shall be a paginated version of the original file (or files). This pagination shall ...
to:
If an input file is empty and the implementation does not treat this as an error, no output shall be written for that file and this shall be considered to be successful completion of the processing for that file.

For each non-empty input file, the pr utility output shall be a paginated version of the original file. This pagination shall ...

Notes
(0005855)
Don Cragun   
2022-06-20 16:20   
(edited on: 2022-06-23 15:17)
Old Interpretation response
------------------------
The standard states the behavior of pr with an empty file, and conforming implementations must conform to this. However, concerns have been raised about this which are being referred to the sponsor.

Rationale:
-------------
The standard does not match existing practice.

Notes to the Editor (not part of this interpretation):
-------------------------------------------------------
Make the changes in the desired action.

(0005856)
kre   
2022-06-20 16:49   
I agree this should be fixed (though it is a little mind boggling that
anyone would treat an empty file as an error) - but it is going to take
more/different text than suggested to fix it.

In particular, with -m, empty files are never simply ignored (nor, I would
suggest, though I have no idea what odd implementations might do, be treated
as an error) - rather the empty file is treated like any other file, it simply
ends a little sooner than some of the others (its output column tends to be
rather empty).

Other oddments here, STDOUT says

    If the standard input is used instead of a file operand,
    the <file> field shall be replaced by a null string.

Which is fine, but I believe the same is true when standard input
is used because of a file argument ("-") rather than instead of one.

This should probably say:
    When the current file is the standard input, the <file> field
    shall be replaced by a null string.

It doesn't matter (for this) why pr is reading stdin, just that it is.

The description of -p says

    pr shall write an <alert> to standard error and wait for a
    <newline> to be read on /dev/tty.

I believe that's not quite correct, what pr waits for is for a read on
/dev/tty to complete, the normal way this happens is when the user types
a <newline> but EOF works just as well (the EOL char probably would too).

That (from "and wait" onwards) should probably be changed to say
     and wait for a read on /dev/tty to complete (usually accomplished by
     entering a <newline>).

As best I can tell (limited testing) what is actually entered makes no
difference at all (but that should probably be left unspecified, in case
some implementation has decided to incorporate some relation of "more"
in pr -p).

STDOUT says:

    Page headers shall be generated unless the -t option is specified.

Yet the description of the -l option says:

    If lines is not greater than the sum of both the header and trailer
    depths (in lines), the pr utility shall suppress both the header and
    trailer, as if the -t option were in effect.

They cannot both be correct (unless both -t and -l small are given).
Either -l small suppresses the header (in which case what it says in
STDOUT is incorrect - the header is not printed, yet no -t option was
specified) or STDOUT is correct, the header and trailer are printed for
small pages, leaving no space for any file data (if -l is small enough)
so the output is just a continuous stream (forever) of header&trailer.

That needs fixing as well.

The STDOUT section also says nothing at all about the trailer appearing
there.

The description of the "-column" option doesn't actually say anywhere
that the "column" there is an integer, nor bound its value in any way
(what does -0 do ?) What does "should not be used with -m" mean
really, that's not standards language. It also says that -e and -i
are assumed for multi-column output, but those options have (optional)
parameters, nothing there says what values those parameters should have
in this case, nor whether these assumed options override earlier explicit
-e or -i options. Given the positioning, it is also unclear if the
"multicolumn output" it refers to there is only that from the -column
option, or also includes -m output. More non-standards language
appears as "When used with -t, use the minimum number of lines to write
the output." which looks like an instruction to the implementer, not
something that an application script writer could depend upon, nor anything
upon which one could base a conformance decision.

The -r option says not to write diagnostic reports when files cannot be
opened, but when given, if the only event that could be considered an
error is such an open failure, does this count as an error for the purposes
of the exit status, or (with -r) is the failure to open a file ignored
completely (exit(0) if no other errors occurred).

There's no spec of how the spaces that -o requires to be output (assuming
offset is > 0) interact with the -i option. Consider "-o 8 -i+4" -- does
that still result in lines starting with 8 spaces, or with two '+' chars ?

There is probably more, I am out of time... beginning discussions on some
of the ancient text is fun, isn't it!
(0005858)
geoffclare   
2022-06-21 09:30   
Reopening because the desired action is incorrect if the -m option is used.
(0005859)
geoffclare   
2022-06-21 09:34   
Re Note: 0005856, thanks for spotting that the proposed change is wrong for -m. I will work on an updated proposal.

The other points in your note are unrelated to the empty file issue and should be dealt with in one or more separate bugs. (Some of them may need their own formal interpretation response instead of being sneaked in as part of this one.)
(0005860)
kre   
2022-06-21 11:07   
On thinking about it, I think the right way to deal with empty files
(other than to allow them to generate an error, if that is really what
happens, sometimes) isn't to deal with them at all.

Instead, what I believe that (at least many) pr implementations do
is suppress the header and trailer if there would be so substantive
output on a page. In normal mode, an empty file is nothing, hence
no output, no header, no trailer, nothing.

In -m mode, if one of the files is empty, it is treated just like
any other file which has run out of data, and its column is filled
with spaces.

On the other hand, if all of the files given with -m are empty, there's
no output at all (no header, or trailer, or anything).

I'll see if I can dredge up the time to turn the rest of Note: 0005856 into
one or more bug reports - but they're unlikely to have much of a desired action
beyond "fix it" except where the problem is simply bad wording. I don't
have the time at the minute to check implementations and see what they do.

Would you prefer one omnibus "cleanup pr" PR, or one for each issue, or
something in between ?
(0005861)
geoffclare   
2022-06-21 13:46   
(edited on: 2022-06-21 14:00)
Re Note: 0005860 Good point about -m with all empty files. Everyone seems to handle that case the way you describe. Even Solaris and HP-UX with only one empty file - which makes them inconsistent with/without -m and that's probably grounds for a future direction disallowing the error they give without -m.

As to how to group the other problems you raised into one or more new bugs...

The file operand of "-" and the -t/-l "as if" problems will get fixed as a side effect of the change here.

The -p and the -r problem I think should each have their own bug.

The others could probably be lumped together in one bug.

(0005862)
geoffclare   
2022-06-21 14:12   
(edited on: 2022-06-21 14:15)
Updated proposal ...

On page 3109 line 103939 section pr (INPUT FILES), after:
The input files shall be text files.
append:
If the -m option is not specified, an empty input file may, but should not, be treated as an error.

On page 3109 line 103964 section pr (STDOUT), change:
The pr utility output shall be a paginated version of the original file (or files). This pagination shall ...
to:
If the -m option is not specified, the pr utility output shall be as follows:

  • If an input file is empty and the implementation does not treat this as an error, no output shall be written for that file and this shall be considered to be successful completion of the processing for that file.

  • For each non-empty input file, the output shall be a paginated version of the original file.

If the -m option is specified, the pr utility output shall be a paginated version of the merged file contents, as described in OPTIONS.

In both cases, the pagination shall ...

On page 3109 line 103966 section pr (STDOUT), change:
Page headers shall be generated unless the -t option is specified.
to:
Page headers shall be generated unless the -t option is specified, the -l option is specified with too small a value (see OPTIONS), or the -m option is specified and all of the input files are empty.

On page 3109 line 103969 section pr (STDOUT), change:
In the POSIX locale, the <output of date> field, representing the date and time of last modification of the input file (or the current date and time if the input file is standard input), shall be equivalent to the output of the following command as it would appear if executed at the given time:
date "+%b %e %H:%M %Y"
without the trailing <newline>, if the page being written is from standard input. If the page being written is not from standard input, in the POSIX locale, the same format shall be used, but the time used shall be the modification time of the file corresponding to file instead of the current time.
to:
In the POSIX locale, the <output of date> field shall be equivalent to the output of the following command:
date "+%b %e %H:%M %Y"
as it would appear if executed at the current time if the -m option is specified, or at the following time otherwise:

  • The current time on pages being written from standard input.

  • The modification time of the file named by the corresponding file operand on pages not being written from standard input.

On page 3110 line 103979 section pr (STDOUT), change:
If the standard input is used instead of a file operand, the <file> field shall be replaced by a null string.

If the -h option is specified, the <file> field shall be replaced by the header argument.
to:
If the -h option is specified, the <file> field shall be replaced by the header argument. Otherwise:

  • If the -m option is specified, the <file> field shall be replaced by a null string on all pages.

  • If the -m option is not specified, the <file> field shall be replaced by a null string on pages containing output that was read from standard input.

After page 3111 line 104034 section pr (RATIONALE), add a new paragraph:
Some implementations of pr treat an empty file as an error when -m is not specified, but not when -m is specified (even if there is only one input file). Implementations are encouraged to eliminate this inconsistency by never treating an empty file as an error.

On page 3111 line 104036 section pr (FUTURE DIRECTIONS), change:
None.
to:
A future version of this standard may require that an empty file is never treated as an error.


(0005864)
kre   
2022-06-21 15:35   
That looks cleaner, though I still suspect it would be even simpler if
the "no output on a page" test was specified, rather than the division
between -m and not -m, and the special case for -m with all empty files.
It really is just one generic "if there's nothing, write nothing" test
(most likely, by deferring writing headers until there is some output to
go on the page, and not writing the trailer (including all the blank lines
required to position it properly) if no header was written.

But I see no technical problems with what is proposed in Note: 0005862
for the issue it is dealing with.
(0005865)
agadmin   
2022-06-21 15:49   
Note the proposed interpretation status has been withdrawn as the bug was reopened after the meeting
(0005866)
Don Cragun   
2022-06-23 15:11   
(edited on: 2022-06-23 15:16)
Interpretation response
------------------------
The standard states the behavior of pr with an empty file, and conforming implementations must conform to this. However, concerns have been raised about this which are being referred to the sponsor.

Rationale:
-------------
The standard does not match existing practice.

Notes to the Editor (not part of this interpretation):
-------------------------------------------------------
Make the changes in Note: 0005862.

(0005870)
agadmin   
2022-06-24 09:19   
Interpretation proposed: 23 June 2022
(0005913)
agadmin   
2022-07-26 11:15   
Interpretation approved: 26 July 2022
(0005936)
geoffclare   
2022-08-19 15:09   
When applying this bug I noticed that the text "without the trailing <newline>", relating the the output of a date command, had been accidentally dropped from the STDOUT section. I retained it.




Viewing Issue Advanced Details
1589 [1003.1(2016/18)/Issue7+TC2] Base Definitions and Headers Objection Omission 2022-06-20 08:36 2022-06-30 13:57
geoffclare
 
normal  
Applied  
Accepted  
   
Geoff Clare
The Open Group
7.3.1 LC_CTYPE
141
4207
---
blank class definition should disallow some characters
In XBD 7.3.1 for the "space" class the standard disallows some characters. The same should be done for "blank".
Change:
In a locale definition file, the <space> and <tab> are automatically included in this class.
to:
In a locale definition file, no character specified for the keywords upper, lower, alpha, digit, graph, or xdigit shall be specified, and none of the characters <form-feed>, <newline>, <carriage-return>, and <vertical-tab> of the portable character set shall be specified. The <space> and <tab> are automatically included in this class.

There are no notes attached to this issue.




Viewing Issue Advanced Details
1587 [Issue 8 drafts] Shell and Utilities Editorial Enhancement Request 2022-05-22 02:09 2022-07-19 14:18
calestyo
 
normal  
Applied  
Accepted  
   
Christoph Anton Mitterer
2.14 Special Built-In Utilities
2366
76656
exec special built-in should list PATH as environment variable
Currently, the description says:
> ENVIRONMENT VARIABLES
> None.

However, exec depends on PATH when a utility operand is given, as exec's description indirectly mentions by referring to Section 2.9.1.6.
Replace line 76656 with something like:

PATH
Determine the search path when looking for commands given as the utility operand; see XBD Chapter 8 (on page 155).
There are no notes attached to this issue.




Viewing Issue Advanced Details
1586 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Editorial Enhancement Request 2022-05-14 22:07 2022-11-24 10:12
steffen
 
normal  
Applied  
Accepted As Marked  
   
steffen
Vol. 3: Shell and Utilities
(Line or range of lines)
---
Note: 0006080
timeout - new utility: run a command with a time limit
As of today it is very complicated to reliably run a program from within
a sh(1)ell with a timeout, a sh(1)ell can only hardly kill a child after
a timeout without introducing a race, as shown in issue #1585.

All modern operating systems (to my knowledge) therefore ship
a timeout(1) command for some time, which can be used to reliably run
a program with a timeout set.
Add the timeout utility.
Here is the current manual page as present on OpenBSD, taken from
FreeBSD, under 2-clause BSD license:

NAME
     timeout – run a command with a time limit

SYNOPSIS
     timeout [-k time] [-s sig] [--foreground] [--preserve-status] duration
             command [args]

DESCRIPTION
     The timeout utility executes command, with any args, and kills it if it
     is still running after the specified duration. If duration is 0, the
     timeout is disabled.

     The options are as follows:

     -k time
             Send a second signal, SIGKILL, if the command is still running
             time after the first signal was sent.

             SIGTERM.

     --foreground
             Do not propagate the timeout signal to children processes.

     --preserve-status
             Always exit with the same status as command, even if the timeout
             was reached.

DURATION FORMAT
     duration and time may contain a decimal fraction. The value defaults to
     seconds unless a unit suffix is given.

     The supported unit suffixes are:

           s seconds
           m minutes
           h hours
           d days

EXIT STATUS
     If the timeout was not reached or --preserve-status was set, the exit
     status of command is returned.

     If the timeout was reached and --preserve-status was not set, an exit
     status of 124 is returned.

     If command exited after receiving a signal, the exit status returned is
     the signal number plus 128.
Notes
(0005920)
geoffclare   
2022-07-29 11:03   
(edited on: 2022-08-01 15:45)
Suggested changes...

On page 3301 insert a new page for timeout:

NAME
timeout - execute a utility with a time limit

SYNOPSIS
timeout [-fp] [-k time] [-s signal_name] duration
    utility [argument...]

DESCRIPTION
The timeout utility shall execute the utility named by the utility operand, with arguments supplied as the argument operands (if any), in a child process. If the value of the duration operand is non-zero and the child process has not terminated after the specified time period, timeout shall send the signal specified by the -s option, or the SIGTERM signal if -s is not given.

If the -f option is specified, the signal shall be sent only to the child process. Otherwise, it is implementation defined which one of the following methods is used to signal additional processes:

  • The timeout utility ensures it is a process group leader before creating the child process which executes the utility, in which case it shall send the signal to its process group.

  • The timeout utility arranges for any descendents of the child process that are orphaned to have their parent process changed to the timeout utility, in which case the signal shall be sent to the child process and all of its descendents.

If the subsequent wait status of the child process shows that it was stopped by a signal, a SIGCONT signal shall also be sent in the same manner as the first signal; otherwise, a SIGCONT signal may be sent in the same manner.

If the -k option is specified, and the child process created to execute the utility still has not terminated after the time period specified by the time option-argument has elapsed since the first signal was sent, timeout shall send a SIGKILL signal in the same manner as the first signal. If timeout receives a signal and propagates it to the child process (see ASYNCHRONOUS EVENTS below), this shall be treated as the first signal.

OPTIONS
The timeout utility shall conform to [xref to XBD 12.2].

The following options shall be supported:

-f
Only time out the utility itself, not its descendents.
-k time
Send a SIGKILL signal if the child process created to execute the utility has not terminated after the time period specified by time has elapsed since the first signal was sent. The value of time shall be interpreted as specified for the duration operand (see OPERANDS below).
-p
Always preserve (mimic) the wait status of the executed utility, even if the time limit was reached.
-s signal_name
Specify the signal to send when the time limit is reached, using one of the symbolic names defined in the <signal.h> header. Values of signal_name shall be recognized in a case-independent fashion, without the SIG prefix. By default, SIGTERM shall be sent.

OPERANDS
duration
The maximum amount of time to allow the utility to run, specified as a decimal number with an optional decimal fraction and an optional suffix, which can be:

s seconds

m minutes

h hours

d days

If a decimal fraction is present, the application shall ensure that it is separated from the units by a <period>. If no suffix is present, the value shall specify seconds.

If the value is zero, timeout shall not enforce a time limit.
utility
The name of a utility that is to be executed. If the utility operand names any of the special built-in utilities in [xref to 2.14], the results are undefined.
argument
Any string to be supplied as an argument when executing the utility named by the utility operand.

STDIN
Not used.

INPUT FILES
None.

ENVIRONMENT VARIABLES
The following environment variables shall affect the execution of timeout:

LANG
Provide a default value for the internationalization variables that are unset or null. (See [xref to XBD 8.2] for the precedence of internationalization variables used to determine the values of locale categories.)
LC_ALL
If set to a non-empty string value, override the values of all the other internationalization variables.
LC_CTYPE
Determine the locale for the interpretation of sequences of bytes of text data as characters (for example, single-byte as opposed to multi-byte characters in arguments).
LC_MESSAGES
Determine the locale that should be used to affect the format and contents of diagnostic messages written to standard error.
[XSI]NLSPATH
Determine the location of messages objects and message catalogs.[/XSI]
PATH
Determine the search path that is used to locate the utility to be executed. See [xref to XBD 8.3].

ASYNCHRONOUS EVENTS
The default behavior specified in [xref to XCU 1.4] shall apply, except that:

  • The timeout utility shall ignore SIGTTIN and SIGTTOU signals.

  • The timeout utility may alter the disposition of SIGALRM if the inherited disposition was for it to be ignored.

  • If the signal specified with the -s option, or any signal whose default action is to terminate the process, is delivered to the timeout utility, then unless the signal is SIGKILL or SIGSTOP, the timeout utility shall immediately send the same signal to the process or processes to which it would send a signal when the time limit is reached. If the delivered signal is SIGALRM, timeout may behave as if the time limit had been reached instead of sending SIGALRM.

  • If the -f option is not specified, then if timeout sends a signal to its process group, it shall briefly change the disposition of that signal to ignored while it sends the signal, so that it does not receive the signal itself.

With the single exception of the signal specified with the -s option, or SIGTERM if -s is not used, all signal dispositions inherited by the utility specified by the utility operand shall be the same as the disposition that timeout inherited.

STDOUT
Not used.

STDERR
The standard error shall be used only for diagnostic messages.

OUTPUT FILES
None.

EXTENDED DESCRIPTION
None.

EXIT STATUS
If the -p option is not specified and the time limit was reached:

  • If the -k option was not specified or the utility terminated before the time period specified by the time option-argument elapsed since the first signal was sent, the exit status shall be 124.

  • If the -k option was specified and the SIGKILL signal was sent, it is unspecified whether the exit status is 124 or the behavior is as if the -p option was specified.

Otherwise, if the executed utility terminated by exiting, the exit status of timeout shall be that of the utility; if the utility was terminated by a signal, timeout shall terminate itself with the same signal while ensuring that a core image is not created.

If an error occurs, the following exit values shall be returned:

125 An error other than the two described below occurred.

126 The utility specified by utility was found but could not be executed.

127 The utility specified by utility could not be found.

CONSEQUENCES OF ERRORS
Default.

APPLICATION USAGE
Unlike the kill utility, the -s option of timeout is not required to accept the symbolic name 0 to represent signal value zero.

When the value of duration is zero, timeout does not time out the utility, but it does still perform signal propagation (including to descendents of the utility if -f is not specified).

Regardless of locale, the <period> character (the decimal-point character of the POSIX locale) is the decimal-point character recognized in the duration operand and the time option-argument.

The command, env, nice, nohup, time, timeout, and xargs utilities have been specified to use exit code 127 if a utility to be invoked cannot be found so that applications can distinguish ``failure to find a utility'' from ``invoked utility exited with an error indication''. The value 127 was chosen because it is not commonly used for other meanings; most utilities use small values for ``normal error conditions'' and the values above 128 can be confused with termination due to receipt of a signal. The value 126 was chosen in a similar manner to indicate that the utility could be found, but not invoked. Some scripts produce meaningful error messages differentiating the 126 and 127 cases. The distinction between exit codes 126 and 127 is based on KornShell practice that uses 127 when all attempts to exec the utility fail with [ENOENT], and uses 126 when any attempt to exec the utility fails for any other reason. The timeout utility extends these special exit codes to 125 and 124, with the meanings described in EXIT STATUS. A timeout exit status below 124 can only result from passing through the exit status of the executed utility.

EXAMPLES
None.

RATIONALE
Some timeout implementations make themselves a process group leader (when -f is not used) in order to be able to send signals to descendents of the child process. However, using this method means that any descendents which change their process group do not receive the signal. To ensure all descendents receive the signal, some implementations instead make use of a feature whereby descendents that are orphaned have their parent process changed to the timeout utility--that is, timeout becomes their ``reaper''--together with the ability of a reaper to send a signal to all of its descendents.

Some historical timeout implementations exited with status 128+signal_number when the child process was terminated by a signal before the time limit was reached (or when -p was used). This is reasonable when timeout is invoked from a shell which sets $? to 128+signal_number, but not all shells do that. In particular, the Korn Shell sets $? to 256+signal_number and so an exit status of 128+signal_number from timeout would be misleading. In order to avoid any possible ambiguity, this standard requires that timeout mimics the wait status of the child process by terminating itself with the same signal. When it does this it needs to ensure that it does not create a core image, otherwise it could overwrite one created by the invoked utility.

The timeout utility ignores SIGTTIN and SIGTTOU so that if the utility it executes reads from or writes to the controlling terminal and this generates a SIGTTIN or SIGTTOU for the process group, timeout will not be stopped by the signal and can still time out the utility.

Some historical timeout implementations always set the disposition for SIGTTIN and SIGTTOU in the child process to default, even if these signals were inherited as ignored. This could result in processes being stopped unexpectedly. Likewise, they did not ensure that for signals they caught, the disposition inherited by the executed utility was the same as the disposition that was inherited by timeout. This meant that, for example, if timeout was used in a script that was run with nohup, the utility executed by timeout would unexpectedly not be protected from SIGHUP. This standard requires that all signal dispositions inherited by the utility specified by the utility operand are the same as the disposition that timeout inherited, with the single exception of the signal that timeout sends when the time limit is reached, which needs to be inherited as default in order for the timeout to take effect (without resorting to SIGKILL if -k is specified).

Some historical timeout implementations only propagated a subset of the signals whose default action is to terminate the process to the child process if one was delivered to the timeout utility. Propagating these signals is beneficial, as otherwise termination of the timeout utility by a signal results in the utility it executed being left running indefinitely (unless it also received the signal, for example a terminal-generated SIGINT). There is no reason to select a subset of these signals to be propagated, therefore this standard requires them all to be propagated (except SIGKILL, which cannot). In the event that a user wants to prevent the utility being timed out, sending timeout a SIGKILL can be used for this purpose.

FUTURE DIRECTIONS
None.

SEE ALSO
kill

XBD Chapter 8 (on page NNN), Section 12.2 (on page NNN), <signal.h>

CHANGE HISTORY
First released in Issue 8.

On page 2598 line 84368 section command, and
page 2694 line 87948 section env, and
page 3028 line 100764 section nice, and
page 3041 line 101203 section nohup, and
page 3299 line 111054 section time, and
page 3450 line 116526 section xargs, change:
The command, env, nice, nohup, time, and xargs utilities
to:
The command, env, nice, nohup, time, timeout, and xargs utilities


(0005971)
geoffclare   
2022-09-20 10:48   
The timeout utility has been added in the Issue8NewAPIs branch in gitlab based on Note: 0005920
(0006080)
geoffclare   
2022-11-21 16:14   
Make the changes from "Additional APIs for Issue 8, Part 2" (Austin/1273).




Viewing Issue Advanced Details
1583 [Issue 8 drafts] Base Definitions and Headers Editorial Enhancement Request 2022-05-09 01:13 2022-06-17 08:41
calestyo
 
normal  
Applied  
Accepted  
   
Christoph Anton Mitterer
3.335 Special Built-In
76
2335
tidy up definition of the term "Special Built-In"
In the definitions chapter there are:

3.53 Built-In Utility (or Built-In)
3.293 Regular Built-In Utility (or Regular Built-In)
3.335 Special Built-In

and 3.392 Utility defines "Utility" to be "A program, excluding special built-in utilities..."


1) Strictly speaking, if the 3.x chapter names are defined terms, than the term "Special Built-In Utility" would now be somewhat contradictory (though everyone would probably still understand what is meant). The full term itself is not defined as such (but only "Special Built-In") and "Utility" is explicitly defined to be not a special built-in utility.

2) Also, the first three chapter / term names should be aligned.

Therefore:
On page 76, replace line 2335:
      3.335 Special Built-In
with
      3.335 Special Built-In Utility (or Special Built-In)
There are no notes attached to this issue.




Viewing Issue Advanced Details
1582 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Editorial Clarification Requested 2022-04-30 10:23 2022-06-17 08:39
nmeum
 
normal  
Applied  
Accepted As Marked  
   
Sören Tempel
ed
2691
87831
Approved
Note: 0005829
Algorithm for computing addresses for "address chains" is not clearly specified
The table in the rationale section of the ed specification specifies (among others) the following address handling rules:

Address Addr1 Addr2
,, $ $
;; $ $

As far as I can tell, the handling of such address chains is only discussed in the text of the rationale section. In this regard, the sentence starting at line number 87812 mentions the following:

    Any number of addresses can be provided to commands taking addresses; for example, "1,2,3,4,5p" prints lines 4 and 5, because two is the greatest valid number of addresses accepted by the print command.

In accordance with the address omission rules from line number 87377 and 87380 I would therefore have expected the aforementioned address chains to be evaluated as follows:

,, -> (1,$)(1,$) -> 1,$
;; -> (1,.)(1,.) -> 1,.

I surveyed different implementations of ed(1) regarding the handling of the ",," address chain. Each implementation was testing using `printf "a\nfoo\nbar\nbaz\n.\n,,p\nQ\n" | ed`.

Implementation Addr1 Addr2
OpenBSD 7.0 1 $
FreeBSD 13.0 1 $
NetBSD 9.2 $ $
GNU ed 1.8 $ $
MacOS Catalina $ $

My takeaway from this is, that the algorithm for computing addresses for "address chains" is not clearly specified in POSIX and should be clarified in the text to ensure portability across different implementations. I also encountered a bug report for the GNU implementation <https://lists.gnu.org/archive/html/bug-ed/2018-03/msg00003.html> [^] which acknowledges that the current behavior is insufficiently specified.

On a side note: The ed specification does not clearly spell out the meaning of the status column in the address table. Furthermore, the evaluation order for address chains is also not clearly specified. However, since line number 87825 mandates that 7,5, should evaluate to 5,5 it seems that address chains are right-associative, i.e. 7,(5,). In my opinion, this should also be clarified in the text, preferably in a different section.
Add an additional paragraph which clearly spells out the algorithm for evaluating address chains.
Notes
(0005829)
geoffclare   
2022-05-05 16:29   
Interpretation response
------------------------
The standard is unclear on this issue, and no conformance distinction can be made between alternative implementations based on this. This is being referred to the sponsor.

Rationale:
-------------
In order to evaluate the address list ",," two rules need to be applied, and it is unclear how they interact.

Line 87365 states:
If more than the required number of addresses are provided to a command that requires zero addresses, it shall be an error. Otherwise, if more than the required number of addresses are provided to a command, the addresses specified first shall be evaluated and then discarded until the maximum number of valid addresses remain, for the specified command.


If the "omitted addresses" rule is applied first, then "the addresses specified first" are those that result from that rule, leading to ",," being evaluated as "1,$ 1,$", which is invalid syntax for an address list (unless the implementation accepts this as an extension). If it is applied during the address counting performed for the above rule, then the first ',' becomes "1,$" and then the second ',' is evaluated after this, leading to the above rule being applied to "1,$,$". It is clear from the rationale in the standard, that it is intended for the latter to be used, but the normative text does not say so.

Notes to the Editor (not part of this interpretation):
-------------------------------------------------------
After line 87382 add a new paragraph:
If an address is omitted between two separators, the rule shall be applied to the first separator and the resulting second address shall be used as the first address for the second separator. For example, with the address list ",," the first ',' becomes "1,$" and the '$' is treated as the first address for the second ',', resulting in "1,$,$".
(0005830)
agadmin   
2022-05-06 13:21   
Interpretation Proposed: 6 May 2022
(0005846)
agadmin   
2022-06-07 09:27   
Approved: 7 June 2022




Viewing Issue Advanced Details
1580 [Issue 8 drafts] Shell and Utilities Editorial Enhancement Request 2022-04-24 23:49 2022-05-26 10:22
calestyo
 
normal  
Applied  
Accepted  
   
Christoph Anton Mitterer
2.12 Shell Execution Environment
2351
76080
add a hint that env vars with invalid names might be passed on to the environments of programs/utilities
This is from https://www.austingroupbugs.net/view.php?id=1561#c5808 [^] .

It was pointed out in that issue by KRE, that the standard allows but doesn't mandate (see 2.9.1.6 point (1a) AND (2a) in draft 2.1) environment variables that don't have a valid name (in the sense of 3.207 Name) to be exported by a shell to invoked programs/utilities.

2.9.1.6 point (1a) AND (2a) both read:

> It is unspecified whether environment variables that were
> passed to the shell when it was invoked, but were not used
> to initialize shell variables (see Section 2.5.3) because
> they had invalid names, are included in the environment
> passed to execl() and (if execl() fails as described above)
> to the new shell.


It may be reasonable to add this information to the list (following line 76070) of things passed on to such invoked programs/utilities.
For example, after line 76080 add another bullet item that repeats the relevant parts from 2.9.1.6:

* It is unspecified whether environment variables that
  were passed to the INVOKING shell when it was invoked itself,
  but were not used to initialize shell variables (see
  Section 2.5.3) because they had invalid names, are
  included in the INVOKED UTILITY’S environment.

Capital letters merely denote additions of mine.
There are no notes attached to this issue.




Viewing Issue Advanced Details
1579 [Issue 8 drafts] Base Definitions and Headers Editorial Enhancement Request 2022-04-18 00:27 2022-05-26 10:20
calestyo
 
normal  
Applied  
Accepted  
   
Christoph Anton Mitterer
9.3.8 BRE Expression Anchoring
172
6015 to 6027
some minor improvementes to BRE Expression Anchoring
Originally from https://www.austingroupbugs.net/view.php?id=1575#c5787 [^] (where it didn't really belong to):


1) Page 172, line 6015-6022 (i.e. the point "1." in that list) mentions:
"A portable BRE shall escape a leading <circumflex> in a subexpression to match a literal circumflex."

The analogue is is missing from point "2." (same page, lines 6023-6027).


2) As noted by Geoff on the mailing list, the word "circumflex" (same page, line 6022) misses the angle brackets
As per Geoff's proposal on the mailing list...

For (1):
On page 172, line 6027, after:
     match the end-of-string following the last character.
append the following sentence:
     A portable BRE shall escape a trailing <dollar-sign> in a
     subexpression to match a literal <dollar-sign>.


For (2):
On page 172, line 6022, replace:
   circumflex
with
   <circumflex>
There are no notes attached to this issue.




Viewing Issue Advanced Details
1578 [Issue 8 drafts] Base Definitions and Headers Editorial Error 2022-04-17 01:40 2022-05-26 10:17
calestyo
 
normal  
Applied  
Accepted As Marked  
   
Christoph Anton Mitterer
Utilities, sed
3138
106249
See Note: 0005828.
sed y-command: error in description about the number of characters in string1 and string2
Hey.

I noted this originally in https://austingroupbugs.net/view.php?id=1551#c5780 [^] and there in my point (VI) (at the very bottom of that note):

The description of the y-command contains on page 3138, line 106249:
"If the number of characters in string1 and string2 are not equal, or if any of the characters in string1 appear more than once, the results are undefined."

That is strictly speaking wrong, namely in the case when string1 and/or string2 contains '\'-escaped 'n' (for newline) or a '\'-escaped delimiters, and the number of occurrences in both strings don't even out.
Perhaps simply write "If the number of characters (after resolving any escape sequences)..." or so?
Notes
(0005828)
Don Cragun   
2022-05-05 15:11   
On P3138, L106249-106251 (sed Extended Description), change:
If the number of characters in string1 and string2 are not equal, or if any of the characters in string1 appear more than once, the results are undefined.
to:
If (after resolving any escape sequences) the numbers of characters in string1 and string2 are not equal, or if any of the characters in string1 appear more than once, the results are undefined.




Viewing Issue Advanced Details
1577 [Issue 8 drafts] System Interfaces Objection Omission 2022-04-07 16:20 2022-05-26 10:37
shware_systems
 
normal  
Applied  
Accepted As Marked  
   
Mark Ziegast
SHware Systems Dev.
dup3()
742
25487-91
Note: 0005827
dup3 flags usage not entirely specified
The current description for dup3() specifies the expected behavior when no bits are set in the flags argument, by reference to dup2 (either clearing the bits or inheriting both of them without change), and when all bits are set, in that specifying FD_CLOFORK and FD_CLOEXEC are both expected to be set in this case. The description does not specify what is to occur when one bit is set and the other is not specified; does this mean the setting for the unspecified bit is inherited from the fd being referenced or is it to be cleared, ignoring how it was set originally.

As example:
int fd2=open("./tmp", O_RDWR | O_CLOFORK | O_CREAT);
int fd=3;
fd=dup3(fd, fd2, O_CLOEXEC);

Does fd have only FD_CLOEXEC only set, clearing FD_CLOFORK set in the open() call, or are both FD_CLOEXEC and FD_CLOFORK set?

An invoke like
fd=dup3(fd2, fd2, O_CLOEXEC)
would lead from reference to dup2 that both be set.
Make it explicit which is the expected behavior, whether the input descriptors are the same or different, when only one O_* flag is specified.
Notes
(0005786)
kre   
2022-04-07 18:31   
There is no "inheriting both of them without change" - that happens only
in dup2() when filedes1 == filedes2 (ie: that operation is a no-op).

For dup3() it is prohibited for filedes1 to be the same as filedes2, so
that situation cannot occur (though the wording for this could be
improved to make it clearer that it is not only when flags==0 that
that prohibition applies ... other than that would make no sense, we do
not need dup3() to be able to manipulate the flag bits for a fd, we have
fcntl() for that).

dup2() clears the flags, except in the no-op case. dup3() sets the
flags to exactly what is given in the flags arg.

I do agree that this should be clearer in the standard, it currently
just says that the flags arg can be the inclusive or of the 2 bits.
It nowhere says what then happens with that arg. It should specify
that the flags for the new fd (filedes2) are set (as if by open).
(0005827)
geoffclare   
2022-04-28 16:36   
(The following changes make the wording for dup3() and pipe2() consistent with accept4().)

Change:
The dup3() function shall be equivalent to the dup2() function if the flag argument is 0, except that it shall be an error if fildes is equal to fildes2. Additionally, the flag argument can be constructed from a bitwise-inclusive OR of flags from the following list:
to:
The dup3() function shall be equivalent to the dup2() function, except that it shall be an error if fildes is equal to fildes2, and the state of FD_CLOEXEC and FD_CLOFORK on the fildes2 file descriptor shall be determined solely by the flag argument, which can be constructed from a bitwise-inclusive OR of flags from the following list:


On page 1413 line 47116 section pipe(), change:
The pipe2() function shall be equivalent to the pipe() function if the flag argument is 0. Additionally, the flag argument can be constructed from a bitwise-inclusive OR of flags from the following list (provided by <fcntl.h>):
to:
The pipe2() function shall be equivalent to the pipe() function, except that the state of O_NONBLOCK on the new file descriptions and FD_CLOEXEC and FD_CLOFORK on the new file descriptors shall be determined solely by the flag argument, which can be constructed from a bitwise-inclusive OR of flags from the following list (provided by <fcntl.h>):




Viewing Issue Advanced Details
1576 [Issue 8 drafts] System Interfaces Editorial Omission 2022-04-07 15:33 2022-05-26 10:15
Don Cragun
 
normal  
Applied  
Accepted  
   
Don Cragun
pipe()
1413
47100-47102
The description of the pipe() function doesn't state which end of the pipe is placed in fildes[0] and fildes[1].
The first sentence in the DESCRIPTION section of pipe() is:
The pipe( ) function shall create a pipe and place two file descriptors, one each into the
arguments fildes[0] and fildes[1], that refer to the open file descriptions for the read and write
ends of the pipe.

It never says whether the file descriptor for reading is assigned to fildes[0] or fildes[1].
Change the4 above quote to:
The pipe( ) function shall create a pipe and place two file descriptors, one each into the
arguments fildes[0] and fildes[1], that refer to the open file descriptions for the read and write
ends of the pipe, respectively.
There are no notes attached to this issue.




Viewing Issue Advanced Details
1574 [1003.1(2013)/Issue7+TC1] System Interfaces Editorial Error 2022-03-22 23:11 2022-05-23 11:39
alanc
 
normal  
Applied  
Accepted As Marked  
   
Alan Coopersmith
unlinkat
(page or range of pages)
(Line or range of lines)
---
Note: 0005815
EPERM condition does not match unlinkat description
The combined unlink/unlinkat description states that unlinkat shall behave
the same as rmdir if AT_REMOVEDIR is specified, but the errors section lists
EPERM for both functions if a directory is specified.
In the Errors list, under "These functions shall fail and shall not unlink the file if:" remove:

[EPERM]
    The file named by path is a directory, and either the calling process
    does not have appropriate privileges, or the implementation prohibits
    using unlink() on directories.


Add a new section under errors:

The unlink() function shall fail and shall not unlink the file if:

[EPERM]
    The file named by path is a directory, and either the calling process
    does not have appropriate privileges, or the implementation prohibits
    using unlink() on directories.


Add a new entry in the "The unlinkat() function shall fail if:"

[EPERM]
    The file named by path is a directory, the AT_REMOVEDIR flag was not
    set in the flag parameter, and either the calling process
    does not have appropriate privileges, or the implementation prohibits
    using unlink() on directories.


(Also, should that section say "shall fail and shall not unlink the file if"
 like the others here?)
Notes
(0005815)
geoffclare   
2022-04-21 16:28   
Make the changes in the desired action, including the final parenthetical part.




Viewing Issue Advanced Details
1573 [1003.1(2016/18)/Issue7+TC2] System Interfaces Editorial Clarification Requested 2022-03-19 00:18 2022-05-23 11:37
steffen
 
normal  
Applied  
Accepted As Marked  
   
steffen
inet_pton
1139
38475 ff.
---
Note: 0005814
inet_pton: clarify IPv4 "standard IPv4 dotted-decimal form"
POSIX says

  If the af argument of inet_pton( ) is AF_INET,
  the src string shall be in the standard IPv4
  dotted-decimal form:

    ddd.ddd.ddd.ddd

  where "ddd" is a one to three digit decimal number
  between 0 and 255 (see inet_addr( )). The inet_pton( )
  function does not accept other formats (such as the octal
  numbers, hexadecimal numbers, and fewer than four numbers
  that inet_addr( ) accepts).

Whereas it explicitly states "octal" here, text forms exist
which always use "ddd.ddd.ddd.ddd", zero padded: the source
of the strings may be end-users used to such forms.

The standard does allow "Leading zeros in individual fields
can be omitted" for IPv6, resulting in two different grades
of fault tolerance for the different IP address types.
(Not to mention that RFCs exist which update IPv6 notation
to be absolutely non-forgiving regarding compression, leading
zeroes, and even character case! (But it seems not all parts
of IETF actually do follow it, as the older, much more
forgiving initial IPv6 RFC allows all sorts of textual
representation, and i for one had a converter which flag-driven
almost supports them all (personally in favour of uppercase).))

As it stands a tolerant software is better off polishing
user data before calling inet_pton. It would be nice if the
standard would not only require decimal, but allow leading
zeroes in IPv4 address fields.
On line 38479, remove "the octal numbers, ".
On line 38480, insert before the closing parenthesis
"Leading zeroes shall be allowed".
Notes
(0005814)
geoffclare   
2022-04-21 16:20   
On line 38478-38480, change:
The inet_pton() function does not accept other formats (such as the octal numbers, hexadecimal numbers, ...
to:
Leading zeroes shall be allowed. The inet_pton() function does not accept other formats (such as octal numbers, hexadecimal numbers, ...




Viewing Issue Advanced Details
1572 [1003.1(2016/18)/Issue7+TC2] System Interfaces Editorial Error 2022-03-18 15:58 2022-05-23 11:34
geoffclare
 
normal  
Applied  
Accepted  
   
Geoff Clare
The Open Group
wctomb()
2292
72872
---
Incorrect CX shading for wctomb()
The descriptions of the mblen(), mbtowc(), and wctomb() functions all have a paragraph about state-dependent encodings that derives from the introductory text in C99 that precedes those three functions.

However, the paragraph is (incorrectly) shaded CX for wctomb() whereas for the other two it is unshaded.
Remove the CX shading from the paragraph on lines 72872-72878 (leaving just line 72879 with CX shading).
There are no notes attached to this issue.




Viewing Issue Advanced Details
1571 [Issue 8 drafts] Base Definitions and Headers Editorial Enhancement Request 2022-03-17 01:00 2022-05-23 11:33
calestyo
 
normal  
Applied  
Accepted  
   
Christoph Anton Mitterer
8.2 Internationalization Variables
159
5507
minor improvement to the locale precedence order
The description of how a locale category is set (based on LC_ALL, LC_*, LANG, etc.) already describes in line 5497-5498, that "the first condition met below determines the value:".

Accordingly none of the four steps beginning at line 5499 except for the last say that the current step is only for the case the the previous didn't apply.

Likewise, in step 4 (line 5507) it makes no sense but just complicates understanding to describe "If the LANG environment variable is not set or is set to the empty string", which is already clear, given that step 3 didn't apply.
Change line 5507-5508 from:

4. If the LANG environment variable is not set or is set to the empty string, the implementation-defined default locale shall be used.

to:

4. Otherwise, the implementation-defined default locale shall be used.
There are no notes attached to this issue.




Viewing Issue Advanced Details
1570 [1003.1(2016/18)/Issue7+TC2] Front Matter Editorial Enhancement Request 2022-03-15 15:53 2022-05-23 11:32
steffen
 
normal  
Applied  
Accepted  
   
steffen
many
many
many
---
Documentation: faulty (display of) equal-sign(s)
While adding to issue 1533 i found misspelled/-generated
equal signs, for example on page 1266 line 42269, present
in C181.pdf (i first thought it was caused by the
pdftotext(1) convertion); it should be ==,

        42269 if(stat(pathname, &statbuf) = = −1)
        42270 return −1;

I have not verified all in PDF, but searching for "= =" in the
pdftotext(1) conversion gives 28 hits.
There seems to be no issue open on this.
Change occurrences of "= =" to "==".
Thank you.
Notes
(0005752)
geoffclare   
2022-03-15 16:09   
The troff source has =\|= i.e. narrow spacing between the two ='s.
I can see how this might be needed in proportional text, but in example code (and other constant-width text) it would seem to be unnecessary and I agree it should be changed to just ==.
(0005753)
steffen   
2022-03-15 17:28   
For non example code using \(eq\(eq may also be an option.




Viewing Issue Advanced Details
1569 [1003.1(2016/18)/Issue7+TC2] Base Definitions and Headers Objection Error 2022-03-15 15:21 2022-05-23 11:30
geoffclare
 
normal  
Applied  
Accepted  
   
Geoff Clare
The Open Group
<unistd.h>
438, 439
14980, 14983, 14986, 14989, 14992, 14998, 15001
---
pointer is not a C-Language Data Type
The <unistd.h> and c99 pages have several uses of pointer as if it were a C-Language Data Type. For example the description of _POSIX_V7_LP64_OFF64 has:
32-bit int and 64-bit long, pointer, and off_t types

In addition to being a misuse of the typographic convention for data types, this also seems to assume/require that all pointers are the same width in each of the ILP32_OFF32, ILP32_OFFBIG, and LP64_OFF64 compilation environments, and that all pointers are at least 64 bits in LPBIG_OFFBIG. The desired action assumes that this is intentional. If it is not, then we'll need an alternative change that only states width requirements for the pointer to void type.
On page 438 line 14979 section <unistd.h>, and
page 439 line 14991 section <unistd.h>, and
page 441 line 15115 section <unistd.h>, and
page 442 line 15119 section <unistd.h>, and
page 442 line 15123 section <unistd.h>, change:
32-bit int, long, pointer, and off_t types.
to:
32-bit int, long, off_t, and all pointer types.

On page 438 line 14982 section <unistd.h>, and
page 439 line 14994 section <unistd.h>, and
page 442 line 15127 section <unistd.h>, and
page 442 line 15132 section <unistd.h>, and
page 442 line 15137 section <unistd.h>, change:
32-bit int, long, and pointer types and an off_t type using at least 64 bits.
to:
32-bit int, long, and all pointer types and an off_t type using at least 64 bits.

On page 438 line 14985 section <unistd.h>, and
page 439 line 14997 section <unistd.h>, and
page 442 line 15142 section <unistd.h>, and
page 442 line 15147 section <unistd.h>, and
page 442 line 15152 section <unistd.h>, change:
32-bit int and 64-bit long, pointer, and off_t types.
to:
a 32-bit int type and 64-bit long, off_t, and all pointer types.

On page 439 line 14988 section <unistd.h>, and
page 439 line 15000 section <unistd.h>, and
page 442 line 15157 section <unistd.h>, and
page 442 line 15162 section <unistd.h>, and
page 443 line 15167 section <unistd.h>, change:
an int type using at least 32 bits and long, pointer, and off_t types using at least 64 bits.
to:
an int type using at least 32 bits and long, off_t, and all pointer types using at least 64 bits.

On page 2547 line 82425 section c99, change:
pointer
to:
pointer types

On page 2549 line 82539 section c99, change:
32-bit int, long, and pointer types and an off_t type using at least 64 bits
to:
32-bit int, long, and all pointer types and an off_t type using at least 64 bits

There are no notes attached to this issue.




Viewing Issue Advanced Details
1568 [Issue 8 drafts] Shell and Utilities Editorial Error 2022-03-12 19:38 2022-05-23 11:26
cmsmith
 
normal  
Applied  
Accepted  
   
Curtis Smith
1.5 Considerations for Utilities in Support of Files of Arbitrary Size
2307
74286
sum utility listed as standard utility in spite of its intentional exclusion
The historic *sum* utility is noted in the *cksum* rationale and also in the C.3.3 Exclusion of Utilities section with the net effect that *sum* is intentionally not in the standard, yet there are references to it suggesting that it is.
Delete line 74286 on page 2307 which lists "sum : Print checksum and block or byte count of a file" from the list of utilities in support of files of arbitrary sizes.

On page 3614, remove references to the sum utility: in particular,

change "The cat, cksum, cmp, cp, dd, mv, sum, and touch utilities" to "The cat, cksum, cmp, cp, dd, mv, and touch utilities" on line 124855, and

change "The cat, cksum, cmp, dd, df, du, ls, and sum utilities" to "The cat, cksum, cmp, dd, df, du, and ls utilities" on line 124857.
There are no notes attached to this issue.




Viewing Issue Advanced Details
1566 [Issue 8 drafts] Shell and Utilities Comment Enhancement Request 2022-03-09 10:02 2022-05-23 11:41
vapier
 
normal  
Applied  
Accepted As Marked  
   
Mike Frysinger
awk
2447
79677-79678
Note: 0005810
awk length() should support arrays
When working with arrays, getting the number of elements in the array can be helpful. Many awk implementations already support this.

* BWK awk 20020101
    length(arrayname) returns number of elements; thanks to
    arnold robbins for suggestion.

* gawk 3.1.5
15. length(array) now returns the number of elements in the array. This is
    is a non-standard extension that will fail in POSIX mode.

* mawk 1.3.4-20121129
    + support length(array), as done in gawk and BWK awk (Original-Mawk #1).

* BusyBox awk 1.22.0
    awk: fix length(array)

* QSE awk (version unknown)

These are known to not support it:

* awka 0.7.5 (2001)
Update the description of the length function:

If the argument is an array, returns the number of elements, otherwise return the length, in characters, of its argument taken as a string, or of the whole record, $0, if there is no argument.
Notes
(0005735)
shware_systems   
2022-03-09 19:48   
The current definition says treat the array as a string and apparently count all characters in it, probably faster than a program looping over each element and adding up individual lengths. As such this appears an improper overload of the function name, hiding that functionality. It is better, to me, the province of a separate General function, e.g. arrsize(varname), returning 1 if it isn't an array.
(0005736)
vapier   
2022-03-09 21:57   
i'm not aware of any implementation behaving that way, and arguably, would be undesirable surprising behavior. if we look at how this particular function is implemented in other languages (e.g. Python or C++), it's quite normal for the same function name to be context-aware.

considering implementations have already implemented length in the "count-elements-not-bytes", and it's been live for decades in some implementations, i think that's a pretty good signal that (1) the behavior isn't surprising for users and (2) no one wants the functionality you describe.
(0005737)
nick   
2022-03-10 02:23   
Re Note: 0005735 : on page 2446 (draft 2.1) the standard clearly states that if an array name is passed as a parameter that the function uses as a scalar (which is the case with length at present) then the behavior is undefined.

I support the addition of this new (to the standard) usage. Defining something that was previously undefined and matches existing practice is always good!
(0005810)
geoffclare   
2022-04-21 14:35   
The following is the desired action with some editorial wording changes...

Replace the description of the length function with:
length[([arg])]
If arg is an array, return the number of elements in the array; otherwise, return the length, in characters, of arg taken as a string, or of the whole record, $0, if there is no argument.




Viewing Issue Advanced Details
1565 [1003.1(2016/18)/Issue7+TC2] System Interfaces Comment Clarification Requested 2022-03-03 20:35 2022-05-23 11:25
dennisw
 
normal  
Applied  
Accepted  
   
Dennis Wölfing
https://gitlab.com/sortix/sortix/-/issues/792 [^]
accept, getpeername, getsockname, recvfrom, recvmsg
568, 1066, 1095, 1796, 1800
19869, 36257, 37100, 58151, 58259
---
Ambiguous which length addr_len is set to
Multiple socket functions have a socklen_t* address_len parameter that on output is specified to point to the length of the "stored address". However the length of the stored address is ambiguous because these functions are specified to truncate the stored address if the given buffer is too small, leaving it unclear whether the stored length is supposed to be the length before or after truncation.

This wording came from 0000464 where the description states that the length before truncation is intended.
On page 568 line 19869 section accept, change
stored address
to
address of the connecting socket


On page 1066 line 36257 section getpeername, change
stored address
to
peer address


On page 1095 line 37100 section getsockname, change
stored address
to
socket address


On page 1796 line 58151 section recvfrom, change
stored address
to
sending address


On page 1800 line 58259 section recvmsg, change
stored address
to
source address
There are no notes attached to this issue.




Viewing Issue Advanced Details
1564 [Issue 8 drafts] Shell and Utilities Editorial Clarification Requested 2022-02-23 01:54 2022-11-30 16:37
calestyo
 
normal  
Applied  
Accepted As Marked  
   
Christoph Anton Mitterer
2.13 Pattern Matching Notation
2351
76099
Note: 0005796
clariy on what (character/byte) strings pattern matching notation should work
On the mailing list, the question arose (from my side) what the current wording in the standard implies as to whether pattern matching works on byte or character strings.


- In some earlier discussion it was pointed out that shell variables
  should be strings (of bytes, other than NUL)
  => which could one lead to think that pattern
     matching must work on any such strings

- 2.6.2 Parameter Expansion
  doesn't seem to say, what the #, ##, % and %% special forms of
  expansion work on: bytes or characters, it just
  refers to the pattern matching chapter


- 2.13. Pattern Matching Notation says:
  "The pattern matching notation described in this section is used to
  specify patterns for matching strings in the shell."
  => strings... would mean bytes (as per 3.375 String)

- 2.13.1 Patterns Matching a Single Character however says:
  "The following patterns matching a single character shall match a
  single character: ordinary characters,..."


I questioned whether one could deduce from that, that patten matching is required to cope with any non-characters in the string it operates upon.

This was however rejected on the list, and Geoff Clare pointed out, that since no behaviour is specified (i.e. how the implementation would need to handle such invalidly encoded character) the use of pattern matching on arbitrary byte strings is undefined behaviour.
Either:
1) - In line 76099, replace "strings" with "character strings" and perhaps mention that the results when this is done on strings that contain any byte sequence that is not a character in the current locale, the results are undefined.

Perhaps also clarify this in fnmatch() (page 879), this doesn't seem to mention locales at all, but when the above assumption is true, and pattern matching operates on characters only, wouldn't it then need to be subject of the current LC_CTYPE?


2) Alternatively, some expert could check whether there are any shell/fnmatch() implementations which do not simply carry on any bytes that do not form characters. Probably there are (yash?). But if there weren't POSIX might even chose to standardise that behaviour, which would probably be better than leaving it unspecified?!
Notes
(0005716)
calestyo   
2022-02-25 04:57   
3) A third aspect, that should perhaps be considered by some more knowledgable person than me:

One main use of pattern matching is matching filenames (2.13.3 Patterns Used for Filename Expansion).
Filenames however are explicitly byte strings


So if pattern matching is indeed intended to only have a specified meaning on character strings (in the current locale), then 2.13.3 should somehow explain this.

Especially how such patterns should deal with filenames that aren't character strings in the current locale (e.g. error, unspecified, ignored?).

For example, would a "ls *" in principle be expected to only match filenames who are character strings in the current locale?
(0005719)
mirabilos   
2022-02-25 20:54   
「would a "ls *" in principle be expected to only match filenames who are character strings in the current locale?」

That’d be the logical consequence of treating it as characters in the current encoding.

When I added locale “things” to my projects, I extended the definition of character. Instead of just accepting the characters that are valid in the current encoding (which is either 8-bit-transparent 7-bit ASCII or (back then BMP-only, but I’m moving to full 21-bit) UTF-8), so-called “raw octets” are also mapped into the wide character range.

Every time a conversion fails, the first octet of it is handled as raw octet, then the conversion restarts on the next one. (This can obviously be optimised for illegal UTF-8 sequences if one is careful about the beginning of the next possibly valid sequence.)

In 16-bit wchar_t times (basically “until 2022Q1”), this is mapped into a PUA range reserved by the CSUR for this. (Not quite optimal.) This is U+EF80‥U+EFFF. (What happens when you encounter \xEE\xBE\x80 can only be described as fun.)

In the new scheme, I’m mapping them to U-10000080‥U-100000FF which is outside of the range of things, so not a problem (except now I’m wondering what to set WCHAR_MAX to, but I think 0x10FFFFU still, because only these are, strictly speaking, valid?)

There’s a complication that has to do with the idiotic Standard C API for mbrtowc(3) in that “return value == 0” is the sole test for “*pwc == L'\0'” and so cannot be used to signal that 0 octets have been eaten, which means I might need to use even higher numbers for 2‑, 3‑ and 4-byte raw octet sequences. (The latter of which has wcwidth() == 4…)

But that’s detail. The thing relevant here is that this is (could be, but anything else is either discarding the notion of character here (which would be hard to make congruent with the existence of character classes) or an active and certainly harmful disservice to users (the “only match filenames that are valid” I quoted above)) a middle ground between characters and bytes: bytes that are characters if possible and have character semantics applied, but may not.

This is currently unspecified. I’d like to (continue) treat(int) things in a way that means that, for example, ? is either a character or a single byte from an invalid multibyte sequence (of length 1 or more), with a subsequent ? catching a possible second byte, and so on. Raw octets are displayed as � with a wcwidth() of 1 each (or some application-local suitable encoding, where that is possible).
(0005729)
calestyo   
2022-03-03 03:37   
Well I guess the whole thing is also, why your point had been earlier, that '.' as sentinel would be enough, and any implementation that wouldn't carry on invalid encodings (i.e. bytes that do not form characters), would be buggy in that respect already.


I guess on the one hand, Geoff is clearly right, when he says that any such behaviour (especially the complicated mappings that you explained above) are not expected to be carried out by an implementation (at least not from the current standard)... and as such '.' would in fact not be enough as the sentinel for command substitution with trailing newlines, but the LC_ALL=C would be required.


OTOH... the '*' example above was intended to question whether there are really any implementations which would filter out filenames which contain bytes that do not form characters. I'd guess not.


So one more reason, why I think that this should be clearly specified (which I've requested with this issue)... i.e. if there's consensus that it (pattern matching) operates on character strings only - clearly name this, declare operation on non-character strings unspecified (with respect to their results) and remove all current references that indicate that it would operate on bytes.
(0005796)
geoffclare   
2022-04-11 13:55   
Suggested changes...

On page 2351 line 76098 section 2.13 Pattern Matching Notation, change:
The pattern matching notation described in this section is used to specify patterns for matching strings in the shell.
to:
The pattern matching notation described in this section is used to specify patterns for matching character strings in the shell.

After page 2351 line 76102 section 2.13 Pattern Matching Notation, add a new paragraph:
If an attempt is made to use pattern matching notation to match a string that contains one or more bytes that do not form part of a valid character, the behavior is unspecified. Since pathnames can contain such bytes, portable applications need to ensure that the current locale is the C or POSIX locale when performing pattern matching (or expansion) on arbitrary pathnames.
(0005797)
kre   
2022-04-11 22:58   
How can a conforming application possibly (sanely) ensure the C locale is
in use when performing pathname expansion using user input that has been
presented in the user's locale (and if that is not to be allowed, how
can the user ever sanely use pathnames containing characters that are not
ASCII, and if that is not to be allowed, what good are locales ?)

I truly wish we could simply stop attempting to make the standard consistent
with regard to the current locale mess, it is all way too broken to be
useful.
(0005798)
geoffclare   
2022-04-12 08:51   
> How can a conforming application possibly (sanely) ensure the C locale is in use when performing pathname expansion using user input that has been presented in the user's locale

1. The vast majority of apps will never need to do that because they know (or can assume) that the pathnames they handle either always use the portable filename character set or use the user's locale. I.e. the pathnames are not abitrary (a word I was careful to include in the proposed changes).

2. In apps that truly do need to do matching or expansion on arbitrary pathnames, a C program can call uselocale() before and after calls to fnmatch(), glob(), and wordexp(). A shell script can set LC_ALL=C before handling pathnames (and unset it or restore it afterwards).
(0005804)
calestyo   
2022-04-15 02:12   
Re: https://www.austingroupbugs.net/view.php?id=1561#c5797 [^]

Well this proposal is not really changing anything, is it? Why do you think it's worse to name that something results in undefined behaviour than not saying anything at all and leave it ambiguous (especially when the wording is already contradictory)?

Also... it doesn't seem as if locales would ever go away. And even if the POSIX/C community (and all other affected groups) would decide tomorrow to abolish locales or at least the choice of character encodings and make all UTF-8... there would be still millions of lines of code which assume different character encodings to exist and which thus somehow need to be defined in a proper manner.
(0005805)
calestyo   
2022-04-15 02:17   
Re: https://www.austingroupbugs.net/view.php?id=1561#c5796 [^]

In principle that clarifies my original point.

(Although I'd probably have preferred if all (relevant) implementations just behave the same already... and this could be made non-undefined.


Do you think something should be done about fnmatch(), page 879?

While it refers to sections 2.13.1 and 2.13.2 (which also fall under your proposed changes in 2.13) it still uses "string" all over and doesn't mention any dependency on the locale's character encoding?




Viewing Issue Advanced Details
1563 [1003.1(2016/18)/Issue7+TC2] Shell and Utilities Editorial Clarification Requested 2022-02-18 15:07 2022-06-21 08:54
andras_farkas
 
normal  
Applied  
Accepted As Marked  
   
Andras Farkas
what
Approved
Note: 0005800
Wording for what seem to imply odd behavior. "all occurrences of @(#)"
On;
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/what.html [^]
There's the text:
> The what utility shall search the given files for all occurrences of the pattern that get (see get) substitutes for the %Z% keyword ( "@(#)" ) and shall write to standard output what follows until the first occurrence of one of the following:

Does this output a line for every occurrence of @(#) even if there are multiple before the occurrence of a character that ends an identification string?

For example: the text "@(#)ABC@(#)DEF@(#)GHI\n" (without the quotes) in a binary file. Will it treat it only as one line to output? "ABC@(#)DEF@(#)GHI" or three lines?
"ABC@(#)DEF@(#)GHI
DEF@(#)GHI
GHI"

I believe the standard itself implies it will only output one line.
My case for why the standard implies it will only output one line:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/get.html [^]
The %A% keyword expands to the same text that %Z%%Y%%M%%I%%Z% expands to. Since %Z% is @(#) notice that it'd be expanded to "@(#)TextHere@(#)". (without the quotes)
If 'what' were to produce multiple lines for such a line, one of those lines would be a useless line with only a tab character on it.

This bug first noticed in note 0005680 on bug 0001538, by kre. Some of this bug is paraphrased from his note.
https://austingroupbugs.net/view.php?id=1538 [^]

I've tested behavior using FreeBSD what, and using the Schily SCCS what available at:
http://sccs.sourceforge.net/ [^]
Schily SCCS what is descended from Solaris's, while the BSD whats are not descended from the original SCCS.
Both have the same behavior: outputting only one line, for the example above.
Both do the same thing: output only one line, for the example above.
If it is found that all (or most) implementations of what only output only one line rather than multiple for strings where multiple @(#) precede a character terminating an identification string, I'd like the following change in text:

Original:
The what utility shall search the given files for all occurrences of the pattern that get (see get) substitutes for the %Z% keyword ( "@(#)" ) and shall write to standard output what follows until the first occurrence of one of the following:
" > newline \ NUL

Desired text:
The what utility shall search the given files for all occurrences of the pattern that get (see get) substitutes for the %Z% keyword ( "@(#)" ). The what utility shall write to standard output what follows until the first occurrence of one of the following:
" > newline \ NUL
The what utility shall then look for the next occurrence of "@(#)" after one of those characters.

My wording can probably be improved.

Please research 'what' behavior across more systems, for me, please. I don't have access to System V systems or certified standards-compliant systems, since they're generally closed-source and cost money. (OpenSolaris being the only exception to this I know of, and only an exception to part of what I stated)
Notes
(0005684)
andras_farkas   
2022-02-18 15:23   
Already spotted one part of my wording which could be improved:
> The what utility shall then look for
s/look/search

(also, oops! I didn't intend to have a near-duplicate last line in my Description)
(0005686)
shware_systems   
2022-02-18 16:02   
(edited on: 2022-02-18 16:17)
AFAICT, the subsequent @(#) entries are all part of the identification string data
as non-special text, terminated by the \n. So it should go on one line. What appears to be missing is making it explicit searches continue after the identification string terminator, when -s not specified. That was added, I see, with different phrasing. If an identification string doesn't have one of the terminators, I'd think it's on the storing application to add one. For the example, using '\n' as default for the purpose, this would change it to:
"@(#)ABC\n@(#)DEF\n@(#)GHI\n"
to get all instances output on separate lines.

An alternative is adding '@' to the list of terminating chars, and explicitly start additional search with the terminating character, not after. That would pick up the 3 entries also.

(0005689)
kre   
2022-02-18 19:40   
Re Note: 0005686

    What appears to be missing is making it explicit searches continue after the
    identification string terminator,

Exactly, if that is the intent (which I would expect it is).

    If an identification string doesn't have one of the terminators,

The only way that can happen is for there to be no terminating character
between the @(#) and EOF - which is probably a case that merits explicit
mention - EOF should also be one of the terminating conditions for the
identification string.

The issue if one wanted to get 3 separate outputs is simple, and doesn't
need discussing (when I tested it, I used " instead of \n as the separator,
but any of the listed set would do)/ But note, that would be
different than what might, improbably but possibly, be intended now, as
with none of @ ( # or ) being terminating characters, the alternate
implementation is that the first line would be long, containing (in the
example) all 3 "perhaps" id strings, and two @(#) sequences included,
the 2nd line would be a trailing substring of that, and the third a
trailing substring of that one. This is unlikely to be useful...

Making @ an additional terminator would be an invention, and not something
that we should be doing here (unless there is evidence of implementations
already doing that - and I very much doubt there are any).
(0005697)
geoffclare   
2022-02-21 12:09   
> Please research 'what' behavior across more systems, for me, please.

Solaris, macOS, and HP-UX all do this:
$ cat what3
@(#)ABC@(#)DEF@(#)GHI
@(#)ABC"@(#)DEF@(#)GHI
$ what what3
what3:  
        ABC@(#)DEF@(#)GHI
        ABC
        DEF@(#)GHI
(0005698)
andras_farkas   
2022-02-21 18:18   
Looks like they all perform as expected, and the standards text for the 'what' utility could be changed to make expected behavior more clear.
(0005800)
geoffclare   
2022-04-14 16:34   
(edited on: 2022-04-14 16:35)
Interpretation response
------------------------
The standard states the identification strings written by what, and conforming implementations must conform to this. However, concerns have been raised about this which are being referred to the sponsor.

Rationale:
-------------
The description in the standard does not match existing practice when the number of identification strings in a file is not one. Additionally, an end-of-file condition was not listed as a delimiter.

Notes to the Editor (not part of this interpretation):
-------------------------------------------------------

On page 3437 line 116031 section what, change:
The what utility shall search the given files for all occurrences of the pattern that get (see [xref to get]) substitutes for the %Z% keyword ( "@(#)" ) and shall write to standard output what follows until the first occurrence of one of the following:
" > newline \ NUL
to:
The what utility shall search the given files for all occurrences of the pattern that get (see [xref to get]) substitutes for the %Z% keyword ( "@(#)" ). The what utility shall write to standard output what follows until the first occurrence of one of the following: <double-quote> ('"') , <greater-than-sign> (' >') , <newline> , <backslash> (' \\') , <NUL> ('\0'), or an end-of-file condition on the input file. If not at end-of-file, the what utility shall then look for the next occurrence of "@(#)" after one of those characters.

On page 3437 line 116063 section what, change:
The standard output shall consist of the following for each file operand:
"%s:\n\t%s\n", <pathname>, <identification string>
to:
For each file operand, the standard output shall consist of:
"%s:\n", <pathname>
followed by zero or more of:
"\t%s\n", <identification string>
one for each identification string located.


(0005801)
andras_farkas   
2022-04-14 19:39   
Looks good to me.
(0005811)
agadmin   
2022-04-21 15:06   
Interpretation proposed: 21 April 2022
(0005842)
agadmin   
2022-05-23 11:26   
Interpretation approved: 23 May 2022




Viewing Issue Advanced Details
1562 [Issue 8 drafts] Shell and Utilities Editorial Clarification Requested 2022-02-13 00:28 2022-05-26 10:13
calestyo
 
normal  
Applied  
Accepted As Marked  
   
Christoph Anton Mitterer
Utilities, printf
3084
104239
Note: 0005818
printf utility: clarify what is (byte) string an what is character string
3.375 String, defines:
"A contiguous sequence of bytes terminated by and including the first null byte."
i.e. a byte string, not - by itself - subject to the locale.


The description of the printf utility, uses the phrase "string" in some cases without clearly telling whether character or byte string is meant.


Line 104239, OPERANDS:
> format
> A string describing the format to use to write the remaining operands. See the
> EXTENDED DESCRIPTION section.

=> At least when following line 104273...
"The format operand shall be used as the format string described in XBD Chapter 5 (on page 101)", where it clearly says:
"The format is a character string that contains three types of objects defined below"

... format should be a character string, and as such, it would be subject to LC_CTYPE?!

=> OTOH, the APPLICATION USAGE tells that it's modelled after the printf() function, which in turn uses a C-string as format string,... and if that would also apply to the printf utility, it would be a (byte) string and XBD Chapter 5's provisions would fully apply (which should then be explicitly mentioned).


(See below, for an analogue example for why I think the difference matters.)


> argument
> The strings to be written to standard output, under the control of format.
> See the EXTENDED DESCRIPTION section.

Seems clearly a (byte) string, whose interpretation (byte, character) depends on the respective conversion specifier.



It may further make sense, to explicitly clarify in line 104288, that string here is a "byte string", especially because in 104290 and following, it's laid out how characters are part of it.
Consider e.g. some weird multibyte locale in which a character named A' is composed of bytes that include the binary representation of e.g. '\' (assuming some ASCII encodings for '\' and 'n')... I take as example for A' = 0xAA 0x5C
A string: A'n ... that is 0xAA 0x5C 0x6E should probably be interpreted as: 0xAA \n and thus giving 0xAA 0x0A ... and not the character A' followed by n.


Given that the whole section uses quite often the term "format string" (in the sense of character string)... it may make things more clear, to emphasise that this is a byte string.

The same probably at line 104321.
See above.

Clarify more explicitly, what is byte string, and what is character string, or whether that's unspecified.
Notes
(0005673)
Don Cragun   
2022-02-13 01:08   
Character String and String are both defined terms in D2.1:
3.62
Character String
A contiguous sequence of characters terminated by and including the first null byte.

3.344
String
A contiguous sequence of bytes terminated by and including the first null byte.
(0005792)
geoffclare   
2022-04-08