ash: improve trap and jobs builtins in child shells

The trap and jobs builtins can be used to report information about
traps and jobs.  This works when they're called from the current
shell but in a child shell the required information is usually
cleared.  Special hacks allow:

- trap to work with command substitution;
- jobs to work with command substitution or in a pipeline.

Neither works with process substitution.

- Relax the test for the trap hack so it also supports pipelines.

- Pass the command to be evaluated to forkshell() in evalbackcmd()
  so trap and jobs both work with process substitution.

function                                             old     new   delta
forkchild                                            629     640     +11
argstr                                              1502    1496      -6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 11/-6)               Total: 5 bytes

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
master
Ron Yorston 2023-03-30 11:05:04 +01:00 committed by Denys Vlasenko
parent af5277f883
commit 098cd7ece4
3 changed files with 31 additions and 6 deletions

View File

@ -5190,8 +5190,7 @@ forkchild(struct job *jp, union node *n, int mode)
closescript();
if (mode == FORK_NOJOB /* is it `xxx` ? */
&& n && n->type == NCMD /* is it single cmd? */
if (n && n->type == NCMD /* is it single cmd? */
/* && n->ncmd.args->type == NARG - always true? */
&& n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
&& n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
@ -5285,10 +5284,12 @@ forkchild(struct job *jp, union node *n, int mode)
) {
TRACE(("Job hack\n"));
/* "jobs": we do not want to clear job list for it,
* instead we remove only _its_ own_ job from job list.
* instead we remove only _its_ own_ job from job list
* (if it has one).
* This makes "jobs .... | cat" more useful.
*/
freejob(curjob);
if (jp)
freejob(curjob);
return;
}
#endif
@ -6607,9 +6608,9 @@ evalbackcmd(union node *n, struct backcmd *result
if (pipe(pip) < 0)
ash_msg_and_raise_perror("can't create pipe");
/* process substitution uses NULL job/node, like openhere() */
/* process substitution uses NULL job, like openhere() */
jp = (ctl == CTLBACKQ) ? makejob(/*n,*/ 1) : NULL;
if (forkshell(jp, (ctl == CTLBACKQ) ? n : NULL, FORK_NOJOB) == 0) {
if (forkshell(jp, n, FORK_NOJOB) == 0) {
/* child */
FORCE_INT_ON;
close(pip[ip]);

View File

@ -6,6 +6,18 @@ trap -- 'a' INT
trap -- 'a' USR1
trap -- 'a' USR2
___
trap -- 'a' EXIT trap -- 'a' INT trap -- 'a' USR1 trap -- 'a' USR2
___
trap -- 'a' EXIT
trap -- 'a' INT
trap -- 'a' USR1
trap -- 'a' USR2
___
trap -- 'a' EXIT
trap -- 'a' INT
trap -- 'a' USR1
trap -- 'a' USR2
___
___
trap -- 'a' USR1
trap -- 'a' USR2

View File

@ -10,6 +10,18 @@ trap "a" EXIT INT USR1 USR2
echo ___
trap
# show them by command substitution
echo ___
echo $(trap)
# show them by pipe
echo ___
trap | cat
# show them by process substitution
echo ___
cat <(trap)
# clear one
echo ___
trap 0 INT