| #
d1c86d36 |
| 09-Oct-2024 |
kre <kre@NetBSD.org> |
PR bin/58687 -- implement suspend as a builtin in sh
Requested by uwe@ in PR bin/58687 without objections from anyone except me, here is an implementation of a suspend builtin command for /bin/sh
T
PR bin/58687 -- implement suspend as a builtin in sh
Requested by uwe@ in PR bin/58687 without objections from anyone except me, here is an implementation of a suspend builtin command for /bin/sh
The sh.1 man page is updated, naturally, to describe it.
This new builtin does not exist in SMALL shells -- as used on (some) boot media, etc.
If this turns out not to be useful, it can easily be removed.
show more ...
|
| #
c591669f |
| 13-Jul-2024 |
kre <kre@NetBSD.org> |
Implement the HISTFILE and HISTAPPEND variables.
See the (newly updated) sh(1) for details. Also add the -z option to fc (clear history).
None of this exists in SMALL shells.
|
| #
b8bee70d |
| 10-Nov-2021 |
kre <kre@NetBSD.org> |
DEBUG mode changes only. NFC (NC) for any normally compiled shell.
Mostly adding DEBUG mode tracing (when appropriate verbose tracing is enabled generally) whenever a shell (including sushell) pro
DEBUG mode changes only. NFC (NC) for any normally compiled shell.
Mostly adding DEBUG mode tracing (when appropriate verbose tracing is enabled generally) whenever a shell (including sushell) process exits, so shells that the tracing should indicate why ehslls that vanish did that.
Note for future investigators: if the relevant tracing is enabled, and a (sub-)shell still simply seems to have vanished without trace, the likely cause is that it was killed by a signal - and of those, the most common that occurs is SIGPIPE.
show more ...
|
| #
4a370dce |
| 20-Aug-2020 |
kre <kre@NetBSD.org> |
Be less conservative about when we do clear_traps() when we have traps_invalid (that is, when we actually nuke the parent shell's caught traps in a subshell). This allows more reasonable use of "tra
Be less conservative about when we do clear_traps() when we have traps_invalid (that is, when we actually nuke the parent shell's caught traps in a subshell). This allows more reasonable use of "trap -p" (and similar) in subshells than existed before (and in particular, that command can be in a function now - there can also be several related commands like traps=$(trap -p INT; trap -p QUIT; trap -p HUP) A side effect of all of this is that (eval "$(trap -p)"; ...) now allows copying caught traps into a subshell environment, if desired.
Also att the ksh93 variant (the one not picked by POSIX as it isn't generally as useful) of "trap -p" (but call it "trap -P" which extracts just the trap action for named signals (giving more than one is usually undesirable). This allows eval "$(trap -P INT)" to run the action for SIGINT traps, without needing to attempt to parse the "trap -p" output.
show more ...
|
| #
20122b0e |
| 20-Aug-2020 |
kre <kre@NetBSD.org> |
Whitespace. NFCI.
|
| #
ff46268c |
| 09-Dec-2019 |
kre <kre@NetBSD.org> |
PR bin/54743
If a builtin command or function is the final command intended to be executed, and is interrupted by a caught signal, the trap handler for that signal was not executed - the shell simpl
PR bin/54743
If a builtin command or function is the final command intended to be executed, and is interrupted by a caught signal, the trap handler for that signal was not executed - the shell simply exited (an exit trap handler would still have been run - if there was one the handler for the signal may have been invoked during the execution of the exit trap handler, which, if it happened, is incorrect sequencing).
Now, if we're exiting, and there are pending signals, run their handlers just before running the EXIT trap handler, if any.
There are almost certainly plenty more issues with traps that need solving. Later,
XXX pullup -9
(-8 is too different in this area, and this problem suitably obscure, that we won't bother) (the -7 sh is simply obsolete).
show more ...
|
| #
e904ec40 |
| 25-Apr-2019 |
kre <kre@NetBSD.org> |
Better interactive SIGINT handling (when a trap is set), and other cleanups to the trap code. No longer silently ignore attempts to do anything other than set SIGKILL or SIGSTOP to the default ('-"
Better interactive SIGINT handling (when a trap is set), and other cleanups to the trap code. No longer silently ignore attempts to do anything other than set SIGKILL or SIGSTOP to the default ('-") state. Don't include those in trap or trap -p output (the former because they cannot be other than in default state, so simply aren't included, the latter because it is pointless) but do list them when requested with trap -p SIG.
Interactive mode SIGINT traps are now run ASAP, rather than after a command has been entered (so the sequence ^C \n is no longer needed to generate one). Further, when trapped, in interactive mode, while waiting for a user command, a SIGINT acts (aside from the trap being run) just like when not trapped, aborts the command being entered (rather than leaving it, which it did when libedit was in use) prints a new prompt, and starts again (which is what should happen.)
Traps other than SIGINT (which has always been handled special in interactive mode) are unaffected by this change, as are SIGINT traps in non-interactive shells. Or that is the intent anyway.
Fix an in_dotrap ref count bug (was never being decremented... that was inserted in a place never executed) (relatively harmless) and add/improve some trap/signal related DEBUG mode tracing.
show more ...
|
| #
e8ed7c88 |
| 18-Jan-2019 |
kre <kre@NetBSD.org> |
Finish (hopefully) the second half of 1.47 ... make sure that when traps are marked as invalid, we never use them for anything except output from the trap command.
Fixes issues where sub-shells of s
Finish (hopefully) the second half of 1.47 ... make sure that when traps are marked as invalid, we never use them for anything except output from the trap command.
Fixes issues where sub-shells of shells which use traps (eg: to trap SIGPIPE) can end up looping forever if the signal occurs in a sub-shell (where the trap is supposed to be reset to its default). Reported, and mostly analyzed by Martijn Dekker.
show more ...
|
| #
af2cfdd7 |
| 12-Dec-2018 |
kre <kre@NetBSD.org> |
Reverse a decision made when the printsignals() routines from kill and sh were merged so that the shell (for trap -l) and kill (for kill -l) can use the same routine, and site that function in the sh
Reverse a decision made when the printsignals() routines from kill and sh were merged so that the shell (for trap -l) and kill (for kill -l) can use the same routine, and site that function in the shell, rather than in kill (use the code that is in kill as the basis for that routine). This allows access to sh internals, and in particular to the posix option, so the builtin kill can operate in posix mode where the standard requires just a single character (space of newline) between successive signal names (and we prefer nicely aligned columns instead)..
In a SMALL shell, use the ancient sh printsignals routine instead, it is smaller (and very much dumber).
/bin/kill still uses the routine that is in its source, and is not posix compliant. A task for some other day...
show more ...
|
| #
78cb4ed2 |
| 05-Dec-2018 |
kre <kre@NetBSD.org> |
evert previous, linux build problem confirmed fixed by update to mkinit.sh (to 1.10).
Or more correctly, revert & fix - turns out that there was an off by one (failure to adjust for other changes --
evert previous, linux build problem confirmed fixed by update to mkinit.sh (to 1.10).
Or more correctly, revert & fix - turns out that there was an off by one (failure to adjust for other changes -- in a value printed by debug mode trace output).
NFC.
show more ...
|
| #
24e0ca1d |
| 05-Dec-2018 |
kre <kre@NetBSD.org> |
NFC (except that it should, I am guessing, fix compilation on some versions of liux) - DEBUG mode change: Delete a (relatively new) trace point (temporarily anyway) which mkinit (a script run using
NFC (except that it should, I am guessing, fix compilation on some versions of liux) - DEBUG mode change: Delete a (relatively new) trace point (temporarily anyway) which mkinit (a script run using the host's /bin/sh) apparently cannot handle correctly on (some release of) linux (it is fine with the NetBSD shell).
I don't know which linux version has a shell with this problem (or whether it is a mkinit issue that only works by fluke on NetBSD)
Problem reported by gson@
show more ...
|
| #
13fc5c1b |
| 03-Dec-2018 |
kre <kre@NetBSD.org> |
Cleanup traps a bit - attempt to handle weird uses in traps, such as traps that issue break/continue/return to cause the loop/function executing when the trap occurred to break/continue/return, and g
Cleanup traps a bit - attempt to handle weird uses in traps, such as traps that issue break/continue/return to cause the loop/function executing when the trap occurred to break/continue/return, and generating the correct exit code from the shell including when a signal is caught, but the trap handler for it exits.
All that from FreeBSD.
Also make T=$(trap) work as it is supposed to (also trap -p).
For now this is handled by the same technique as $(jobs) - rather than clearing the traps in subshells, just mark them invalid, and then whenever they're invalid, clear them before executing anything other than the special blessed "trap" command. Eventually we will handle these using non-subshell command substitution instead (not creating a subshell environ when the commands in a command-sub alter nothing in the environment).
show more ...
|
| #
33a05de6 |
| 28-Oct-2018 |
kre <kre@NetBSD.org> |
Switch from using two printsignals() functions, one in trap.c and one in (the included from bin/kill) kill.c and use just the one in kill.c (which is amended slightly so it can work the way that trap
Switch from using two printsignals() functions, one in trap.c and one in (the included from bin/kill) kill.c and use just the one in kill.c (which is amended slightly so it can work the way that trap.c needs it to work). This one is chosen as it was a much nicer implementation, and because while kill is always built into the shell, kill also exists without the shell.
Leave the old implementation #if 0'd in trap.c (but updated to match the calling convention of the one in kill.c) - for now.
Delete references of sys_signame[] from sh/trap.c and along with that several uses of NSIG (unfortunately, there are still more) and replace them with the newer libc functional interfaces.
show more ...
|
| #
8a9a9619 |
| 19-Aug-2018 |
kre <kre@NetBSD.org> |
PR bin/48875 (is related, and ameliorated, but not exactly "fixed")
Import a whole set of tree evaluation enhancements from FreeBSD.
With these, before forking, the shell predicts (often) when all
PR bin/48875 (is related, and ameliorated, but not exactly "fixed")
Import a whole set of tree evaluation enhancements from FreeBSD.
With these, before forking, the shell predicts (often) when all it will have to do after forking (in the parent) is wait for the child and then exit with the status from the child, and in such a case simply does not fork, but rather allows the child to take over the parent's role.
This turns out to handle the particular test case from PR bin/48875 in such a way that it works as hoped, rather than as it did (the delay there was caused by an extra copy of the shell hanging around waiting for the background child to complete ... and keeping the command substitution stdout open, so the "real" parent had to wait in case more output appeared).
As part of doing this, redirection processing for compound commands gets moved out of evalsubshell() and into a new evalredir(), which allows us to properly handle errors occurring while performing those redirects, and not mishandle (as in simply forget) fd's which had been moved out of the way temporarily.
evaltree() has its degree of recursion reduced by making it loop to handle the subsequent operation: that is instead of (for any binop like ';' '&&' (etc)) where it used to evaltree(node->left); evaltree(node->right); return; it now does (kind of) next = node; while ((node = next) != NULL) { next = NULL;
if (node is a binary op) { evaltree(node->left); if appropriate /* if && test for success, etc */ next = node->right; continue; } /* similar for loops, etc */ } which can be a good saving, as while the left side (now) tends to be (usually) a simple (or simpleish) command, the right side can be many commands (in a command sequence like a; b; c; d; ... the node at the top of the tree will now have "a" as its left node, and the tree for b; c; d; ... as its right node - until now everything was evaluated recursively so it made no difference, and the tree was constructed the other way).
if/while/... statements are done similarly, recurse to evaluate the condition, then if the (or one of the) body parts is to be evaluated, set next to that, and loop (previously it recursed).
There is more to do in this area (particularly in the way that case statements are processed - we can avoid recursion there as well) but that can wait for another day.
While doing all of this we keep much better track of when the shell is just going to exit once the current tree is evaluated (with a new predicate at_eof() to tell us that we have, for sure, reached the end of the input stream, that is, this shell will, for certain, not be reading more command input) and use that info to avoid unneeded forks. For that we also need another new predicate (have_traps()) to determine of there are any caught traps which might occur - if there are, we need to remain to (potentially) handle them, so these optimisations will not occur (to make the issue in PR 48875 appear again, run the same code, but with a trap set to execute some code when a signal (or EXIT) occurs - note that the trap must be set in the appropriate level of sub-shell to have this effect, any caught traps are cleared in a subshell whenever one is created).
There is still work to be done to handle traps properly, whatever weirdness they do (some of which is related to some of this.)
These changes do not need man page updates, but 48875 does - an update to sh.1 will be forthcoming once it is decided what it should say...
Once again, all the heavy lifting for this set of changes comes directly (with thanks) from the FreeBSD shell.
XXX pullup-8 (but not very soon)
show more ...
|
| #
ee4a694a |
| 22-Jul-2018 |
kre <kre@NetBSD.org> |
PR bin/36532 (perhaps)
This is more or less the same patch as provided in the PR (just 11 years later, so changed a bit) by woods@...
Since there is no known way to actually cause the reported cras
PR bin/36532 (perhaps)
This is more or less the same patch as provided in the PR (just 11 years later, so changed a bit) by woods@...
Since there is no known way to actually cause the reported crash, we may never know if this change actually fixes anything. But even if it doesn't it certainly cannot hurt.
There is a potential race which could possibly explain the issue (see commentary in the PR) which is not easy to avoid - if that is the actual cause, this should provide a defence, if not really a fix.
show more ...
|
| #
144cb209 |
| 22-Jul-2018 |
kre <kre@NetBSD.org> |
Revert previous, change has nothing to do with DEBUG mode. COming again (correctly) in a few seconds.
|
| #
bcacfd9a |
| 22-Jul-2018 |
kre <kre@NetBSD.org> |
DEBUG mode only change (ie: no effect to any normal shell).
Add tracing of pattern matching (aid in debugging various issues.)
|
| #
2e1a04e9 |
| 05-Jul-2017 |
kre <kre@NetBSD.org> |
DEBUG and white space changes only. Convert TRACE() calls for DEBUg mode to the new style. NFC (when not debugging sh).
|
| #
5791be97 |
| 07-May-2017 |
kre <kre@NetBSD.org> |
Enhance the trap command to make it possible to do what POSIX wants (even if no shell in existence, that I am aware of, does that).
That is, POSIX says ... [of the trap command with no args]
The s
Enhance the trap command to make it possible to do what POSIX wants (even if no shell in existence, that I am aware of, does that).
That is, POSIX says ... [of the trap command with no args]
The shell shall format the output, including the proper use of quoting, so that it is suitable for re-input to the shell as commands that achieve the same trapping results. For example:
save_traps=$(trap)
...
eval "$save_traps"
It is obvious what the intent is there. But no shell makes it work.
An example using bash (as the NetBSD shell, still does not do the save_traps= stuff correctly - but that is a problem for a different time and place...)
Given this script
printf 'At start: '; trap printf '\n'
traps=$(trap) trap 'echo hello' INT printf 'inside : '; trap printf '\n' eval "${traps}"
printf 'At end : '; trap printf '\n'
One would expect that (assuming no traps are set at the start, and there aren't) that the first trap will print nothing, then the inside trap will show the trap that was set, and then when we get to the end everything will be back to nothing again.
But:
At start: inside : trap -- 'echo hello' SIGINT
At end : trap -- 'echo hello' SIGINT
And of course. when you think about it, it is obvious why this happens. The first "trap" command prints nothing ... nothing has changed when we get to the "traps=$(trap)" command ... that trap command also prints nothing. So this does traps=''. When we do eval "${traps}" we are doing eval "", and it is hardly surprising that this accomplishes nothing!
Now we cannot rationally change the "trap" command without args to behave in a way that would make it useful for the posix purpose (and here, what they're aiming for is good, it should be possible to accomplish that objective) so is there some other way?
I think I have seen some shell (but I do not remember which one) that actually has "trap -" that resets all traps to the default, so with that, if we changed the 'eval "${traps}"' line to 'trap -; eval "${traps}"' then things would actually work - kind of - that version has race conditions, so is not really safe to use (it will work, most of the time...)
But, both ksh93 and bash have a -p arg to "trap" that allows information about the current trap status of named signals to be reported. Unfortunately they don't do quite the same thing, but that's not important right now, either would be usable, and they are, but it is a lot of effort, not nearly as simple as the posix example.
First, while "trap -p" (with no signals specified) works, it works just the same (in both bash and ksh93, aside from output format) as "trap". That is, that is useless. But we can to
trap_int=$(trap -p int) trap_hup=$(trap -p hup) ...
and then reset them all, one by one, later...
(bash syntax) test -n "${trap_int}" && eval "${trap_int}" || trap - int test -n "${trap_hup}" && eval "${trap_hup}" || trap - hup (ksh93 syntax) trap "${trap_int:-}" int trap "${trap_hup:-}" hup
the test (for bash) and variable with default for ksh93, is needed because they both still print nothing if the signal action is the default.
So, this modification attempts to fix all of that...
1) we add trap -p, but make it always output something for every signal listed (all of the signals if none are given) even if the signal action is the default.
2) choose the bash output format for trap -p, over the ksh93 format, even though the simpler usage just above makes the ksh93 form seem better. But it isn't. Consider:
ksh93$ trap -p int hup echo hello
One of the two traps has "echo hello" as its action, the other is still at the default, but which?
From bash... bash$ trap -p int hup trap -- 'echo hello' SIGINT
And now we know! Given the bash 'trap -p' format, the following function produces ksh93 format output (for use with named signals only) instead...
ksh93_trap_p() { for _ARG_ do _TRAP_=$(trap -p "${_ARG_}") || return 1 eval set -- "${_TRAP_}" printf '%s' "$3${3:+ }" done return 0 }
[ It needs to be entered without the indentation, that '}"' line has to be at the margin. If the shell running that has local vars (bash does) then _ARG_ and _TRAP_ should be made local. ]
So the bash format was chosen (except we do not include the "SIG" on the signal names. That's irrelevant.)
If no traps are set, "trap -p" will say (on NetBSD of course)...
trap -- - EXIT HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS trap -- - PIPE ALRM TERM URG STOP TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ trap -- - VTALRM PROF WINCH INFO USR1 USR2 PWR RT0 RT1 RT2 RT3 RT4 RT5 trap -- - RT6 RT7 RT8 RT9 RT10 RT11 RT12 RT13 RT14 RT15 RT16 RT17 RT18 trap -- - RT19 RT20 RT21 RT22 RT23 RT24 RT25 RT26 RT27 RT28 RT29 RT30
Obviously if traps are set, the relevant signal names will be removed from that list, and additional lines added for the trapped signals.
With args, the signals names are listed, one line each, whatever the status of the trap for that signal is:
$ trap -p HUP INT QUIT trap -- - HUP trap -- 'echo interrupted' INT trap -- - QUIT
3) we add "trap -" to reset all traps to default. (It is easy, and seems useful.)
4) While here, lots of generic cleanup. In particular, get rid of the NSIG+1 nonsense, and anything that ever believes a signo == NSIG is in any way rational. Before there was a bunch of confusion, as we need all the signals for traps, plus one more for the EXIT trap, which looks like we then need NSIG+1. But EXIT is 0, NSIG includes signals from 0..NSIG-1 but there is no signal 0, EXIT uses that slot, so we do not need to add and extra one, NSIG is enough. (To see the effect of this, use a /bin/sh from before this fix, and compare the output from
trap '' 64 and trap '' 65
both invalid signal numbers.
Then try just "trap" and watch your shell drop core...)
Eventually NSIG needs to go away completely (from user apps), it is not POSIX, it isn't really useful (unless we make lots of assumptions about how signals are numbered, which are not guaranteed, so even if apps, like this sh, work on NetBSD, they're not portable,) and it isn't necessary (or will not be, soon.)
But that is for another day...
5) As is kind of obvious above, when listing "all" traps, list all the ones still at their defaults, and all the ignored signals, on as few lines as possible (it could all be on one line - technically it would work as well, but it would have made this cvs log message really ugly...) Signals with a non-null action still get listed one to a line (even if several do have the exact same action.)
6) Man page updates as well.
After this change, the following script:
printf 'At start: '; trap printf '\n'
trap -p >/tmp/out.$$ trap 'echo hello' INT printf 'inside : '; trap printf '\n' . /tmp/out.$$; rm /tmp/out.$$
printf 'At end : '; trap printf '\n'
which is just the example from above, using "trap -p" instead of just "trap" to save the traps, and modified to a form that will work with the NetBSD shell today produces:
At start: inside : trap -- 'echo hello' INT
At end :
[Do I get a prize for longest commit log message of the year?]
show more ...
|
| #
6f0d4805 |
| 29-Apr-2017 |
kre <kre@NetBSD.org> |
Fix several problems with the implementation of the "trap" command (that is, with the command itself, not with the traps that are executed, if any).
- "trap -- -l" is not rational, permit the (non-s
Fix several problems with the implementation of the "trap" command (that is, with the command itself, not with the traps that are executed, if any).
- "trap -- -l" is not rational, permit the (non-std) -l option only when given as the sole arg (ie: "trap -l"). - "trap --" is the same as just "trap" (and -- is ignored for below) - "trap action" generates a usage message (there must be at least one condition) - "trap N [condition...]" (the old form with a numeric first arg, to reset traps to default, instead of "trap - condition...") is properly detected. In particular while "trap 1 2 3" resets sighup sigint and siquit handlers to default, "trap hup int quit" runs the "hup" command on sigint or sigquit and does nothing to sighup at all. - actions can start with "-" (as can commands in general) - it may be unusual or even unwise, but it is not prohibited, and should work - bad conditions (signal names/numbers) are just a usage error (resulting in non-zero "exit status" (and a diagnostic on stderr)) they do not cause the script to abort (as a syntax error in a special builtin would.) (so says posix, very explicitly.) - when outputting the trap list ("trap") properly quote null actions (ignored conditions). This has the side effect of also generating an explicit null string ('') in other cases where null values are output, such as when reporting var values ("set") but that's OK, and might be better (VAR= and VAR='' mean the same, but the latter is more obvious.)
We still do not properly handle traps=$(trap) (ie: it does not work at all, and should) but that's a different problem that needs fixing in another place.
show more ...
|
| #
c19b98a9 |
| 26-Apr-2017 |
kre <kre@NetBSD.org> |
Deal with traps that reset the (same) trap in the trap handler (avoid referrencing memory that might have been freed). From FreeBSD (ages ago, just not committed until now...)
|
| #
f95d5940 |
| 22-Aug-2015 |
christos <christos@NetBSD.org> |
report the signal that wait was interrupted by, which is not always SIGINT anymore.
|
| #
c0195771 |
| 22-Aug-2015 |
christos <christos@NetBSD.org> |
Process pending signals while waiting for a job: $ cat << EOF > hup.sh #!/bin/sh trap 'echo SIGHUP; exit 1' 1 sleep 10000 & wait EOF $ chmod +x ./hup.sh $ ./hup.sh &
Process pending signals while waiting for a job: $ cat << EOF > hup.sh #!/bin/sh trap 'echo SIGHUP; exit 1' 1 sleep 10000 & wait EOF $ chmod +x ./hup.sh $ ./hup.sh & $ kill -HUP %1
show more ...
|
| #
4fc4fe2e |
| 18-Jun-2011 |
christos <christos@NetBSD.org> |
PR/45069: Henning Petersen: Use prototypes from builtins.h .
|
| #
4498b1fe |
| 15-Feb-2008 |
matt <matt@NetBSD.org> |
Fix inconsistent definitions
|