Message ID | 20181124162021.10486-1-ao2@ao2.it (mailing list archive) |
---|---|
State | Rejected |
Delegated to: | Herbert Xu |
Headers | show |
Series | main: don't raise exception when executing dotcmd() on a non-existent file | expand |
On Sat, Nov 24, 2018 at 05:20:21PM +0100, Antonio Ospite wrote: > When sourcing a file with the dotcmd() builtin, dash raises an exception > when the input file cannot be opened. > For instance the following script fails prematurely and does not output > the message: > #!/bin/sh > . /non-existent-file > echo "Survived!" > In this case, the behavior of dash is different from other shells (e.g. > bash, zsh) which are more forgiving and allow execution to carry on even > if the input file cannot be opened. POSIX is unambiguous (XCU 2.14 Special Built-In Utilities -> dot) that a non-interactive shell shall abort when a dot script is not found, and bash and zsh comply to this when standards compliance is requested (e.g. by naming the shell "sh" in argv[0] or using "set -o posix" in bash or "set -o posixbuiltins" in zsh). Most other shells (e.g. mksh, FreeBSD sh, yash) comply to POSIX unconditionally here, like dash currently does. > Fix this by passing the INPUT_NOFILE_OK flag when calling setinputfile() > in dotcmd(). > As a bonus, this also fixes cases like the following: > set -e > . /non-existent-file || true > echo "Survived! Let's do something else..." > This idiom is sometimes used in shell script to source a config file > with default values only to provide fallback values if the default > values were not available. The above code is specific to bash and zsh non-POSIX modes, and will not work in a #!/bin/sh script unless specific steps are taken (such as "set +o posix" or starting the script with "bash script1" rather than "./script1"). The simple solution is [ ! -f /non-existent-file ] || . /non-existent-file Time-of-check-time-of-use issues should not be an issue for config files. Alternatively, one could try command . ./non-existent-file || true but this may ignore more errors than desired (such as syntax errors in the sourced file) and does not work correctly in yash 2.30.
On Sat, 24 Nov 2018 18:56:48 +0100 Jilles Tjoelker <jilles@stack.nl> wrote: > On Sat, Nov 24, 2018 at 05:20:21PM +0100, Antonio Ospite wrote: > > When sourcing a file with the dotcmd() builtin, dash raises an exception > > when the input file cannot be opened. > > > For instance the following script fails prematurely and does not output > > the message: > > > #!/bin/sh > > > . /non-existent-file > > echo "Survived!" > > > In this case, the behavior of dash is different from other shells (e.g. > > bash, zsh) which are more forgiving and allow execution to carry on even > > if the input file cannot be opened. > > POSIX is unambiguous (XCU 2.14 Special Built-In Utilities -> dot) that a > non-interactive shell shall abort when a dot script is not found, and > bash and zsh comply to this when standards compliance is requested (e.g. > by naming the shell "sh" in argv[0] or using "set -o posix" in bash or > "set -o posixbuiltins" in zsh). Most other shells (e.g. mksh, FreeBSD > sh, yash) comply to POSIX unconditionally here, like dash currently > does. > OK, thanks for clarifying that. I guess I was a little lazy for not checking before posting. > > Fix this by passing the INPUT_NOFILE_OK flag when calling setinputfile() > > in dotcmd(). > > > As a bonus, this also fixes cases like the following: > > > set -e > > . /non-existent-file || true > > echo "Survived! Let's do something else..." > > > This idiom is sometimes used in shell script to source a config file > > with default values only to provide fallback values if the default > > values were not available. > > The above code is specific to bash and zsh non-POSIX modes, and will not > work in a #!/bin/sh script unless specific steps are taken (such as "set > +o posix" or starting the script with "bash script1" rather than > "./script1"). > > The simple solution is > [ ! -f /non-existent-file ] || . /non-existent-file > Time-of-check-time-of-use issues should not be an issue for config > files. > Indeed this is the most used form, thank you again. Now I know that the other one is non-standard. Sorry for the noise, Antonio > Alternatively, one could try > command . ./non-existent-file || true > but this may ignore more errors than desired (such as syntax errors in > the sourced file) and does not work correctly in yash 2.30. > > -- > Jilles Tjoelker
diff --git a/src/main.c b/src/main.c index 6d53e00..a229d68 100644 --- a/src/main.c +++ b/src/main.c @@ -331,12 +331,18 @@ dotcmd(int argc, char **argv) char *fullname; fullname = find_dot_file(*argv); - setinputfile(fullname, INPUT_PUSH_FILE); + status = setinputfile(fullname, INPUT_PUSH_FILE | INPUT_NOFILE_OK); + if (status < 0) { + sh_warnx("%s: %s", fullname, strerror(errno)); + status = 1; + goto out; + } commandname = fullname; status = cmdloop(0); popfile(); } +out: return status; }
When sourcing a file with the dotcmd() builtin, dash raises an exception when the input file cannot be opened. For instance the following script fails prematurely and does not output the message: #!/bin/sh . /non-existent-file echo "Survived!" In this case, the behavior of dash is different from other shells (e.g. bash, zsh) which are more forgiving and allow execution to carry on even if the input file cannot be opened. Fix this by passing the INPUT_NOFILE_OK flag when calling setinputfile() in dotcmd(). As a bonus, this also fixes cases like the following: set -e . /non-existent-file || true echo "Survived! Let's do something else..." This idiom is sometimes used in shell script to source a config file with default values only to provide fallback values if the default values were not available. Signed-off-by: Antonio Ospite <ao2@ao2.it> --- Hi Herbert, I also thought about printing the warning in setinputfile() itself, maybe guarding the printout with a new flag, like INPUT_NOFILE_OK_SILENT, which could be used by readprofile() to keep the current silent behavior when profile files are not found. I though i'd send this simple version first to see if changing the behavior of dotcmd() is acceptable in the first place. If it is we can then discuss about how to do it. Thank you, Antonio src/main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)