diff options
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/shell/ash.c b/shell/ash.c index 16a331bb0..4e80b097c 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -9623,12 +9623,14 @@ evalcommand(union node *cmd, int flags) | |||
9623 | 9623 | ||
9624 | /* Execute the command. */ | 9624 | /* Execute the command. */ |
9625 | switch (cmdentry.cmdtype) { | 9625 | switch (cmdentry.cmdtype) { |
9626 | default: | 9626 | default: { |
9627 | 9627 | ||
9628 | #if ENABLE_FEATURE_SH_NOFORK | 9628 | #if ENABLE_FEATURE_SH_NOFORK |
9629 | /* Hmmm... shouldn't it happen somewhere in forkshell() instead? | 9629 | /* (1) BUG: if variables are set, we need to fork, or save/restore them |
9630 | * Why "fork off a child process if necessary" doesn't apply to NOFORK? */ | 9630 | * around run_nofork_applet() call. |
9631 | { | 9631 | * (2) Should this check also be done in forkshell()? |
9632 | * (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...) | ||
9633 | */ | ||
9632 | /* find_command() encodes applet_no as (-2 - applet_no) */ | 9634 | /* find_command() encodes applet_no as (-2 - applet_no) */ |
9633 | int applet_no = (- cmdentry.u.index - 2); | 9635 | int applet_no = (- cmdentry.u.index - 2); |
9634 | if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { | 9636 | if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { |
@@ -9637,10 +9639,14 @@ evalcommand(union node *cmd, int flags) | |||
9637 | exitstatus = run_nofork_applet(applet_no, argv); | 9639 | exitstatus = run_nofork_applet(applet_no, argv); |
9638 | break; | 9640 | break; |
9639 | } | 9641 | } |
9640 | } | ||
9641 | #endif | 9642 | #endif |
9643 | /* Can we avoid forking off? For example, very last command | ||
9644 | * in a script or a subshell does not need forking, | ||
9645 | * we can just exec it. | ||
9646 | */ | ||
9642 | #if ENABLE_PLATFORM_MINGW32 | 9647 | #if ENABLE_PLATFORM_MINGW32 |
9643 | if (!(flags & EV_EXIT) || trap[0]) { | 9648 | if (!(flags & EV_EXIT) || trap[0]) { |
9649 | /* No, forking off a child is necessary */ | ||
9644 | struct forkshell fs; | 9650 | struct forkshell fs; |
9645 | 9651 | ||
9646 | memset(&fs, 0, sizeof(fs)); | 9652 | memset(&fs, 0, sizeof(fs)); |
@@ -9659,8 +9665,8 @@ evalcommand(union node *cmd, int flags) | |||
9659 | } | 9665 | } |
9660 | /* goes through to shellexec() */ | 9666 | /* goes through to shellexec() */ |
9661 | #endif | 9667 | #endif |
9662 | /* Fork off a child process if necessary. */ | ||
9663 | if (!(flags & EV_EXIT) || may_have_traps) { | 9668 | if (!(flags & EV_EXIT) || may_have_traps) { |
9669 | /* No, forking off a child is necessary */ | ||
9664 | INT_OFF; | 9670 | INT_OFF; |
9665 | jp = makejob(/*cmd,*/ 1); | 9671 | jp = makejob(/*cmd,*/ 1); |
9666 | if (forkshell(jp, cmd, FORK_FG) != 0) { | 9672 | if (forkshell(jp, cmd, FORK_FG) != 0) { |
@@ -9677,7 +9683,7 @@ evalcommand(union node *cmd, int flags) | |||
9677 | listsetvar(varlist.list, VEXPORT|VSTACK); | 9683 | listsetvar(varlist.list, VEXPORT|VSTACK); |
9678 | shellexec(argv, path, cmdentry.u.index); | 9684 | shellexec(argv, path, cmdentry.u.index); |
9679 | /* NOTREACHED */ | 9685 | /* NOTREACHED */ |
9680 | 9686 | } /* default */ | |
9681 | case CMDBUILTIN: | 9687 | case CMDBUILTIN: |
9682 | cmdenviron = varlist.list; | 9688 | cmdenviron = varlist.list; |
9683 | if (cmdenviron) { | 9689 | if (cmdenviron) { |
@@ -9722,7 +9728,8 @@ evalcommand(union node *cmd, int flags) | |||
9722 | if (evalfun(cmdentry.u.func, argc, argv, flags)) | 9728 | if (evalfun(cmdentry.u.func, argc, argv, flags)) |
9723 | goto raise; | 9729 | goto raise; |
9724 | break; | 9730 | break; |
9725 | } | 9731 | |
9732 | } /* switch */ | ||
9726 | 9733 | ||
9727 | out: | 9734 | out: |
9728 | popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec); | 9735 | popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec); |