summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-03-30 11:05:04 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2023-03-31 14:22:56 +0200
commit098cd7ece44bf7ab7ae38dc00dd574af79a9bad8 (patch)
treeaf16f7162dc6a5bbcea8277528476859325d4cb7
parentaf5277f883e8fc2e0236aa9ecc5115ecaffd0ccb (diff)
downloadbusybox-098cd7ece44bf7ab7ae38dc00dd574af79a9bad8.tar.gz
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>
-rw-r--r--shell/ash.c13
-rw-r--r--shell/ash_test/ash-signals/usage.right12
-rwxr-xr-xshell/ash_test/ash-signals/usage.tests12
3 files changed, 31 insertions, 6 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 559566b58..40b921be1 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -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]);
diff --git a/shell/ash_test/ash-signals/usage.right b/shell/ash_test/ash-signals/usage.right
index c0dbd6c3c..df1ed2dd7 100644
--- a/shell/ash_test/ash-signals/usage.right
+++ b/shell/ash_test/ash-signals/usage.right
@@ -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
diff --git a/shell/ash_test/ash-signals/usage.tests b/shell/ash_test/ash-signals/usage.tests
index d29c6e74a..34e24cceb 100755
--- a/shell/ash_test/ash-signals/usage.tests
+++ b/shell/ash_test/ash-signals/usage.tests
@@ -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