case1.0 tests POSIX requirements and one more for keywords in case
statements. The others test very special cases of command substitution.
These also work on stable/8.
This allows doing things like LC_ALL=C some_builtin to run a builtin under a
different locale, just like is possible with external programs. The
immediate reason is that this allows making printf(1) a builtin without
breaking things like LC_NUMERIC=C printf '%f\n' 1.2
This change also affects special builtins, as even though the assignment is
persistent, the export is only to the builtin (unless the variable was
already exported).
Note: for this to work for builtins that also exist as external programs
such as /bin/test, the setlocale() call must be under #ifndef SHELL. The
shell will do the setlocale() calls which may not agree with the environment
variables.
Unset PWD if it is incorrect and no value for it can be determined.
This preserves the logical current directory across shell invocations.
Example (assuming /home is a symlink):
$ cd
$ pwd
/home/foo
$ sh
$ pwd
/home/foo
Formerly the second pwd would show the physical path (symlinks resolved).
Current versions pass this test trivially by never importing PWD, but I plan
to change sh to import PWD if it is an absolute pathname for the current
directory, possibly containing symlinks.
This applies to word in ${v-word}, ${v+word}, ${v=word}, ${v?word} (which
inherits quoting from the outside) and in ${v%word}, ${v%%word}, ${v#word},
${v##word} (which does not inherit any quoting).
In all cases tilde expansion is only attempted at the start of word, even if
word contains spaces. This agrees with POSIX and other shells.
This is the last part of the patch tested in the exp-run.
Exp-run done by: erwin (with some other sh(1) changes)
Note that this depends on r206145 for allowing pattern match characters to
have their special meaning inside a double-quoted expansion like "${v%pat}".
PR: bin/117748
Exp-run done by: erwin (with some other sh(1) changes)
* remove the backslash from \} inside double quotes inside +-=?
substitutions, e.g. "${$+\}a}"
* maintain separate double-quote state for ${v#...} and ${v%...};
single and double quotes are special inside, even in a double-quoted
string or here document
* keep track of correct order of substitutions and arithmetic
This is different from dash's approach, which does not track individual
double quotes in the parser, trying to fix this up during expansion.
This treats single quotes inside "${v#...}" incorrectly, however.
This is similar to NetBSD's approach (as submitted in PR bin/57554), but
recognizes the difference between +-=? and #% substitutions hinted at in
POSIX and is more refined for arithmetic expansion and here documents.
PR: bin/57554
Exp-run done by: erwin (with some other sh(1) changes)
Redirection errors on subshells already did not abort the shell because
the redirection is executed in the subshell.
Other shells seem to agree that these redirection errors should not abort
the shell.
Also ensure that the redirections will be cleaned up properly in cases like
command eval '{ shift x; } 2>/dev/null'
Example:
{ echo bad; } </var/empty/x; echo good
Although simple commands without a command word (only assignments and/or
redirections) are much like special builtins, POSIX and most shells seem to
agree that redirection errors should not abort the shell in this case. Of
course, the assignments persist and assignment errors are fatal.
To get the old behaviour portably, use the ':' special builtin.
To get the new behaviour portably, given that there are no assignments, use
the 'true' regular builtin.
We currently ignore readonly status for assignments before regular builtins
and external programs (these assignments are not persistent anyway), so just
check that the readonly variable really is not changed.
The test depends on the command builtin changes for 'command :'.
These expansions, which were already in the Bourne shell, work correctly for
the most part. The testcases are only about the parts that already work
correctly.
They are mainly about expansions in here documents but because all the
testcases are in $() command substitution, we also test that $() command
substitution is recursively parsed (or very close to it).
* avoid unnecessary fork
* allow executing builtins via command
* executing a special builtin via command removes its special properties
Obtained from: NetBSD (parts)
- correctly handle error output in $(builtin 2>&1), clarify out1/out2 vs
output/errout in the code
- treat all builtins as regular builtins so errors do not abort the shell
and variable assignments do not persist
- respect the caller's INTOFF
Some bugs still exist:
- expansion errors may still abort the shell
- some side effects of expansions and builtins persist
Reset the exception handler in the child to main's.
This avoids inappropriate double cleanups or shell duplication when the
exception is caught, such as 'fc' and future 'command eval' and 'command .'.
- Redirecting fds that were not open before kept two copies of the
redirected file.
sh -c '{ :; } 7>/dev/null; fstat -p $$; true'
(both fd 7 and 10 remained open)
- File descriptors used to restore things after redirection were not
set close-on-exec, instead they were explicitly closed before executing
a program normally and before executing a shell procedure. The latter
must remain but the former is replaced by close-on-exec.
sh -c 'exec 7</; { exec fstat -p $$; } 7>/dev/null; true'
(fd 10 remained open)
The examples above are simpler than the testsuite because I do not want to
use fstat or procstat in the testsuite.
This avoids weirdness when 'fc -e vi' or the like is done and there is a
syntax error in the file. Formerly an interactive shell tried to execute
stuff after the syntax error and exited.
This should also avoid similar issues with 'command eval' and 'command .'
when 'command' is implemented properly as in NetBSD sh.
Special builtins did not have this problem since errors in them cause the
shell to exit or to reset various state such as the current command input
file.
This seems more useful and will likely be in the next POSIX standard.
Also document more precisely in the man page what set -u does (note that
$@, $* and $! are the only special parameters that can ever be unset, all
the others are always set, although they may be empty).