Based on the patch by Rich Felker <dalias@libc.org>
function old new delta
builtin_umask 121 161 +40
umaskcmd 318 279 -39
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
POSIX says that _exit() should do this, but on GNO it doesn't. This implementation should match the POSIX behavior in most cases, although it's not exactly the same.
Gsh also kills jobs on exit, but does so whether they're stopped or not and uses SIGKILL.
The logic for this was broken (giving a signal number rather than a mask to sigblock), and if it wasn't broken then it would have caused the wait call to hang.
Blocking SIGCHLD is required by POSIX, but gsh doesn't do it, so existing GNO code shouldn't be relying on it.
The issue is that GNO's login (and other BSD-derived versions) start up the login shell with SIGTSTP ignored. Hush was recording this configuration and propagating it to its child processes, causing ^Z not to work. The fix is to not do that (for login shells only).
Also, set the system vector to run hush before running any of the startup scripts, in case something run in them uses it.
Commands in the range of 16k-32k should now work, and commands longer than that should cause hush to die with an error message instead of corrupting stuff (at least in the simple cases I tested).
It would be possible to eliminate the 32k limit by using a type larger than "int" for lengths, but that would be a more invasive change.
This addresses a problem where something invoked in a group or function (e.g. gsh) could change the terminal's pgrp, and this would result in hush getting backgrounded.
We can still get strange behavior when a backgrounded child process changes the pgrp. Trying to deal with this would be inherently racy. Gsh also has problems in this scenario.
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.
This should avoid strange behavior due to races when the parent has resumed but the child is still running the exec* code in libc, which mainly manifests itself when running at low speed.
We also change to signaling the child's completion with SIGALRM, and setting an extra alarm in the parent in case the child doesn't actually do it.
GNO's _exit (contrary to its man page) does clean-up for stuff like the memory allocator, which is inappropriate in a forked child process and leads to hangs and crashes.