- 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
This will be important when things like 'command eval f' will be possible.
Currently, the funcnest = 0 assignment in RESET (called when returning to
the top level after an error in interactive mode) is really sufficient.
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 .'.
That is, do not do tilde expansion if any of the CTL* bytes (\201-\210), not
only CTLESC and CTLQUOTEMARK, are encountered. Such an expansion would look
up a user name with sh's internal representation.
The parser does not currently distinguish between backslashed and
unbackslashed \201-\210, so tilde expansion of user names with these bytes
in them is not so easy to fix.
It is already done by evalcommand(), unless special-ness has been removed,
in which case variable assignments should not persist. (These are currently
always special builtins, but this will change later: command builtin,
command substitution.)
This also fixes a memory leak when calling . with variable assignments.
Example:
valgrind --leak-check=full sh -c 'x=1 . /dev/null; x=2'
- 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.
* exception handlers are now run with interrupts disabled, which avoids
many race conditions
* fix some cases where SIGINT only aborts one command and continues the
script, in particular if a SIGINT causes an EINTR error which trumped the
interrupt.
Example:
sh -c 'echo < /some/fifo; echo This should not be printed'
The fifo should not have writers. When pressing ctrl+c to abort the open,
the shell used to continue with the next command.
Example:
sh -c '/bin/echo < /some/fifo; echo This should not be printed'
Similar. Note, however, that this particular case did not and does not work
in interactive mode with job control enabled.
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.
* increase buffer size from 100 to 256 bytes
* remove implied flush from out2str(), in particular this avoids unnecessary
flushing in the middle of a -x tracing line
* rename dprintf() to out2fmt_flush(), make it flush out2 and use this
function in various places where flushing is desired after an error
message
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).
the line number where the command substitution started.
This applies to both the $() and `` forms but is most useful for ``
because the other line number is relative to the enclosed text there.
(For older versions, -v can be used as a workaround.)
This also fixes that trying to execute a non-regular file with a command
name without '/' returns 127 instead of 126.
The fix is rather simplistic: treat CMDUNKNOWN as if the command were found
as an external program. The resulting fork is a bit wasteful but executing
unknown commands should not be very frequent.
PR: bin/137659
Due to the amount of code removed by this, it seems that allowing unmatched
quotes was a deliberate imitation of System V sh and real ksh. Most other
shells do not allow unmatched quotes (e.g. bash, zsh, pdksh, NetBSD /bin/sh,
dash).
PR: bin/137657
I do not consider this a bug because POSIX permits it and argument strings
and environment variables cannot contain '\0' anyway.
PR: bin/25542
MFC after: 2 weeks
Empty pairs of braces are represented by a NULL node pointer, just like
empty lines at the top level.
Support for empty pairs of braces may be removed later. They make the code
more complex, have inconsistent behaviour (may or may not change $?), are
not specified by POSIX and are not allowed by some other shells like bash,
dash and ksh93.
Reported by: kan
Add a reference count to function definitions.
Memory may leak if multiple SIGINTs arrive in interactive mode,
this will be fixed later by changing SIGINT handling.
PR: bin/137640
in particular "$@"$ifschar if the final positional parameter is empty.
With the NetBSD code, adding the $ifschar removes a parameter.
PR: standards/79067
Approved by: ed (mentor) (implicit)
(EV_EXIT). The fork is still done as normal if any traps are active.
In many cases, the fork can be avoided even without this change by using {}
instead of (), but in practice many scripts use (), likely because the
syntax is simpler.
Example:
sh -c '(/bin/sleep 10)& sleep 1;ps -p $! -o comm='
Now prints "sleep" instead of "sh". $! is more useful this way.
Most shells (dash, bash, pdksh, ksh93, zsh) seem to print "sleep" for this.
Example:
sh -c '( ( ( (ps jT))))'
Now shows no waiting shell processes instead of four.
Most shells (dash, bash, pdksh, ksh93, zsh) seem to show zero or one.
PR: bin/74404
Approved by: ed (mentor) (implicit)
- update for getrlimit(2) manpage;
- support for setting RLIMIT_SWAP in login class;
- addition to the limits(1) and sh and csh limit-setting builtins;
- tuning(7) documentation on the sysctls controlling overcommit.
In collaboration with: pho
Reviewed by: alc
Approved by: re (kensmith)
- remove ineffective and unnecessary (void) &var; [1]
- remove some unnecessary volatile keywords
- add a necessary volatile keyword
- save the old handler before doing something that could use the saved
value
Submitted by: Christoph Mallon [1]
Approved by: ed (mentor)
Formerly, it was possible for the file to be created between the check if it
existed and the open; the contents would then be lost.
Because this must use O_EXCL, noclobber > will not create a file through a
symlink anymore. This agrees with behaviour of other shells.
Approved by: ed (mentor) (implicit)
Output quoted suitable for re-input to the shell occurs in
various cases such as 'set', 'trap'.
Bugfix: *, ? and [ must be quoted (except sole [)
Bugfix: ~ and # must be quoted (really only sometimes, but keep it simple)
Bugfix: space, tab and newline must always be quoted
Shortening: other IFS characters do not need quoting
Bugfix: send to correct output file, not hard-coded stdout
Shortening: avoid unnecessary '' with \'
Approved by: ed (mentor)
For parsing an old-style backquote substitution (`...`),
a string "file" is used to store the contents of the
substitution (with the special backslash processing done).
If an error occurs, the shell cleans up all these files
(returning to the top level) and flush the top level
file. Erroneously, it first flushed the current file and
then cleaned up all extra files, so that the top level
file (i.e. the terminal) was not flushed.
Example (in interactive mode):
echo `for` echo This should not be printed
Also noticeable in (in interactive mode):
echo `(`
The old version prints an extraneous prompt.
Approved by: ed (mentor)
This change only affects strings passed to -c, when the -s
option is not used.
The approach is to check if there may be additional data
in the string after parsing each command. If there is none,
use the EV_EXIT flag so that a fork may be omitted in
specific cases.
If there are empty lines after the command, the check will
not see the end and forks will not be omitted. The same
thing seems to happen in bash.
Example:
sh -c 'ps lT'
No longer shows a shell process waiting for ps to finish.
PR: bin/113860
Reviewed by: stefanf
Approved by: ed (mentor)
Example:
sh -c '(trap "echo trapped" EXIT; sleep 3)'
now correctly prints "trapped".
With this check, it is no longer necessary to check for -T
explicitly in that case.
This is a useful bugfix by itself and also important because I plan to
skip forking more often.
PR: bin/113860 (part of)
PR: bin/74404 (part of)
Reviewed by: stefanf
Approved by: ed (mentor)
The exit status may exceed 255 in some cases (return); even though it seems
unwise to rely on this, it is also unwise to assume that $? is always
between 0 and 255.
This resolves bin/124748 by documenting that 'exit -1' is not valid.
PR: bin/124748
Approved by: ed (mentor)