Hush uses recursion for (at least) parsing nested constructs like { ... }, so it's possible for pathological/malicious scripts to overflow the stack, but this should be enough for just about anything non-pathological (e.g. up to about 10 levels of nested { }).
The problem seemed to be that it crashes if the t_intrc special character is set to -1 on a pty. I worked around this by setting it to an obscure control character instead in that case.
The support for OA-left/right on GNO uses the OA2META ioctl option to map OA-x to ESC x.
VT100-type terminal emulators have significant variations in what modifier combinations they'll pass through and what escape sequences they produce. Hopefully at least one of them works on just about everything.
This was broken by the change to using CRMOD mode, which actually does mapping on input as well as output. The fix is to set the terminal to "vt100 arrow" mode, which is an undocumented option that translates arrows to vt100-style escape sequences (also used by gsh).
(Note that the earlier patch actually makes us use CRMOD mode most of the time, not non-CRMOD mode as the summary erroneously says.)
This is important because CRMOD mode prevents text from backgrounded programs from being printed properly. It also leaves the terminal in an inappropriate state if hush crashes or is killed.
For the time being, we still switch briefly to CRMOD mode when we want to print just a CR.
This is done by adding new memory allocation routines that use the current process's userID, so the memory will be deallocated when it quits or execs, even if it's a forked child process.
The bug is that an #if condition may be mis-evaluated if it immediately follows a use of a function-like macro. I also modified a couple other places that could possibly trigger the bug (including a possibly more reliable fix for the instance of this problem I worked around earlier in include/xatonum.h).
We do this by maintaining a mask (for each pid) giving the fds to be closed on exec. We wrap functions that close fds so that their close-on-exec bits can be cleared at that point.
This implementation may close the fds even if the execve operation ultimately fails.
Also, fix issue where callers of getopt32() weren't properly detecting errors on GNO due to a size mismatch.
This avoids strange behavior when commands using getopt32 (like export) are invoked multiple times, sometimes with invalid arguments.
This avoids problems stemming from the fact that GNO's environment implementation may deallocate those strings, in some cases before we're done with them. It also allows us to uppercase the variable names, although since we made them case-insensitive this only matters for display purposes (in "set" output).
This avoids a problem where one of the SIGALRM signals could be delivered after the original SIGALRM handler was restored, which would normally cause the process to terminate.
For now, we just rely on polling in a loop to determine when the child is done. This isn't optimal, but should be OK. If procsend() worked, we could use that in the child to signal the parent. However, procsend() is broken in GNO 2.0.6 -- it seems that it actually tries to invoke the send() call for sockets, but with the wrong arguments, leading to a crash.
This should allow most typical cases of arguments with spaces to work correctly, although it will still break down in some cases. We can't do this perfectly, because we're ultimately dependent on the argument parsing code in the target application, and at least the code generated by ORCA/C doesn't give us a way to make an arbitrary string be treated as a single argument.
*Most significantly, we avoid using setpgid(), because it doesn't work and in fact corrupts the kernel's process group table.
*Also, work around tctpgrp() returning garbage instead of 0 on success.
This adds an implementation of tcsetpgrp that works by reading the process tables to find a process in the appropriate group. This isn't used for the main job control operations, though, since it might be relatively slow.
At this point, basic job control seems to work.
* Push/pop environment to make sure it is isolated from our parents and children.
* Make all environment vars (and shell vars) case-insensitive, consistent with GNO's internal handling of environment vars.
* Wrap putenv and unsetenv to make sure they are called with lower-case variable names, which is necessary to maintain consistency between the environ array and the kernel's internal representation of variables.