From 4f2ef4a836be37b25808c94f41c7c85895db6f93 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Nov 2018 09:53:25 +0100 Subject: ash: allow shell scripts to be embedded in the binary To assist in the deployment of shell scripts it may be convenient to embed them in the BusyBox binary. 'Embed scripts in the binary' takes any files in the directory 'embed', concatenates them with null separators, compresses them and embeds them in the binary. When scripts are embedded in the binary, scripts can be run as 'busybox SCRIPT [ARGS]' or by usual (sym)link mechanism. embed/nologin is provided as an example. function old new delta packed_scripts - 123 +123 unpack_scripts - 87 +87 ash_main 1103 1171 +68 run_applet_and_exit 78 128 +50 get_script_content - 32 +32 script_names - 10 +10 expmeta 663 659 -4 ------------------------------------------------------------------------------ (add/remove: 4/0 grow/shrink: 2/1 up/down: 370/-4) Total: 366 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- libbb/lineedit.c | 6 ++++ 2 files changed, 88 insertions(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 319bcc2..0872008 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -50,6 +50,16 @@ #include "usage_compressed.h" +#if ENABLE_ASH_EMBEDDED_SCRIPTS +# define DEFINE_script_names 1 +# include "embedded_scripts.h" +#else +# define NUM_SCRIPTS 0 +#endif +#if NUM_SCRIPTS > 0 +# include "bb_archive.h" +static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS }; +#endif /* "Do not compress usage text if uncompressed text is small * and we don't include bunzip2 code for other reasons" @@ -953,7 +963,71 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar } # endif /* NUM_APPLETS > 0 */ -# if ENABLE_BUSYBOX || NUM_APPLETS > 0 +# if NUM_SCRIPTS > 0 +static char * +unpack_scripts(void) +{ + char *outbuf = NULL; + bunzip_data *bd; + int i; + jmp_buf jmpbuf; + + /* Setup for I/O error handling via longjmp */ + i = setjmp(jmpbuf); + if (i == 0) { + i = start_bunzip(&jmpbuf, + &bd, + /* src_fd: */ -1, + /* inbuf: */ packed_scripts, + /* len: */ sizeof(packed_scripts) + ); + } + /* read_bunzip can longjmp and end up here with i != 0 + * on read data errors! Not trivial */ + if (i == 0) { + outbuf = xmalloc(UNPACKED_SCRIPTS_LENGTH); + read_bunzip(bd, outbuf, UNPACKED_SCRIPTS_LENGTH); + } + dealloc_bunzip(bd); + return outbuf; +} + +/* + * In standalone shell mode we sometimes want the index of the script + * and sometimes the index offset by NUM_APPLETS. + */ +static int +find_script_by_name(const char *arg) +{ + const char *s = script_names; + int i = 0; + + while (*s) { + if (strcmp(arg, s) == 0) + return i; + i++; + while (*s++ != '\0') + continue; + } + return -1; +} + +char* FAST_FUNC +get_script_content(unsigned n) +{ + char *t = unpack_scripts(); + if (t) { + while (n != 0) { + while (*t++ != '\0') + continue; + n--; + } + } + return t; +} +# endif /* NUM_SCRIPTS > 0 */ + +# if ENABLE_BUSYBOX || NUM_APPLETS > 0 || NUM_SCRIPTS > 0 static NORETURN void run_applet_and_exit(const char *name, char **argv) { # if ENABLE_BUSYBOX @@ -968,6 +1042,13 @@ static NORETURN void run_applet_and_exit(const char *name, char **argv) run_applet_no_and_exit(applet, name, argv); } # endif +# if NUM_SCRIPTS > 0 + { + int script = find_script_by_name(name); + if (script >= 0) + exit(ash_main(-script - 1, argv)); + } +# endif /*bb_error_msg_and_die("applet not found"); - links in printf */ full_write2_str(applet_name); diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b1e971f..aef1911 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -41,6 +41,12 @@ #include "busybox.h" #include "NUM_APPLETS.h" #include "unicode.h" +#if ENABLE_ASH_EMBEDDED_SCRIPTS +# include "embedded_scripts.h" +#else +# define NUM_SCRIPTS 0 +#endif + #ifndef _POSIX_VDISABLE # define _POSIX_VDISABLE '\0' #endif -- cgit v1.1