aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/Config.in17
-rw-r--r--shell/ash.c18
2 files changed, 35 insertions, 0 deletions
diff --git a/shell/Config.in b/shell/Config.in
index 40e0217f4..94ffa09f8 100644
--- a/shell/Config.in
+++ b/shell/Config.in
@@ -287,6 +287,23 @@ config FEATURE_SH_STANDALONE
# that exact location with that exact name, this option will not work at
# all.
+config FEATURE_SH_NOFORK
+ bool "Run 'nofork' applets directly"
+ default n
+ depends on (MSH || LASH || HUSH || ASH) && FEATURE_PREFER_APPLETS
+ help
+ This option causes busybox shells [currently only ash]
+ to not execute typical fork/exec/wait sequence, but call <applet>_main
+ directly, if possible. (Sometimes it is not possible: for example,
+ this is not possible in pipes).
+
+ This will be done only for some applets (those which are marked
+ NOFORK in include/applets.h).
+
+ This may significantly speed up some shell scripts.
+
+ This feature is relatively new. Use with care.
+
config CTTYHACK
bool "cttyhack"
default n
diff --git a/shell/ash.c b/shell/ash.c
index 0872e681a..cc61401d1 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8747,6 +8747,24 @@ evalcommand(union node *cmd, int flags)
/* Execute the command. */
switch (cmdentry.cmdtype) {
default:
+
+#if ENABLE_FEATURE_SH_NOFORK
+ {
+ /* TODO: don't rerun find_applet_by_name, find_command
+ * already did it. Make it save applet_no somewhere */
+ int applet_no = find_applet_by_name(argv[0]);
+ if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
+ struct nofork_save_area nofork_save;
+
+ listsetvar(varlist.list, VEXPORT|VSTACK);
+ save_nofork_data(&nofork_save);
+ /* run <applet>_main(), then restore nofork_save_area */
+ exitstatus = run_nofork_applet_prime(&nofork_save, applet_no, argv) & 0xff;
+ break;
+ }
+ }
+#endif
+
/* Fork off a child process if necessary. */
if (!(flags & EV_EXIT) || trap[0]) {
INT_OFF;