diff options
author | Ron Yorston <rmy@pobox.com> | 2024-09-04 12:47:03 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2024-09-04 12:47:03 +0100 |
commit | cbfa58d56c3ca59538bf23e30105ce27ed5ef948 (patch) | |
tree | 29c88182b7ff243931d5956121e23cd877112b16 | |
parent | 13a2b505b3fd7abcb4b4516d6745df870d7aee64 (diff) | |
download | busybox-w32-cbfa58d56c3ca59538bf23e30105ce27ed5ef948.tar.gz busybox-w32-cbfa58d56c3ca59538bf23e30105ce27ed5ef948.tar.bz2 busybox-w32-cbfa58d56c3ca59538bf23e30105ce27ed5ef948.zip |
ash: optimise running of scripts (2)
Commit 4b7b4a960 (ash: optimise running of scripts) avoided creation
of a process when running a script. There's another case where we
can do the same: if the script is being run from a FS_SHELLEXEC
shell.
- Check the necessary conditions for this to happen.
- Allocate two extra slots in the argv array for FS_SHELLEXEC.
- Set the index of the script file in the argv array. Without this
the test 'pidof this' failed because the command name hadn't been
correctly set.
Adds 80-96 bytes.
-rw-r--r-- | include/mingw.h | 1 | ||||
-rw-r--r-- | libbb/appletlib.c | 7 | ||||
-rw-r--r-- | shell/ash.c | 26 |
3 files changed, 26 insertions, 8 deletions
diff --git a/include/mingw.h b/include/mingw.h index ed7884e39..65940b40b 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -667,3 +667,4 @@ enum { | |||
667 | ADMIN_ENABLED = 2 | 667 | ADMIN_ENABLED = 2 |
668 | }; | 668 | }; |
669 | int elevation_state(void); | 669 | int elevation_state(void); |
670 | void set_interp(int i) FAST_FUNC; | ||
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 97dfb3df8..1ff7fe6c8 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -394,6 +394,13 @@ bool re_execed; | |||
394 | static int interp = 0; | 394 | static int interp = 0; |
395 | char bb_comm[COMM_LEN]; | 395 | char bb_comm[COMM_LEN]; |
396 | char bb_command_line[128]; | 396 | char bb_command_line[128]; |
397 | |||
398 | # if ENABLE_FEATURE_SH_STANDALONE | ||
399 | void FAST_FUNC set_interp(int i) | ||
400 | { | ||
401 | interp = i; | ||
402 | } | ||
403 | # endif | ||
397 | #endif | 404 | #endif |
398 | 405 | ||
399 | 406 | ||
diff --git a/shell/ash.c b/shell/ash.c index 2e4181b3f..d9a7bee83 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -9099,6 +9099,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c | |||
9099 | #endif | 9099 | #endif |
9100 | { | 9100 | { |
9101 | #if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE | 9101 | #if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE |
9102 | struct forkshell *fs = (struct forkshell *)sticky_mem_start; | ||
9102 | interp_t interp; | 9103 | interp_t interp; |
9103 | #endif | 9104 | #endif |
9104 | #if ENABLE_FEATURE_SH_STANDALONE | 9105 | #if ENABLE_FEATURE_SH_STANDALONE |
@@ -9106,7 +9107,6 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c | |||
9106 | # if ENABLE_PLATFORM_MINGW32 | 9107 | # if ENABLE_PLATFORM_MINGW32 |
9107 | /* Treat all applets as NOEXEC, including the shell itself if | 9108 | /* Treat all applets as NOEXEC, including the shell itself if |
9108 | * this is a FS_SHELLEXEC shell. */ | 9109 | * this is a FS_SHELLEXEC shell. */ |
9109 | struct forkshell *fs = (struct forkshell *)sticky_mem_start; | ||
9110 | if (applet_main[applet_no] != ash_main || | 9110 | if (applet_main[applet_no] != ash_main || |
9111 | (fs && fs->fpid == FS_SHELLEXEC)) { | 9111 | (fs && fs->fpid == FS_SHELLEXEC)) { |
9112 | run_noexec: | 9112 | run_noexec: |
@@ -9152,21 +9152,28 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c | |||
9152 | add_win32_extension((char *)cmd); | 9152 | add_win32_extension((char *)cmd); |
9153 | 9153 | ||
9154 | # if ENABLE_FEATURE_SH_STANDALONE | 9154 | # if ENABLE_FEATURE_SH_STANDALONE |
9155 | /* If nfpath is non-NULL, evalcommand() has determined this | 9155 | /* If nfpath is non-NULL evalcommand() has determined this |
9156 | * command doesn't need a fork(). If the command is a script | 9156 | * command doesn't need a fork(). Even it's NULL we can |
9157 | * with an interpreter which is an applet we can run it as if | 9157 | * possibly avoid a fork if this is a FS_SHELLEXEC shell. */ |
9158 | * it were a noexec applet. */ | 9158 | if (nfpath == NULL && (fs && fs->fpid == FS_SHELLEXEC)) |
9159 | nfpath = pathval(); | ||
9160 | |||
9161 | /* If nfpath is non-NULL and the command is a script with an | ||
9162 | * interpreter which is an applet, we can run it as if it | ||
9163 | * were a noexec applet. */ | ||
9159 | if (nfpath && parse_interpreter(cmd, &interp)) { | 9164 | if (nfpath && parse_interpreter(cmd, &interp)) { |
9160 | applet_no = find_applet_by_name_for_sh(interp.name, nfpath); | 9165 | applet_no = find_applet_by_name_for_sh(interp.name, nfpath); |
9161 | if (applet_no >= 0) { | 9166 | if (applet_no >= 0) { |
9162 | argv[0] = (char *)cmd; | 9167 | argv[0] = (char *)cmd; |
9163 | /* evalcommand() has added two elements before argv */ | 9168 | /* evalcommand()/spawn_forkshell() add two elements before argv */ |
9164 | if (interp.opts) { | 9169 | if (interp.opts) { |
9165 | argv--; | 9170 | argv--; |
9166 | argv[0] = (char *)interp.opts; | 9171 | argv[0] = (char *)interp.opts; |
9167 | } | 9172 | } |
9168 | argv--; | 9173 | argv--; |
9169 | cmd = argv[0] = (char *)interp.name; | 9174 | cmd = argv[0] = (char *)interp.name; |
9175 | /* Identify the index of the script file in argv */ | ||
9176 | set_interp(1 + (interp.opts != NULL)); | ||
9170 | goto run_noexec; | 9177 | goto run_noexec; |
9171 | } | 9178 | } |
9172 | } | 9179 | } |
@@ -16842,7 +16849,8 @@ argv_size(struct datasize ds, char **p) | |||
16842 | ds.funcstringsize += align_len(*p); | 16849 | ds.funcstringsize += align_len(*p); |
16843 | p++; | 16850 | p++; |
16844 | } | 16851 | } |
16845 | ds.funcblocksize += sizeof(char *); | 16852 | // Allow two extra elements for tryexec(). |
16853 | ds.funcblocksize += 3 * sizeof(char *); | ||
16846 | } | 16854 | } |
16847 | return ds; | 16855 | return ds; |
16848 | } | 16856 | } |
@@ -16856,6 +16864,8 @@ argv_copy(char **p) | |||
16856 | #endif | 16864 | #endif |
16857 | 16865 | ||
16858 | if (p) { | 16866 | if (p) { |
16867 | // Allow two extra elements for tryexec(). | ||
16868 | funcblock = (char *) funcblock + 2 * sizeof(char *); | ||
16859 | while (*p) { | 16869 | while (*p) { |
16860 | new = funcblock; | 16870 | new = funcblock; |
16861 | funcblock = (char *) funcblock + sizeof(char *); | 16871 | funcblock = (char *) funcblock + sizeof(char *); |
@@ -16866,7 +16876,7 @@ argv_copy(char **p) | |||
16866 | new = funcblock; | 16876 | new = funcblock; |
16867 | funcblock = (char *) funcblock + sizeof(char *); | 16877 | funcblock = (char *) funcblock + sizeof(char *); |
16868 | *new = NULL; | 16878 | *new = NULL; |
16869 | return start; | 16879 | return start + 2; |
16870 | } | 16880 | } |
16871 | return NULL; | 16881 | return NULL; |
16872 | } | 16882 | } |