hush: allow hush to run embedded scripts
authorRon Yorston <rmy@pobox.com>
Tue, 27 Nov 2018 14:34:25 +0000 (14:34 +0000)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 27 Nov 2018 15:13:07 +0000 (16:13 +0100)
Embedded scripts require a shell to be present in the BusyBox
binary.  Allow either ash or hush to be used for this purpose.
If both are enabled ash takes precedence.

The size of the binary is unchanged in the default configuration:
both ash and hush are present but support for embedded scripts
isn't compiled into hush.

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
archival/libarchive/Kbuild.src
docs/embedded-scripts.txt
include/libbb.h
libbb/appletlib.c
scripts/embedded_scripts
scripts/gen_build_files.sh
shell/Config.src
shell/ash.c
shell/hush.c
util-linux/nologin.c

index 12e66a88b812f3bcd8acccfa8847d89762bcecc4..d2f284b08c4593265069a2d5441ac8b268f7a9cd 100644 (file)
@@ -91,7 +91,7 @@ lib-$(CONFIG_FEATURE_SEAMLESS_LZMA)     += open_transformer.o decompress_unlzma.
 lib-$(CONFIG_FEATURE_SEAMLESS_XZ)       += open_transformer.o decompress_unxz.o
 lib-$(CONFIG_FEATURE_COMPRESS_USAGE)    += open_transformer.o decompress_bunzip2.o
 lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o
-lib-$(CONFIG_ASH_EMBEDDED_SCRIPTS)      += open_transformer.o decompress_bunzip2.o
+lib-$(CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS) += open_transformer.o decompress_bunzip2.o
 
 ifneq ($(lib-y),)
 lib-y += $(COMMON_FILES)
index 1b0c5b5910590ea8fcc818af1e0928430cdecee7..7a273d698fa6e2091faf957c6ee5938c797e19f2 100644 (file)
@@ -3,13 +3,9 @@ Embedded Shell Scripts in BusyBox
 
 BusyBox allows applets to be implemented as shell scripts.  Since
 this obviously requires a shell to interpret the scripts the feature
-depends on having a shell (specifically, ash) built into the binary.
-Support for embedded scripts also has to be enabled.
-
-To embed scripts in BusyBox you must enable these configuration options:
-
-   ASH
-   ASH_EMBEDDED_SCRIPTS
+depends on having a shell built into the binary.  Either ash or hush
+will do.  If both are present ash will be used.  Support for embedded
+scripts also has to be enabled.
 
 It's unlikely that your applet will be implemented as a pure shell
 script:  it will probably need some external commands.  If these are
@@ -75,10 +71,9 @@ code for the native applet:
 
 The only difference is that the applet is specified as being of type
 APPLET_SCRIPTED.  It would also be useful to include details of any
-dependencies the script has.  We can assume that ash is available.
-No external commands are used by our mu script, but it does depend on
-optional shell features.  We can ensure these are selected by adding
-this to the configuration:
+dependencies the script has.  No external commands are used by our mu
+script, but it does depend on optional shell features.  We can ensure
+these are selected by adding this to the configuration:
 
 //config:config MU_DEPENDENCIES
 //config:      bool "Enable dependencies for mu"
@@ -87,8 +82,8 @@ this to the configuration:
 //config:      select ASH_RANDOM_SUPPORT
 //config:      select FEATURE_SH_MATH
 //config:      help
-//config:      mu is implemented as a shell script. It requires ash
-//config:      support for $RANDOM and arithmetic.
+//config:      mu is implemented as a shell script. It requires support
+//config:      for $RANDOM and arithmetic.
 
 The configuration data should be placed in a C file in an appropriate
 subdirectory.  There isn't any C code, though!  In this case the file
index ebd090e187e382a709f4ce384d44de868034a076..b560cc2ebf10ee0da64a713a0b0005261ce478e3 100644 (file)
@@ -1348,6 +1348,11 @@ int ash_main(int argc, char** argv)
                MAIN_EXTERNALLY_VISIBLE
 #endif
 ;
+int hush_main(int argc, char** argv)
+#if ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH
+               MAIN_EXTERNALLY_VISIBLE
+#endif
+;
 /* If shell needs them, they exist even if not enabled as applets */
 int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE);
 int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE);
index a79a37efb27dd81b93d7e750014d9ea81e3f1ed2..cd09b620cf7b4360da53379614835c10342ace95 100644 (file)
@@ -50,7 +50,7 @@
 
 #include "usage_compressed.h"
 
-#if ENABLE_ASH_EMBEDDED_SCRIPTS
+#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
 # define DEFINE_SCRIPT_DATA 1
 # include "embedded_scripts.h"
 #else
@@ -774,7 +774,13 @@ int scripted_main(int argc UNUSED_PARAM, char **argv)
 {
        int script = find_script_by_name(applet_name);
        if (script >= 0)
+#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH
                exit(ash_main(-script - 1, argv));
+#elif ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH
+               exit(hush_main(-script - 1, argv));
+#else
+               return 1;
+#endif
        return 0;
 }
 
index 86ad44d1d68d451547edc567114cc0ccbf6ad00b..aa7bf3e8a1924d7ecc85d6228bdfb1e2d0b2ec4e 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/sh
 
+. ./.config || exit 1
+
 target="$1"
 custom_loc="$2"
 applet_loc="$3"
@@ -8,6 +10,12 @@ test "$target" || exit 1
 test "$SED" || SED=sed
 test "$DD" || DD=dd
 
+if [ x"$CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS" != x"y" ]
+then
+       printf '#define NUM_SCRIPTS 0\n' >"$target"
+       exit 0
+fi
+
 # Some people were bitten by their system lacking a (proper) od
 od -v -b </dev/null >/dev/null
 if test $? != 0; then
index 362632df3c1ae0e0f920b4b25ef4b2129d8a3291..92de681ac17125f630675b2bff09fcb86ed1d437 100755 (executable)
@@ -25,7 +25,7 @@ custom_scripts()
        then
                for i in $(cd "$custom_loc"; ls * 2>/dev/null)
                do
-                       printf "APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, scripted)\n" $i;
+                       printf "IF_FEATURE_SH_EMBEDDED_SCRIPTS(APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, scripted))\n" $i;
                done
        fi
 }
index 959d3cb42dfc8ffa3e9f5e2541ff82d4d9ce7cf9..bc7218fe58a95f1ab36f594bac78e36ae8c96e27 100644 (file)
@@ -161,6 +161,20 @@ config FEATURE_SH_HISTFILESIZE
        to set shell history size. Note that its max value is capped
        by "History size" setting in library tuning section.
 
+config FEATURE_SH_EMBEDDED_SCRIPTS
+       bool "Embed scripts in the binary"
+       default y
+       depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH
+       help
+       Allow scripts to be compressed and embedded in the busybox
+       binary. The scripts should be placed in the 'embed' directory
+       at build time. Like applets, scripts can be run as
+       'busybox SCRIPT ...' or by linking their name to the binary.
+
+       This also allows applets to be implemented as scripts: place
+       the script in 'applets_sh' and a stub C file containing
+       configuration in the appropriate subsystem directory.
+
 endif # Options common to all shells
 
 endmenu
index 04e4006c89d4b0a1b6680eb6e7d1a63090c0927d..9ce1d1a76decf77c9371082430182d577884cb0d 100644 (file)
 //config:      you to run the specified command or builtin,
 //config:      even when there is a function with the same name.
 //config:
-//config:config ASH_EMBEDDED_SCRIPTS
-//config:      bool "Embed scripts in the binary"
-//config:      default y
-//config:      depends on ASH || SH_IS_ASH || BASH_IS_ASH
-//config:      help
-//config:      Allow scripts to be compressed and embedded in the busybox
-//config:      binary. The scripts should be placed in the 'embed' directory
-//config:      at build time. Like applets, scripts can be run as
-//config:      'busybox SCRIPT ...' or by linking their name to the binary.
-//config:
-//config:      This also allows applets to be implemented as scripts: place
-//config:      the script in 'applets_sh' and a stub C file containing
-//config:      configuration in the appropriate subsystem directory.
-//config:
 //config:endif # ash options
 
 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
 #include <sys/times.h>
 #include <sys/utsname.h> /* for setting $HOSTNAME */
 #include "busybox.h" /* for applet_names */
-#if ENABLE_ASH_EMBEDDED_SCRIPTS
+#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
 # include "embedded_scripts.h"
 #else
 # define NUM_SCRIPTS 0
index 431010f095ec55df83adceb6f54007baef20b04d..90191408d69062e9a2aa67678ad3402add7322fa 100644 (file)
 # define PIPE_BUF 4096  /* amount of buffering in a pipe */
 #endif
 
+#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH)
+# include "embedded_scripts.h"
+#else
+# define NUM_SCRIPTS 0
+#endif
 
 /* So far, all bash compat is controlled by one config option */
 /* Separate defines document which part of code implements what */
@@ -9951,6 +9956,14 @@ int hush_main(int argc, char **argv)
        /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
        flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
        builtin_argc = 0;
+#if NUM_SCRIPTS > 0
+       if (argc < 0) {
+               optarg = get_script_content(-argc - 1);
+               optind = 0;
+               argc = string_array_len(argv);
+               goto run_script;
+       }
+#endif
        while (1) {
                int opt = getopt(argc, argv, "+c:exinsl"
 #if !BB_MMU
@@ -9974,6 +9987,9 @@ int hush_main(int argc, char **argv)
                         * Note: the form without ARG0 never happens:
                         * sh ... -c 'builtin' BARGV... ""
                         */
+#if NUM_SCRIPTS > 0
+ run_script:
+#endif
                        if (!G.root_pid) {
                                G.root_pid = getpid();
                                G.root_ppid = getppid();
index 0982fff3dfd969d7e9868f3b01522471c65fdc57..5e5e423052a86bc533e5a822993054a192a387ad 100644 (file)
@@ -1,7 +1,7 @@
 //config:config NOLOGIN
 //config:      bool "nologin"
 //config:      default y
-//config:      depends on ASH_EMBEDDED_SCRIPTS
+//config:      depends on FEATURE_SH_EMBEDDED_SCRIPTS
 //config:      help
 //config:      Politely refuse a login
 //config: