DASH Shell discussions
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: Jonathan Nieder <jrnieder@gmail.com>
Cc: Herbert Xu <herbert@gondor.hengli.com.au>,
	Gerrit Pape <pape@smarden.org>,
	dash@vger.kernel.org, "Krzysztof A. Sobiecki" <sobkas@gmail.com>,
	Jari Aalto <jari.aalto@cante.net>
Subject: Re: [PATCH] [INPUT] Catch attempts to run a directory as a script
Date: Wed, 06 Oct 2010 06:18:05 -0600	[thread overview]
Message-ID: <4CAC68FD.4040602@redhat.com> (raw)
In-Reply-To: <20101006105531.GB475@burratino>

On 10/06/2010 04:55 AM, Jonathan Nieder wrote:
>>> But POSIX makes it clear enough that in "sh command_file",
>>> command_file is supposed to be a file, not a directory.  So
>>> diagnose this with an error message and exit with status 2.
> [...]
>> Is this required by POSIX? If not this is simply making dash
>> bigger for no good reason.
>
> Not clear.  I suppose POSIX usually doesn't require anything when the
> caller screws up.

POSIX requires that input files to bash shall be text files; directories 
do not qualify for this.
http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html
"The input file shall be a text file, except that line lengths shall be 
unlimited. "

However, that is a requirement on the user, not the shell; so running 
'sh /' is a constraint violation by the user, and leaves behavior up to 
the shell.

> Under OPERANDS[2]: if the path contains a slash, all the standard says
> is "the implementation attempts to read that file".  If the path does
> not contain a slash and the file is not in the working directory, the
> implementation _may_ perform a search as described in "Command Search
> and Execution".

It's more than just MAY; it's a requirement:
http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01_01

"If the command name contains at least one <slash>, the shell shall 
execute the utility in a separate utility environment with actions 
equivalent to calling the execve() function...

"If the execve() 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"

>
> During that search, after execve() fails, "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 shall return an exit
> status of 126." (emphasis mine).

But yes, that same section is clear that for both command searches along 
PATH for a word without slash, and for a direct command with a slash, if 
execve() fails with ENOEXEC (as it does for directories), then it is 
optional whether the shell bypasses attempts to read the file because it 
was not a text file.

On the other hand, in Linux, execve(".",...) fails with EACCES, as 
permitted by the standard:

http://www.opengroup.org/onlinepubs/9699919799/functions/execve.html
"[EACCES] ...or the new process image file is not a regular file and the 
implementation does not support execution of files of its type."

And since EACCES is not the same class as ENOEXEC, there is no 
requirement for the shell to attempt to execute the same file.  So, 
rather than stat()ing the argument in advance and checking for S_ISDIR, 
it seems like it would be simpler to check after the execve() attempt 
for EACCES and blindly set $? to 126 in that case (since you already 
have to check for ENOEXEC).

> So this behavior is allowed as an optional subset of an optional
> behavior.  That may have guided the bash implementors:
>
>   $ bash directory
>   directory: directory: is a directory
>   $ echo $?
>   126
>
> It's probably not required.

Additionally, the standard REQUIRES that 'sh -c "exec /"' shall fail 
with status 126:

http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#exec
"If command is found, but it is not an executable utility, the exit 
status shall be 126."

Right now, dash gets this wrong:

dash -c 'exec .'; echo $?
exec: 1: /: Permission denied
2

And since you already have the code in dash to detect failure to 'exec' 
a directory, you should be able to reuse that code when detecting 
failure to run a directory as a script, as in 'dash .'.

[Hmm, bash also gets it wrong:
bash -c 'exec .'; echo $?
bash: line 0: exec: .: not found
127
even though . should always be found]

-- 
Eric Blake   eblake@redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

  reply	other threads:[~2010-10-06 12:18 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-05 16:06 debian patches to exit with code 127 for nonexistent/directory scripts Jilles Tjoelker
2010-06-08 10:19 ` Herbert Xu
2010-06-08 10:36   ` Cristian Ionescu-Idbohrn
2010-06-11  8:39     ` Herbert Xu
2010-06-14  9:54 ` [PATCH] [INPUT] exit 127 if command_file is given but doesn't exist Gerrit Pape
2010-06-28  6:53   ` Herbert Xu
2010-10-06 10:04     ` [PATCH] [OPTIONS] Use exit status 127 when the script to run does not exist Jonathan Nieder
2010-10-06 10:08       ` [PATCH] [INPUT] Catch attempts to run a directory as a script Jonathan Nieder
2010-10-06 10:29         ` Herbert Xu
2010-10-06 10:55           ` Jonathan Nieder
2010-10-06 12:18             ` Eric Blake [this message]
2010-10-06 12:31               ` Herbert Xu
2010-10-07  1:02               ` [PATCH 0/3] Fix exit status for 'exec nonexistent' and 'exec .' Jonathan Nieder
2010-10-07  1:03                 ` [PATCH 1/3] [EXCEPTIONS] Stop documenting EXSHELLPROC Jonathan Nieder
2010-10-07  3:01                   ` Herbert Xu
2010-10-07  3:04                     ` Jonathan Nieder
2010-10-07  3:29                       ` Herbert Xu
2010-10-07  3:39                         ` [PATCH v2] " Jonathan Nieder
2010-11-28 12:47                           ` Herbert Xu
2010-10-07  1:04                 ` [PATCH 2/3] Revert "Eliminated global exerrno." Jonathan Nieder
2010-10-07  2:56                   ` Herbert Xu
2010-10-07  3:35                     ` Jonathan Nieder
2010-10-07  4:14                       ` Herbert Xu
2010-10-07  4:37                         ` Herbert Xu
2010-10-07 21:34                           ` Jonathan Nieder
2010-11-28 12:45                       ` Herbert Xu
2010-10-07  1:08                 ` [PATCH 3/3] [EXCEPTIONS] Eliminate global exerrno Jonathan Nieder
2010-10-07  3:00                   ` Herbert Xu
2010-11-28 12:06       ` [PATCH] [OPTIONS] Use exit status 127 when the script to run does not exist Herbert Xu
2010-11-28 12:24         ` Herbert Xu
2010-11-28 12:33           ` Herbert Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4CAC68FD.4040602@redhat.com \
    --to=eblake@redhat.com \
    --cc=dash@vger.kernel.org \
    --cc=herbert@gondor.hengli.com.au \
    --cc=jari.aalto@cante.net \
    --cc=jrnieder@gmail.com \
    --cc=pape@smarden.org \
    --cc=sobkas@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox