The following issue has been SUBMITTED. ====================================================================== http://austingroupbugs.net/view.php?id=1157 ====================================================================== Reported By: geoffclare Assigned To: ====================================================================== Project: 1003.1(2016)/Issue7+TC2 Issue ID: 1157 Category: Shell and Utilities Type: Clarification Requested Severity: Objection Priority: normal Status: New Name: Geoff Clare Organization: The Open Group User Reference: Section: 2.14 exec Page Number: 2397-2398 Line Number: 76683-76745 Interp Status: --- Final Accepted Text: ====================================================================== Date Submitted: 2017-07-26 15:40 UTC Last Modified: 2017-07-26 15:40 UTC ====================================================================== Summary: major overhaul of exec special built-in Description: Discussion on the mailing list identified some problems with the description of the exec special built-in utility; it is in need of a major overhaul.
The discussion was triggered by a question about whether exec can execute functions. Although it is known that the original intent was that exec can only execute non-built-in utilities (because the POSIX description was based on ksh88), and it is clear from the EXIT STATUS section that the standard requires this (because it refers to a program which overlays the shell process), and all of the widely used shells conform to this, there are some lesser used shells (notably mksh and zsh) which allow execution of functions and built-in utilities via exec, and there appear to be pros and cons for both approaches. Therefore, the proposed changes have two options: one which clarifies the current requirement and one which allows both behaviours. Desired Action: On page 2367 line 75579-75599 section 2.9.1 replace item b with:<blockquote>Otherwise, the shell shall execute a non-built-in utility as described in [xref to 2.9.1.2].</blockquote> On page 2367 line 75608-75621 section 2.9.1 replace item 2 with:<blockquote>If the command name contains at least one <slash>, the shell shall execute a non-built-in utility as described in [xref to 2.9.1.2].</blockquote> On page 2368 line 75627 section 2.9.1 add a new section:<blockquote>2.9.1.2 Non-built-in Utility Execution When the shell executes a non-built-in utility, if the execution is not being made via the <i>exec</i> special built-in utility, the shell shall execute the utility in a separate utility environment (see [xref to 2.12]). If the execution is being made via the <i>exec</i> special built-in utility, the shell shall not create a separate utility environment for this execution; the new process image shall replace the current shell execution environment. If the current shell environment is a subshell environment, the new process image shall replace the subshell environment and the shell shall continue in the environment from which that subshell environment was invoked. In either case, execution of the utility in the specified environment shall be performed as follows: 1.<blockquote>If the command name does not contain any <slash> characters, the command name shall be searched for using the PATH environment variable as described in [xref to XBD Chapter 8]: a.<blockquote>If the search is successful, the shell shall execute the utility with actions equivalent to calling the <i>execl</i>() function as defined in the System Interfaces volume of POSIX.1-2008 with the <i>path</i> argument set to the pathname resulting from the search, <i>arg0</i> set to the command name, and the remaining <i>execl</i>() arguments set to the command arguments (if any) and the null terminator. If the <i>execl</i>() function fails due to an error equivalent to the [ENOEXEC] error defined in the System Interfaces volume of POSIX.1-2008, the shell shall execute a command equivalent to having a shell invoked with the pathname resulting from the search as its first operand, with any remaining arguments passed to the new shell, except that the value of "$0" in the new shell may be set to the command name. If the executable file is not a text file, the shell may bypass this command execution. In this case, it shall write an error message, and the <i>exec</i> command shall fail with an exit status of 126. 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 [xref to 2.5.3]) because they had invalid names, are included in the environment passed to <i>execl</i>() and (if <i>execl</i>() fails as described above) to the new shell.</blockquote> b.<blockquote>If the search is unsuccessful, the command shall fail with an exit status of 127 and the shell shall write an error message.</blockquote></blockquote> 2.<blockquote>If the command name contains at least one <slash>: a.<blockquote>If the named utility exists, the shell shall execute the utility with actions equivalent to calling the <i>execl</i>() function as defined in the System Interfaces volume of POSIX.1-2008 with the <i>path</i> and <i>arg0</i> arguments set to the command name, and the remaining <i>execl</i>() arguments set to the command arguments (if any) and the null terminator. If the <i>execl</i>() function fails due to an error equivalent to the [ENOEXEC] error, the shell shall execute a command equivalent to having a shell invoked with the command name as its first operand, with any remaining arguments passed to the new shell. If the executable file is not a text file, the shell may bypass this command execution. In this case, it shall write an error message, and the <i>exec</i> command shall fail with an exit status of 126. 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 [xref to 2.5.3]) because they had invalid names, are included in the environment passed to <i>execl</i>() and (if <i>execl</i>() fails as described above) to the new shell.</blockquote> b.<blockquote>If the named utility does not exist, the command shall fail with an exit status of 127 and the shell shall write an error message.</blockquote></blockquote></blockquote> On page 2397 line 76683 section 2.14 exec, change NAME from:<blockquote>exec - execute commands and open, close, or copy file descriptors</blockquote>to:<blockquote>exec - perform redirections in the current shell or execute a utility</blockquote> On page 2397 line 76685 section 2.14 exec, change SYNOPSIS from:<blockquote>exec [command [argument...]]</blockquote>to:<blockquote>exec [utility [argument...]]</blockquote> On page 2397 line 76687-76689 section 2.14 exec, change:<blockquote>The <i>exec</i> utility shall open, close, and/or copy file descriptors as specified by any redirections as part of the command. If <i>exec</i> is specified without <i>command</i> or <i>arguments</i>, and any file descriptors with numbers greater than 2 are opened with associated redirection statements, ...</blockquote>to:<blockquote>If <i>exec</i> is specified with no operands, any redirections associated with the <i>exec</i> command shall be made in the current shell execution environment. If any file descriptors with numbers greater than 2 are opened by those redirections, ...</blockquote> On page 2397 line 76693 section 2.14 exec, append to the paragraph:<blockquote>If the result of the redirections would be that file descriptor 0, 1, or 2 is closed, implementations may open the file descriptor to an unspecified file.</blockquote> On page 2397 line 76694-76696 section 2.14 exec, change:<blockquote>If <i>exec</i> is specified with <i>command</i>, it shall replace the shell with <i>command</i> without creating a new process. If <i>arguments</i> are specified, they shall be arguments to <i>command</i>. Redirection affects the current shell execution environment.</blockquote> to one of the following options: OPTION 1<blockquote>If <i>exec</i> is specified with a <i>utility</i> operand, the shell shall execute a non-built-in utility as described in [xref to 2.9.1.2] with <i>utility</i> as the command name and the <i>argument</i> operands (if any) as the command arguments. If the <i>exec</i> command fails, a non-interactive shell shall exit from the current shell execution environment; [UP]an interactive shell may exit from a subshell environment but shall not exit if the current shell environment is not a subshell environment[/UP]. [UP]If the <i>exec</i> command fails and the shell does not exit, any redirections associated with the <i>exec</i> command that were successfully made shall take effect in the current shell execution environment. [/UP]</blockquote> OPTION 2<blockquote>If <i>exec</i> is specified with a <i>utility</i> operand: 1.<blockquote>If the <i>utility</i> does not contain any <slash> characters and either the named utility is implemented as a shell built-in or a function of the same name exists, it is unspecified whether or not the shell executes the built-in utility or function. If it does, the execution shall be performed as described in [xref to 2.9.1.1] and the shell shall then exit from the current shell execution environment as if by executing the <i>exit</i> special built-in utility with no arguments. If the shell does not execute the built-in utility or function, it shall execute a non-built-in utility as described below.</blockquote> 2.<blockquote>The shell shall execute a non-built-in utility as described in [xref to 2.9.1.2] with <i>utility</i> as the command name and the <i>argument</i> operands (if any) as the command arguments. If the <i>exec</i> command fails, a non-interactive shell shall exit from the current shell execution environment; [UP]an interactive shell may exit from a subshell environment but shall not exit if the current shell environment is not a subshell environment[/UP]. [UP]If the <i>exec</i> command fails and the shell does not exit, any redirections associated with the <i>exec</i> command that were successfully made shall take effect in the current shell execution environment. [/UP]</blockquote></blockquote> On page 2397 line 76718-76722 section 2.14 exec, change EXIT STATUS from:<blockquote>If <i>command</i> is specified, <i>exec</i> shall not return to the shell; rather, the exit status of the process shall be the exit status of the program implementing <i>command</i>, which overlaid the shell. If <i>command</i> is not found, the exit status shall be 127. If <i>command</i> is found, but it is not an executable utility, the exit status shall be 126. If a redirection error occurs (see [xref to 2.8.1]), the shell shall exit with a value in the range 1-125. Otherwise, <i>exec</i> shall return a zero exit status.</blockquote>to:<blockquote>If <i>utility</i> is specified and is executed, <i>exec</i> shall not return to the shell; rather, the exit status of the current shell execution environment shall be the exit status of <i>utility</i>. If <i>utility</i> is specified and an attempt to execute it as a non-built-in utility fails, the exit status shall be as described in [xref to 2.9.1.2]. If a redirection error occurs (see [xref to 2.8.1]), the exit status shall be a value in the range 1-125. Otherwise, <i>exec</i> shall return a zero exit status.</blockquote> If OPTION 1 is chosen above, then also make the following two changes. On page 2398 line 76737 section 2.14 exec, add to EXAMPLES:<blockquote>An application that is not concerned with strict conformance can make use of optional %g support known to be present in the implementation's <i>printf</i> utility by ensuring that any shell built-in version is not executed instead, and using a subshell so that the shell continues afterwards: <tt>(exec printf '%g\n' "$float_value")</tt></blockquote> On page 2694 line 87961 section env, change:<blockquote>Therefore, shell functions, special built-ins, and built-ins that are only provided by the shell are not found.</blockquote>to:<blockquote>Therefore, shell functions, special built-ins, and built-ins that are only provided by the shell are not found by this type of <i>env</i> implementation. However, <i>env</i> can be implemented as a shell built-in, in which case it may be able to execute shell functions and built-ins. An application wishing to ensure execution of a non-built-in utility can use <i>exec</i> in a subshell for this purpose.</blockquote> If OPTION 2 is chosen above, then also make the following three changes. On page 2398 line 76726 section 2.14 exec, change APPLICATION USAGE from:<blockquote>None.</blockquote>to:<blockquote>Since it is unspecified whether <i>exec</i> executes built-in utilities and functions, portable applications cannot rely on the use of <i>exec</i> in a subshell to bypass these and ensure the execution of a non-built-in utility. The only portable ways to ensure execution of a non-built-in utility are: 1.<blockquote>Include at least one <slash> in the command name.</blockquote> 2.<blockquote>Execute it via the <i>env</i> utility, while ensuring that a non-built-in version of <i>env</i> is used.</blockquote>For example, the following function employs method 1 to execute a non-built-in version of any utility:<pre> exec_non_built_in() ( safe_exec() { case "$1" in (-*) exec ./"$@" ;; (*) exec "$@" ;; esac exit # can only be reached if shell is interactive } case "$1" in (*/*) safe_exec "$@" ;; (*) case "$PATH" in (*[!:]:) dirs="${PATH}:" ;; (*) dirs="$PATH" ;; esac IFS=":" set -f for dir in $dirs do case "$dir" in ("") dir="." ;; (*/) dir="${dir%/}" ;; esac if test -x "$dir/$1" && test -f "$dir/$1" then unset IFS safe_exec "$dir"/"$@" fi done printf >&2 "%s not found\n" "$1" exit 127 ;; esac ) </pre>Method 2 reduces to method 1 applied to the <i>env</i> utility, but the search for the non-built-in implementation of <i>env</i> can be done at the time the application is configured and installed. This reduces complexity in the application itself, but at the expense of an extra <i>exec</i>() call when it uses <i>env</i> to execute a utility.</blockquote> On page 2398 line 76745 section 2.14 exec, add <i>env</i> to SEE ALSO. On page 2694 line 87961 section env, change:<blockquote>Therefore, shell functions, special built-ins, and built-ins that are only provided by the shell are not found.</blockquote>to:<blockquote>Therefore, shell functions, special built-ins, and built-ins that are only provided by the shell are not found by this type of <i>env</i> implementation. However, <i>env</i> can be implemented as a shell built-in, in which case it may be able to execute shell functions and built-ins. For methods of ensuring execution of a non-built-in utility, see the APPLICATION USAGE section of [xref to exec].</blockquote> ====================================================================== Issue History Date Modified Username Field Change ====================================================================== 2017-07-26 15:40 geoffclare New Issue 2017-07-26 15:40 geoffclare Name => Geoff Clare 2017-07-26 15:40 geoffclare Organization => The Open Group 2017-07-26 15:40 geoffclare Section => 2.14 exec 2017-07-26 15:40 geoffclare Page Number => 2397-2398 2017-07-26 15:40 geoffclare Line Number => 76683-76745 2017-07-26 15:40 geoffclare Interp Status => --- ======================================================================