The contorted rules for reporting the state of the parent shell suggest that maybe the entire approach needs re-thinking.
Several approaches come to mind. 1. Create a built-in “parent” command where “parent ulimit” or “parent trap” answers based on the parent shell rather than the subshell itself. (Obviously it would be the snapshot taken when the processes forked, rather than the parent's *current* state, unless we want to get really fancy with some kind of IPC. I suspect this would not play well with the current "longjmp" implementation of subshells.) 2. Extend all the commands that report on the shell's internal state analogously to printf: take a '-v VAR' argument to which they write what would normally be their output, so there's no need for a subshell, and therefore doubt about which shell they're reporting on. 3. Provide tracking variables so that it's not necessary to use commands at all. e.g. "${BASH_ULIMIT[core]}" would report the maximum size of core dump (and "${BASH_ULIMIT[hard-core]}" would report the maximum value that the former can be set to), while "${BASH_TRAP[HUP]}" would match the command string from trap -p HUP (and [[ -v BASH_TRAP[HUP] ]] would tell you whether its unset or just empty). 4. For "jobs" only, always report the viewpoint of the nearest shell that has functioning job control - the one that actually uses setpgrp(). "fg", "bg", and any other command used with a job-spec should recognize that they're in the "wrong shell" and complain rather than simply being silent. I wonder how "job control enabled" should be reported in subshells. A simple reading of POSIX suggests that $- must contain 'm' in subshells of a session shell that has job control enabled, even though they don't actually do job control themselves. Maybe there should be an 'M' in $- when job control is actually active (in the top level session shell). What do others think about this? - Martin