From 3db4e7f84cf795de8559ea0d96eaa491999ccf24 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Fri, 19 Oct 2018 15:25:41 +0200 Subject: printf: fix printing +-prefixed numbers Thanks to Cristian Ionescu-Idbohrn for noticing. Also fix "%d" ' 42' to skip leading whitespace. function old new delta print_direc 435 454 +19 bb_strtoll 99 103 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 23/0) Total: 23 bytes Signed-off-by: Bernhard Reutner-Fischer --- libbb/bb_strtonum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/bb_strtonum.c b/libbb/bb_strtonum.c index 2185017b0..cb70f1053 100644 --- a/libbb/bb_strtonum.c +++ b/libbb/bb_strtonum.c @@ -81,7 +81,7 @@ long long FAST_FUNC bb_strtoll(const char *arg, char **endp, int base) /* Check for the weird "feature": * a "-" string is apparently a valid "number" for strto[u]l[l]! * It returns zero and errno is 0! :( */ - first = (arg[0] != '-' ? arg[0] : arg[1]); + first = (arg[0] != '-' && arg[0] != '+' ? arg[0] : arg[1]); if (!isalnum(first)) return ret_ERANGE(); errno = 0; -- cgit v1.2.3-55-g6feb From 93ef5dd640ef41edc72c80fa59c7cc9427b5945b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Oct 2018 23:24:18 +0100 Subject: printf: fix printf "%u\n" +18446744073709551614 function old new delta conv_strtoll 19 32 +13 conv_strtoull 49 61 +12 bb_strtoll 89 84 -5 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 25/-5) Total: 20 bytes Signed-off-by: Denys Vlasenko --- coreutils/printf.c | 8 ++++++++ libbb/bb_strtonum.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'libbb') diff --git a/coreutils/printf.c b/coreutils/printf.c index b2429c5cf..67d3b2eda 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -95,6 +95,12 @@ static int multiconvert(const char *arg, void *result, converter convert) static void FAST_FUNC conv_strtoull(const char *arg, void *result) { + /* Allow leading '+' - bb_strtoull() by itself does not allow it, + * and probably shouldn't (other callers might require purely numeric + * inputs to be allowed. + */ + if (arg[0] == '+') + arg++; *(unsigned long long*)result = bb_strtoull(arg, NULL, 0); /* both coreutils 6.10 and bash 3.2: * $ printf '%x\n' -2 @@ -107,6 +113,8 @@ static void FAST_FUNC conv_strtoull(const char *arg, void *result) } static void FAST_FUNC conv_strtoll(const char *arg, void *result) { + if (arg[0] == '+') + arg++; *(long long*)result = bb_strtoll(arg, NULL, 0); } static void FAST_FUNC conv_strtod(const char *arg, void *result) diff --git a/libbb/bb_strtonum.c b/libbb/bb_strtonum.c index cb70f1053..2185017b0 100644 --- a/libbb/bb_strtonum.c +++ b/libbb/bb_strtonum.c @@ -81,7 +81,7 @@ long long FAST_FUNC bb_strtoll(const char *arg, char **endp, int base) /* Check for the weird "feature": * a "-" string is apparently a valid "number" for strto[u]l[l]! * It returns zero and errno is 0! :( */ - first = (arg[0] != '-' && arg[0] != '+' ? arg[0] : arg[1]); + first = (arg[0] != '-' ? arg[0] : arg[1]); if (!isalnum(first)) return ret_ERANGE(); errno = 0; -- cgit v1.2.3-55-g6feb From 571e525a141a2de87b9c2ced485745e96418d921 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 12 Sep 2018 16:06:36 +0200 Subject: libbb: optionally honour libc provided SIGRTMIN/SIGRTMAX in get_signum() When an application documents that it responds such and such to SIGRTMIN+n, that almost always means with respect to the libc-provided SIGRTMIN. Hence I disagree with the "more correct" in commit 7b276fc17594. In any case, this is rather unfortunate: 36 34 (the first shell is bash). We probably can't change default behaviour after 7 years, but at least we can provide a config option. We avoid a little code generation (repeated calls to __libc_current_sigrtmin) by stashing SIGRTMIN/SIGRTMAX in local variables, but it does cost ~50 bytes. The next patch serves as penance for that. Signed-off-by: Rasmus Villemoes Signed-off-by: Denys Vlasenko --- libbb/u_signal_names.c | 76 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 23 deletions(-) (limited to 'libbb') diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c index b3038e32d..866ca85fd 100644 --- a/libbb/u_signal_names.c +++ b/libbb/u_signal_names.c @@ -12,6 +12,18 @@ //config: help //config: Support RTMIN[+n] and RTMAX[-n] signal names //config: in kill, killall etc. This costs ~250 bytes. +//config: +//config:config FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS +//config: bool "Use the definitions of SIGRTMIN/SIGRTMAX provided by libc" +//config: default y +//config: depends on FEATURE_RTMINMAX +//config: help +//config: Some C libraries reserve a few real-time signals for internal +//config: use, and adjust the values of SIGRTMIN/SIGRTMAX seen by +//config: applications accordingly. Saying yes here means that a signal +//config: name RTMIN+n will be interpreted according to the libc definition +//config: of SIGRTMIN, and not the raw definition provided by the kernel. +//config: This behavior matches "kill -l RTMIN+n" from bash. #include "libbb.h" @@ -123,7 +135,7 @@ static const char signals[][7] ALIGN1 = { #ifdef SIGSYS [SIGSYS ] = "SYS", #endif -#if ENABLE_FEATURE_RTMINMAX +#if ENABLE_FEATURE_RTMINMAX && !ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS # ifdef __SIGRTMIN [__SIGRTMIN] = "RTMIN", # endif @@ -168,36 +180,46 @@ int FAST_FUNC get_signum(const char *name) # endif #endif -#if ENABLE_FEATURE_RTMINMAX -# if defined(SIGRTMIN) && defined(SIGRTMAX) -/* libc may use some rt sigs for pthreads and therefore "remap" SIGRTMIN/MAX, - * but we want to use "raw" SIGRTMIN/MAX. Underscored names, if exist, provide - * them. If they don't exist, fall back to non-underscored ones: */ +#if ENABLE_FEATURE_RTMINMAX && defined(SIGRTMIN) && defined(SIGRTMAX) + { +# if ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS + /* Use the libc provided values. */ + unsigned sigrtmin = SIGRTMIN; + unsigned sigrtmax = SIGRTMAX; +# else + /* Use the "raw" SIGRTMIN/MAX. Underscored names, if exist, provide + * them. If they don't exist, fall back to non-underscored ones: */ # if !defined(__SIGRTMIN) # define __SIGRTMIN SIGRTMIN # endif # if !defined(__SIGRTMAX) # define __SIGRTMAX SIGRTMAX # endif - if (strncasecmp(name, "RTMIN", 5) == 0) { - if (!name[5]) - return __SIGRTMIN; - if (name[5] == '+') { - i = bb_strtou(name + 6, NULL, 10); - if (!errno && i <= __SIGRTMAX - __SIGRTMIN) - return __SIGRTMIN + i; + +# define sigrtmin __SIGRTMIN +# define sigrtmax __SIGRTMAX +# endif + if (strncasecmp(name, "RTMIN", 5) == 0) { + if (!name[5]) + return sigrtmin; + if (name[5] == '+') { + i = bb_strtou(name + 6, NULL, 10); + if (!errno && i <= sigrtmax - sigrtmin) + return sigrtmin + i; + } } - } - else if (strncasecmp(name, "RTMAX", 5) == 0) { - if (!name[5]) - return __SIGRTMAX; - if (name[5] == '-') { - i = bb_strtou(name + 6, NULL, 10); - if (!errno && i <= __SIGRTMAX - __SIGRTMIN) - return __SIGRTMAX - i; + else if (strncasecmp(name, "RTMAX", 5) == 0) { + if (!name[5]) + return sigrtmax; + if (name[5] == '-') { + i = bb_strtou(name + 6, NULL, 10); + if (!errno && i <= sigrtmax - sigrtmin) + return sigrtmax - i; + } } +# undef sigrtmin +# undef sigrtmax } -# endif #endif return -1; @@ -228,8 +250,16 @@ void FAST_FUNC print_signames(void) printf("%2u) %s\n", signo, name); } #if ENABLE_FEATURE_RTMINMAX -# ifdef __SIGRTMAX +# if ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS +# if defined(SIGRTMIN) && defined(SIGRTMAX) + printf("%2u) %s\n", SIGRTMIN, "RTMIN"); + printf("%2u) %s\n", SIGRTMAX, "RTMAX"); +# endif +# else +// __SIGRTMIN is included in signals[] array. +# ifdef __SIGRTMAX printf("%2u) %s\n", __SIGRTMAX, "RTMAX"); +# endif # endif #endif } -- cgit v1.2.3-55-g6feb From 656ca7bdd992f6aabbdd5cadbac5241f6e1971a1 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 12 Sep 2018 16:06:37 +0200 Subject: libbb/u_signal_names.c: don't check errno after bb_strtou Since we're comparing the return value to a smallish integer anyway, we might as well use that bb_strtou() returns UINT_MAX for malformed input. Referencing errno is kinda bloaty on glibc. While NSIG is not in POSIX, we do already rely on it being defined, compile-time const and smallish, since arrays in struct globals_misc are defined in terms of it. function old new delta get_signum 312 286 -26 Signed-off-by: Rasmus Villemoes Signed-off-by: Denys Vlasenko --- libbb/u_signal_names.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'libbb') diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c index 866ca85fd..f7d598c7a 100644 --- a/libbb/u_signal_names.c +++ b/libbb/u_signal_names.c @@ -153,8 +153,12 @@ int FAST_FUNC get_signum(const char *name) { unsigned i; + /* bb_strtou returns UINT_MAX on error. NSIG is smaller + * than UINT_MAX on any sane Unix. Hence no need + * to check errno after bb_strtou(). + */ i = bb_strtou(name, NULL, 10); - if (!errno && i < NSIG) /* for shells, we allow 0 too */ + if (i < NSIG) /* for shells, we allow 0 too */ return i; if (strncasecmp(name, "SIG", 3) == 0) name += 3; @@ -204,7 +208,7 @@ int FAST_FUNC get_signum(const char *name) return sigrtmin; if (name[5] == '+') { i = bb_strtou(name + 6, NULL, 10); - if (!errno && i <= sigrtmax - sigrtmin) + if (i <= sigrtmax - sigrtmin) return sigrtmin + i; } } @@ -213,7 +217,7 @@ int FAST_FUNC get_signum(const char *name) return sigrtmax; if (name[5] == '-') { i = bb_strtou(name + 6, NULL, 10); - if (!errno && i <= sigrtmax - sigrtmin) + if (i <= sigrtmax - sigrtmin) return sigrtmax - i; } } -- cgit v1.2.3-55-g6feb 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 --- Makefile | 6 ++- applets_sh/nologin | 4 -- archival/libarchive/Kbuild.src | 1 + embed/nologin | 4 ++ include/.gitignore | 1 + include/libbb.h | 8 ++++ libbb/appletlib.c | 83 +++++++++++++++++++++++++++++++++++++++++- libbb/lineedit.c | 6 +++ scripts/embedded_scripts | 66 +++++++++++++++++++++++++++++++++ shell/ash.c | 33 ++++++++++++++++- 10 files changed, 205 insertions(+), 7 deletions(-) delete mode 100755 applets_sh/nologin create mode 100755 embed/nologin create mode 100755 scripts/embedded_scripts (limited to 'libbb') diff --git a/Makefile b/Makefile index 59ec83a6a..8a0dbdf49 100644 --- a/Makefile +++ b/Makefile @@ -850,11 +850,14 @@ quiet_cmd_gen_common_bufsiz = GEN include/common_bufsiz.h cmd_gen_common_bufsiz = $(srctree)/scripts/generate_BUFSIZ.sh include/common_bufsiz.h quiet_cmd_split_autoconf = SPLIT include/autoconf.h -> include/config/* cmd_split_autoconf = scripts/basic/split-include include/autoconf.h include/config +quiet_cmd_gen_embedded_scripts = GEN include/embedded_scripts.h + cmd_gen_embedded_scripts = scripts/embedded_scripts include/embedded_scripts.h embed #bbox# piggybacked generation of few .h files -include/config/MARKER: scripts/basic/split-include include/autoconf.h +include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard embed/*) scripts/embedded_scripts $(call cmd,split_autoconf) $(call cmd,gen_bbconfigopts) $(call cmd,gen_common_bufsiz) + $(call cmd,gen_embedded_scripts) @touch $@ # Generate some files @@ -974,6 +977,7 @@ MRPROPER_FILES += .config .config.old include/asm .version .old_version \ include/autoconf.h \ include/bbconfigopts.h \ include/bbconfigopts_bz2.h \ + include/embedded_scripts.h \ include/usage_compressed.h \ include/applet_tables.h \ include/applets.h \ diff --git a/applets_sh/nologin b/applets_sh/nologin deleted file mode 100755 index 3768eaaa7..000000000 --- a/applets_sh/nologin +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -cat /etc/nologin.txt 2>/dev/null || echo "This account is not available" -sleep 5 -exit 1 diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index e1a8a7529..12e66a88b 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src @@ -91,6 +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 ifneq ($(lib-y),) lib-y += $(COMMON_FILES) diff --git a/embed/nologin b/embed/nologin new file mode 100755 index 000000000..3768eaaa7 --- /dev/null +++ b/embed/nologin @@ -0,0 +1,4 @@ +#!/bin/sh +cat /etc/nologin.txt 2>/dev/null || echo "This account is not available" +sleep 5 +exit 1 diff --git a/include/.gitignore b/include/.gitignore index 75afff9ca..13a96e018 100644 --- a/include/.gitignore +++ b/include/.gitignore @@ -5,6 +5,7 @@ /autoconf.h /bbconfigopts_bz2.h /bbconfigopts.h +/embedded_scripts.h /NUM_APPLETS.h /usage_compressed.h /usage.h diff --git a/include/libbb.h b/include/libbb.h index 140404ff5..affff5874 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1321,9 +1321,17 @@ void bb_logenv_override(void) FAST_FUNC; #define MAIN_EXTERNALLY_VISIBLE #endif +/* Embedded script support */ +//int find_script_by_name(const char *arg IF_FEATURE_SH_STANDALONE(, int offset)) FAST_FUNC; +char *get_script_content(unsigned n) FAST_FUNC; /* Applets which are useful from another applets */ int bb_cat(char** argv) FAST_FUNC; +int ash_main(int argc, char** argv) +#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH + 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); diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 319bcc263..08720082e 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 b1e971f88..aef1911d9 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 diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts new file mode 100755 index 000000000..986e85160 --- /dev/null +++ b/scripts/embedded_scripts @@ -0,0 +1,66 @@ +#!/bin/sh + +target="$1" +loc="$2" + +test "$target" || exit 1 +test "$SED" || SED=sed +test "$DD" || DD=dd + +# Some people were bitten by their system lacking a (proper) od +od -v -b /dev/null +if test $? != 0; then + echo 'od tool is not installed or cannot accept "-v -b" options' + exit 1 +fi + +exec >"$target.$$" + +scripts="" +if [ -d "$loc" ] +then + scripts=$(cd $loc; ls * 2>/dev/null) +fi + +n=$(echo $scripts | wc -w) + +if [ $n -ne 0 ] +then + printf '#ifdef DEFINE_script_names\n' + printf 'const char script_names[] ALIGN1 = ' + for i in $scripts + do + printf '"%s\\0"' $i + done + printf '"\\0";\n' + printf '#else\n' + printf 'extern const char script_names[] ALIGN1;\n' + printf '#endif\n' +fi +printf "#define NUM_SCRIPTS $n\n\n" + +if [ $n -ne 0 ] +then + printf '#define UNPACKED_SCRIPTS_LENGTH ' + for i in $scripts + do + cat $loc/$i + printf '\000' + done | wc -c + + printf '#define PACKED_SCRIPTS \\\n' + for i in $scripts + do + cat $loc/$i + printf '\000' + done | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | od -v -b \ + | grep -v '^ ' \ + | $SED -e 's/^[^ ]*//' \ + -e 's/ //g' \ + -e '/^$/d' \ + -e 's/\(...\)/0\1,/g' \ + -e 's/$/ \\/' + printf '\n' +fi + +mv -- "$target.$$" "$target" diff --git a/shell/ash.c b/shell/ash.c index dc1a55a6b..25468d796 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -148,6 +148,21 @@ //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. In standalone shell mode such scripts can be +//config: run directly and are subject to tab completion; otherwise they +//config: can be run by giving their name as an argument to the shell. +//config: For convenience shell aliases are created. The '-L' shell +//config: argument lists the names of the scripts. Like applets scripts +//config: can be run as 'busybox name ...' or by linking their name to +//config: the binary. +//config: //config:endif # ash options //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) @@ -181,6 +196,11 @@ #include #include /* for setting $HOSTNAME */ #include "busybox.h" /* for applet_names */ +#if ENABLE_ASH_EMBEDDED_SCRIPTS +# 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 */ @@ -14021,13 +14041,17 @@ procargs(char **argv) int login_sh; xargv = argv; +#if NUM_SCRIPTS > 0 + if (minusc) + goto setarg0; +#endif login_sh = xargv[0] && xargv[0][0] == '-'; arg0 = xargv[0]; /* if (xargv[0]) - mmm, this is always true! */ xargv++; + argptr = xargv; for (i = 0; i < NOPTS; i++) optlist[i] = 2; - argptr = xargv; if (options(/*cmdline:*/ 1, &login_sh)) { /* it already printed err message */ raise_exception(EXERROR); @@ -14130,6 +14154,7 @@ extern int etext(); */ int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int ash_main(int argc UNUSED_PARAM, char **argv) +/* note: 'argc' is used only if embedded scripts are enabled */ { volatile smallint state; struct jmploc jmploc; @@ -14183,6 +14208,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv) init(); setstackmark(&smark); + +#if NUM_SCRIPTS > 0 + if (argc < 0) + /* Non-NULL minusc tells procargs that an embedded script is being run */ + minusc = get_script_content(-argc - 1); +#endif login_sh = procargs(argv); #if DEBUG TRACE(("Shell args: ")); -- cgit v1.2.3-55-g6feb From aa2959c90d9c3217ddb6f482b82fef7234ad9bde Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Nov 2018 10:28:04 +0100 Subject: claenups for previous commit Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 36 ++++++++++++++++-------------------- shell/ash.c | 11 +++-------- 2 files changed, 19 insertions(+), 28 deletions(-) (limited to 'libbb') diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 08720082e..4e6d1c3d6 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -964,6 +964,22 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar # endif /* NUM_APPLETS > 0 */ # if NUM_SCRIPTS > 0 +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; +} + static char * unpack_scripts(void) { @@ -992,26 +1008,6 @@ unpack_scripts(void) 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) { diff --git a/shell/ash.c b/shell/ash.c index 25468d796..3adb6d0d2 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -153,15 +153,10 @@ //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: 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. In standalone shell mode such scripts can be -//config: run directly and are subject to tab completion; otherwise they -//config: can be run by giving their name as an argument to the shell. -//config: For convenience shell aliases are created. The '-L' shell -//config: argument lists the names of the scripts. Like applets scripts -//config: can be run as 'busybox name ...' or by linking their name to -//config: the binary. +//config: at build time. Like applets, scripts can be run as +//config: 'busybox SCRIPT ...' or by linking their name to the binary. //config: //config:endif # ash options -- cgit v1.2.3-55-g6feb From 151de441e7a19ce3afba0c59b083240a801222cf Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 1 Nov 2018 11:04:47 +0100 Subject: ash: recognize embedded scripts in SH_STANDALONE mode function old new delta find_script_by_name - 51 +51 shellexec 254 271 +17 find_command 990 1007 +17 evalcommand 1653 1661 +8 doCommands 2233 2222 -11 run_applet_and_exit 128 100 -28 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 6/4 up/down: 104/-52) Total: 52 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- libbb/appletlib.c | 8 ++++---- shell/ash.c | 12 ++++++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index affff5874..a32608ebd 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1322,7 +1322,7 @@ void bb_logenv_override(void) FAST_FUNC; #endif /* Embedded script support */ -//int find_script_by_name(const char *arg IF_FEATURE_SH_STANDALONE(, int offset)) FAST_FUNC; +int find_script_by_name(const char *name) FAST_FUNC; char *get_script_content(unsigned n) FAST_FUNC; /* Applets which are useful from another applets */ diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 4e6d1c3d6..92d99fbe8 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -964,20 +964,20 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar # endif /* NUM_APPLETS > 0 */ # if NUM_SCRIPTS > 0 -static int -find_script_by_name(const char *arg) +int FAST_FUNC +find_script_by_name(const char *name) { const char *s = script_names; int i = 0; while (*s) { - if (strcmp(arg, s) == 0) + if (strcmp(name, s) == 0) return i; i++; while (*s++ != '\0') continue; } - return -1; + return -0x10000; /* make it so that NUM_APPLETS + is still < 0 */ } static char * diff --git a/shell/ash.c b/shell/ash.c index 3adb6d0d2..58ecf6d2c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8085,6 +8085,9 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) if (strchr(prog, '/') != NULL #if ENABLE_FEATURE_SH_STANDALONE || (applet_no = find_applet_by_name(prog)) >= 0 +# if NUM_SCRIPTS > 0 + || (applet_no = NUM_APPLETS + find_script_by_name(prog)) >= 0 +# endif #endif ) { tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); @@ -10186,6 +10189,10 @@ evalcommand(union node *cmd, int flags) */ /* find_command() encodes applet_no as (-2 - applet_no) */ int applet_no = (- cmdentry.u.index - 2); +# if NUM_SCRIPTS > 0 + /* Applets are ok, but not embedded scripts */ + if (applet_no < NUM_APPLETS) +# endif if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { char **sv_environ; @@ -13368,6 +13375,11 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) #if ENABLE_FEATURE_SH_STANDALONE { int applet_no = find_applet_by_name(name); +# if NUM_SCRIPTS > 0 + if (applet_no < 0) + /* embedded script indices are offset by NUM_APPLETS */ + applet_no = NUM_APPLETS + find_script_by_name(name); +# endif if (applet_no >= 0) { entry->cmdtype = CMDNORMAL; entry->u.index = -2 - applet_no; -- cgit v1.2.3-55-g6feb From c9e161277eae5d2af39704e220ca5652e69bc428 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 1 Nov 2018 12:51:10 +0100 Subject: lineedit: autocompletion for embedded scripts function old new delta complete_cmd_dir_file 811 826 +15 Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'libbb') diff --git a/libbb/lineedit.c b/libbb/lineedit.c index aef1911d9..618e7c221 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -812,14 +812,20 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) } pf_len = strlen(pfind); -# if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 +# if ENABLE_FEATURE_SH_STANDALONE && (NUM_APPLETS != 1 || NUM_SCRIPTS > 0) if (type == FIND_EXE_ONLY && !dirbuf) { - const char *p = applet_names; - + const char *p; +# if NUM_APPLETS != 1 && NUM_SCRIPTS > 0 + for (i = 0, p = applet_names; i < 2; i++, p = script_names) +# elif NUM_APPLETS != 1 /* and NUM_SCRIPTS == 0 */ + p = applet_names; +# else /* NUM_APPLETS == 1 && NUM_SCRIPTS > 0 */ + p = script_names; +# endif while (*p) { if (strncmp(pfind, p, pf_len) == 0) add_match(xstrdup(p)); - while (*p++ != '\0') + while (*p++) continue; } } -- cgit v1.2.3-55-g6feb From 0575c9932d203d93633104e12054dcf5da522061 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Nov 2018 13:58:16 +0100 Subject: busybox: show embedded scripts in applet list function old new delta busybox_main 624 642 +18 Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'libbb') diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 92d99fbe8..d48b2ea60 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -839,24 +839,30 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) "Currently defined functions:\n" ); col = 0; - a = applet_names; /* prevent last comma to be in the very last pos */ output_width--; - while (*a) { - int len2 = strlen(a) + 2; - if (col >= (int)output_width - len2) { - full_write2_str(",\n"); - col = 0; - } - if (col == 0) { - col = 6; - full_write2_str("\t"); - } else { - full_write2_str(", "); + a = applet_names; + { +# if NUM_SCRIPTS > 0 + int i; + for (i = 0; i < 2; i++, a = script_names) +# endif + while (*a) { + int len2 = strlen(a) + 2; + if (col >= (int)output_width - len2) { + full_write2_str(",\n"); + col = 0; + } + if (col == 0) { + col = 6; + full_write2_str("\t"); + } else { + full_write2_str(", "); + } + full_write2_str(a); + col += len2; + a += len2 - 1; } - full_write2_str(a); - col += len2; - a += len2 - 1; } full_write2_str("\n"); return 0; -- cgit v1.2.3-55-g6feb From c339c7f7b393fbcd51b0f96df837baa1edad7fd8 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 2 Nov 2018 14:14:31 +0100 Subject: libarchive: add a function to unpack embedded data Similar code to unpack embedded data is used to decompress usage messages, embedded scripts and the config file (in the non-default bbconfig applet). Moving this code to a common function reduces the size of the default build and hides more of the internals of libarchive. function old new delta unpack_bz2_data - 135 +135 bb_show_usage 137 157 +20 get_script_content 32 47 +15 unpack_scripts 119 - -119 unpack_usage_messages 124 - -124 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 2/0 up/down: 170/-243) Total: -73 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_bunzip2.c | 38 +++++++++++++-- include/bb_archive.h | 7 +-- libbb/appletlib.c | 81 ++++++-------------------------- miscutils/bbconfig.c | 27 ++--------- 4 files changed, 54 insertions(+), 99 deletions(-) (limited to 'libbb') diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index 7ef4e035f..6f2c49fbc 100644 --- a/archival/libarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c @@ -107,7 +107,7 @@ struct bunzip_data { uint8_t selectors[32768]; /* nSelectors=15 bits */ struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ }; -/* typedef struct bunzip_data bunzip_data; -- done in .h file */ +typedef struct bunzip_data bunzip_data; /* Return the next nnn bits of input. All reads from the compressed input @@ -575,7 +575,7 @@ static int get_next_block(bunzip_data *bd) in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. (Why? This allows to get rid of one local variable) */ -int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) +static int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) { const uint32_t *dbuf; int pos, current, previous; @@ -699,7 +699,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) /* Because bunzip2 is used for help text unpacking, and because bb_show_usage() should work for NOFORK applets too, we must be extremely careful to not leak any allocations! */ -int FAST_FUNC start_bunzip( +static int FAST_FUNC start_bunzip( void *jmpbuf, bunzip_data **bdp, int in_fd, @@ -759,7 +759,7 @@ int FAST_FUNC start_bunzip( return RETVAL_OK; } -void FAST_FUNC dealloc_bunzip(bunzip_data *bd) +static void FAST_FUNC dealloc_bunzip(bunzip_data *bd) { free(bd->dbuf); free(bd); @@ -847,6 +847,36 @@ unpack_bz2_stream(transformer_state_t *xstate) return i ? i : IF_DESKTOP(total_written) + 0; } +char* FAST_FUNC +unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) +{ + 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, + /* len: */ packed_len + ); + } + /* read_bunzip can longjmp and end up here with i != 0 + * on read data errors! Not trivial */ + if (i == 0) { + /* Cannot use xmalloc: will leak bd in NOFORK case! */ + outbuf = malloc_or_warn(unpacked_len); + if (outbuf) + read_bunzip(bd, outbuf, unpacked_len); + } + dealloc_bunzip(bd); + return outbuf; +} + #ifdef TESTING static char *const bunzip_errors[] = { diff --git a/include/bb_archive.h b/include/bb_archive.h index d2022336b..561dd0c9d 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -214,12 +214,7 @@ const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_F const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; /* A bit of bunzip2 internals are exposed for compressed help support: */ -typedef struct bunzip_data bunzip_data; -int start_bunzip(void *, bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC; -/* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes - * in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */ -int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; -void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; +char *unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) FAST_FUNC; /* Meaning and direction (input/output) of the fields are transformer-specific */ typedef struct transformer_state_t { diff --git a/libbb/appletlib.c b/libbb/appletlib.c index d48b2ea60..6dfaf1f41 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -107,34 +107,8 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; # include "bb_archive.h" -static const char *unpack_usage_messages(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_usage, - /* len: */ sizeof(packed_usage) - ); - } - /* read_bunzip can longjmp and end up here with i != 0 - * on read data errors! Not trivial */ - if (i == 0) { - /* Cannot use xmalloc: will leak bd in NOFORK case! */ - outbuf = malloc_or_warn(sizeof(UNPACKED_USAGE)); - if (outbuf) - read_bunzip(bd, outbuf, sizeof(UNPACKED_USAGE)); - } - dealloc_bunzip(bd); - return outbuf; -} +# define unpack_usage_messages() \ + unpack_bz2_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE)) # define dealloc_usage_messages(s) free(s) #else @@ -152,21 +126,23 @@ void FAST_FUNC bb_show_usage(void) /* Imagine that this applet is "true". Dont suck in printf! */ const char *usage_string = unpack_usage_messages(); - if (*usage_string == '\b') { - full_write2_str("No help available.\n\n"); - } else { - full_write2_str("Usage: "SINGLE_APPLET_STR" "); - full_write2_str(usage_string); - full_write2_str("\n\n"); + if (usage_string) { + if (*usage_string == '\b') { + full_write2_str("No help available.\n\n"); + } else { + full_write2_str("Usage: "SINGLE_APPLET_STR" "); + full_write2_str(usage_string); + full_write2_str("\n\n"); + } + if (ENABLE_FEATURE_CLEAN_UP) + dealloc_usage_messages((char*)usage_string); } - if (ENABLE_FEATURE_CLEAN_UP) - dealloc_usage_messages((char*)usage_string); #else const char *p; const char *usage_string = p = unpack_usage_messages(); int ap = find_applet_by_name(applet_name); - if (ap < 0) /* never happens, paranoia */ + if (ap < 0 || usage_string == NULL) xfunc_die(); while (ap) { while (*p++) continue; @@ -986,38 +962,11 @@ find_script_by_name(const char *name) return -0x10000; /* make it so that NUM_APPLETS + is still < 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; -} - char* FAST_FUNC get_script_content(unsigned n) { - char *t = unpack_scripts(); + char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts), + UNPACKED_SCRIPTS_LENGTH); if (t) { while (n != 0) { while (*t++ != '\0') diff --git a/miscutils/bbconfig.c b/miscutils/bbconfig.c index 501349548..fe02516a8 100644 --- a/miscutils/bbconfig.c +++ b/miscutils/bbconfig.c @@ -43,29 +43,10 @@ int bbconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { #if ENABLE_FEATURE_COMPRESS_BBCONFIG - 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: */ bbconfig_config_bz2, - /* len: */ sizeof(bbconfig_config_bz2) - ); - } - /* read_bunzip can longjmp and end up here with i != 0 - * on read data errors! Not trivial */ - if (i == 0) { - /* Cannot use xmalloc: will leak bd in NOFORK case! */ - char *outbuf = malloc_or_warn(sizeof(bbconfig_config)); - if (outbuf) { - read_bunzip(bd, outbuf, sizeof(bbconfig_config)); - full_write1_str(outbuf); - } + const char *outbuf = unpack_bz2_data(bbconfig_config_bz2, + sizeof(bbconfig_config_bz2), sizeof(bbconfig_config)); + if (outbuf) { + full_write1_str(outbuf); } #else full_write1_str(bbconfig_config); -- cgit v1.2.3-55-g6feb From 3778898f97a64e7b42b53194af7f3b93cc9c07a3 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sat, 17 Nov 2018 17:48:14 +0000 Subject: Treat custom and applet scripts as applets BusyBox has support for embedded shell scripts. Two types can be distinguished: custom scripts and scripts implementing applets. Custom scripts should be placed in the 'embed' directory at build time. They are given a default applet configuration and appear as applets to the user but no further configuration is possible. Applet scripts are integrated with the BusyBox build system and are intended to be used to ship standard applets that just happen to be implemented as scripts. They can be configured at build time and appear just like native applets. Such scripts should be placed in the 'applets_sh' directory. A stub C program should be written to provide the usual applet configuration details and placed in a suitable subsystem directory. It may be helpful to have a configuration option to enable any dependencies the script requires: see the 'nologin' applet for an example. function old new delta scripted_main - 41 +41 applet_names 2773 2781 +8 applet_main 1600 1604 +4 i2cdetect_main 672 674 +2 applet_suid 100 101 +1 applet_install_loc 200 201 +1 applet_flags 100 101 +1 packed_usage 33180 33179 -1 tryexec 159 152 -7 evalcommand 1661 1653 -8 script_names 9 - -9 packed_scripts 123 114 -9 complete_cmd_dir_file 826 811 -15 shellexec 271 254 -17 find_command 1007 990 -17 busybox_main 642 624 -18 run_applet_and_exit 100 78 -22 find_script_by_name 51 - -51 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 6/9 up/down: 58/-174) Total: -116 bytes text data bss dec hex filename 950034 477 7296 957807 e9d6f busybox_old 949918 477 7296 957691 e9cfb busybox_unstripped Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- .gitignore | 5 +++ Makefile | 4 +- applets/busybox.mkscripts | 16 +++++++ applets_sh/README | 5 --- applets_sh/dos2unix | 5 --- applets_sh/nologin | 3 ++ applets_sh/tac | 7 --- applets_sh/unix2dos | 5 --- embed/nologin | 4 -- include/applets.src.h | 21 +++++++++ include/libbb.h | 2 +- libbb/appletlib.c | 72 ++++++++++++++---------------- libbb/lineedit.c | 20 ++------- scripts/embedded_scripts | 107 ++++++++++++++++++++++++++++++++++----------- scripts/gen_build_files.sh | 21 ++++++++- shell/ash.c | 19 ++------ util-linux/nologin.c | 27 ++++++++++++ 17 files changed, 217 insertions(+), 126 deletions(-) create mode 100755 applets/busybox.mkscripts delete mode 100644 applets_sh/README delete mode 100755 applets_sh/dos2unix create mode 100755 applets_sh/nologin delete mode 100755 applets_sh/tac delete mode 100755 applets_sh/unix2dos delete mode 100755 embed/nologin create mode 100644 util-linux/nologin.c (limited to 'libbb') diff --git a/.gitignore b/.gitignore index c03c2e8a6..becd9bf6d 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,8 @@ cscope.po.out # tags TAGS + +# +# user-supplied scripts +# +/embed diff --git a/Makefile b/Makefile index 8a0dbdf49..c19280476 100644 --- a/Makefile +++ b/Makefile @@ -361,7 +361,7 @@ scripts/basic/%: scripts_basic ; # This target generates Kbuild's and Config.in's from *.c files PHONY += gen_build_files -gen_build_files: $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) +gen_build_files: $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) $(wildcard embed/*) $(Q)$(srctree)/scripts/gen_build_files.sh $(srctree) $(objtree) # bbox: we have helpers in applets/ @@ -851,7 +851,7 @@ quiet_cmd_gen_common_bufsiz = GEN include/common_bufsiz.h quiet_cmd_split_autoconf = SPLIT include/autoconf.h -> include/config/* cmd_split_autoconf = scripts/basic/split-include include/autoconf.h include/config quiet_cmd_gen_embedded_scripts = GEN include/embedded_scripts.h - cmd_gen_embedded_scripts = scripts/embedded_scripts include/embedded_scripts.h embed + cmd_gen_embedded_scripts = $(srctree)/scripts/embedded_scripts include/embedded_scripts.h $(srctree)/embed $(srctree)/applets_sh #bbox# piggybacked generation of few .h files include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard embed/*) scripts/embedded_scripts $(call cmd,split_autoconf) diff --git a/applets/busybox.mkscripts b/applets/busybox.mkscripts new file mode 100755 index 000000000..935685cba --- /dev/null +++ b/applets/busybox.mkscripts @@ -0,0 +1,16 @@ +#!/bin/sh +# Make busybox scripted applet list file. + +# input $1: full path to Config.h +# input $2: full path to applets.h +# output (stdout): list of pathnames that should be linked to busybox + +export LC_ALL=POSIX +export LC_CTYPE=POSIX + +CONFIG_H=${1:-include/autoconf.h} +APPLETS_H=${2:-include/applets.h} +$HOSTCC -E -DMAKE_SCRIPTS -include $CONFIG_H $APPLETS_H | + awk '/^[ \t]*SCRIPT/{ + print $2 + }' diff --git a/applets_sh/README b/applets_sh/README deleted file mode 100644 index 9dcd38ae3..000000000 --- a/applets_sh/README +++ /dev/null @@ -1,5 +0,0 @@ -This directory contains examples of applets implemented as shell scripts. - -So far these scripts are not hooked to the build system and are not -installed by "make install". If you want to use them, -you need to install them by hand. diff --git a/applets_sh/dos2unix b/applets_sh/dos2unix deleted file mode 100755 index 0fd5206f6..000000000 --- a/applets_sh/dos2unix +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -# TODO: use getopt to avoid parsing options as filenames, -# and to support -- and --help -[ $# -ne 0 ] && DASH_I=-i -sed $DASH_I -e 's/\r$//' "$@" diff --git a/applets_sh/nologin b/applets_sh/nologin new file mode 100755 index 000000000..4ed5f6ca3 --- /dev/null +++ b/applets_sh/nologin @@ -0,0 +1,3 @@ +cat /etc/nologin.txt 2>/dev/null || echo This account is not available +sleep 5 +exit 1 diff --git a/applets_sh/tac b/applets_sh/tac deleted file mode 100755 index c5a8e39c1..000000000 --- a/applets_sh/tac +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# TODO: use getopt to avoid parsing options as filenames, -# and to support -- and --help -for i in "$@" -do -sed -e '1!G;h;$!d' "$i" -done diff --git a/applets_sh/unix2dos b/applets_sh/unix2dos deleted file mode 100755 index 70e042906..000000000 --- a/applets_sh/unix2dos +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -# TODO: use getopt to avoid parsing options as filenames, -# and to support -- and --help -[ $# -ne 0 ] && DASH_I=-i -sed $DASH_I -e 's/$/\r/' "$@" diff --git a/embed/nologin b/embed/nologin deleted file mode 100755 index 3768eaaa7..000000000 --- a/embed/nologin +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -cat /etc/nologin.txt 2>/dev/null || echo "This account is not available" -sleep 5 -exit 1 diff --git a/include/applets.src.h b/include/applets.src.h index 2ddf120ad..a9db5d160 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -22,41 +22,60 @@ s - suid type: BB_SUID_REQUIRE or BB_SUID_MAYBE applet. */ +#define NOUSAGE_STR "\b" + +#define dummy_trivial_usage NOUSAGE_STR \ + +#define dummy_full_usage "" \ + #if defined(PROTOTYPES) # define APPLET(name,l,s) int name##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; # define APPLET_ODDNAME(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; # define APPLET_NOEXEC(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; # define APPLET_NOFORK(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +# define APPLET_SCRIPTED(name,main,l,s,help) #elif defined(NAME_MAIN) # define APPLET(name,l,s) name name##_main # define APPLET_ODDNAME(name,main,l,s,help) name main##_main # define APPLET_NOEXEC(name,main,l,s,help) name main##_main # define APPLET_NOFORK(name,main,l,s,help) name main##_main +# define APPLET_SCRIPTED(name,main,l,s,help) name scripted_main #elif defined(MAKE_USAGE) && ENABLE_FEATURE_VERBOSE_USAGE # define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage name##_full_usage) # define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) # define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) # define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) +# define APPLET_SCRIPTED(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) #elif defined(MAKE_USAGE) && !ENABLE_FEATURE_VERBOSE_USAGE # define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage) # define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) # define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) # define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) +# define APPLET_SCRIPTED(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) #elif defined(MAKE_LINKS) # define APPLET(name,l,c) LINK l name # define APPLET_ODDNAME(name,main,l,s,help) LINK l name # define APPLET_NOEXEC(name,main,l,s,help) LINK l name # define APPLET_NOFORK(name,main,l,s,help) LINK l name +# define APPLET_SCRIPTED(name,main,l,s,help) LINK l name #elif defined(MAKE_SUID) # define APPLET(name,l,s) SUID s l name # define APPLET_ODDNAME(name,main,l,s,help) SUID s l name # define APPLET_NOEXEC(name,main,l,s,help) SUID s l name # define APPLET_NOFORK(name,main,l,s,help) SUID s l name +# define APPLET_SCRIPTED(name,main,l,s,help) SUID s l name + +#elif defined(MAKE_SCRIPTS) +# define APPLET(name,l,s) +# define APPLET_ODDNAME(name,main,l,s,help) +# define APPLET_NOEXEC(name,main,l,s,help) +# define APPLET_NOFORK(name,main,l,s,help) +# define APPLET_SCRIPTED(name,main,l,s,help) SCRIPT name #else static struct bb_applet applets[] = { /* name, main, location, need_suid */ @@ -64,6 +83,7 @@ s - suid type: # define APPLET_ODDNAME(name,main,l,s,help) { #name, #main, l, s }, # define APPLET_NOEXEC(name,main,l,s,help) { #name, #main, l, s, 1 }, # define APPLET_NOFORK(name,main,l,s,help) { #name, #main, l, s, 1, 1 }, +# define APPLET_SCRIPTED(name,main,l,s,help) { #name, #main, l, s }, #endif #if ENABLE_INSTALL_NO_USR @@ -84,3 +104,4 @@ INSERT #undef APPLET_ODDNAME #undef APPLET_NOEXEC #undef APPLET_NOFORK +#undef APPLET_SCRIPTED diff --git a/include/libbb.h b/include/libbb.h index a32608ebd..aa9e9d019 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1322,8 +1322,8 @@ void bb_logenv_override(void) FAST_FUNC; #endif /* Embedded script support */ -int find_script_by_name(const char *name) FAST_FUNC; char *get_script_content(unsigned n) FAST_FUNC; +int scripted_main(int argc, char** argv); /* Applets which are useful from another applets */ int bb_cat(char** argv) FAST_FUNC; diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 6dfaf1f41..a0ebaca29 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -51,7 +51,7 @@ #include "usage_compressed.h" #if ENABLE_ASH_EMBEDDED_SCRIPTS -# define DEFINE_script_names 1 +# define DEFINE_SCRIPT_DATA 1 # include "embedded_scripts.h" #else # define NUM_SCRIPTS 0 @@ -818,27 +818,21 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) /* prevent last comma to be in the very last pos */ output_width--; a = applet_names; - { -# if NUM_SCRIPTS > 0 - int i; - for (i = 0; i < 2; i++, a = script_names) -# endif - while (*a) { - int len2 = strlen(a) + 2; - if (col >= (int)output_width - len2) { - full_write2_str(",\n"); - col = 0; - } - if (col == 0) { - col = 6; - full_write2_str("\t"); - } else { - full_write2_str(", "); - } - full_write2_str(a); - col += len2; - a += len2 - 1; + while (*a) { + int len2 = strlen(a) + 2; + if (col >= (int)output_width - len2) { + full_write2_str(",\n"); + col = 0; + } + if (col == 0) { + col = 6; + full_write2_str("\t"); + } else { + full_write2_str(", "); } + full_write2_str(a); + col += len2; + a += len2 - 1; } full_write2_str("\n"); return 0; @@ -946,20 +940,25 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar # endif /* NUM_APPLETS > 0 */ # if NUM_SCRIPTS > 0 -int FAST_FUNC -find_script_by_name(const char *name) +static int find_script_by_name(const char *name) { - const char *s = script_names; - int i = 0; + int i; + int applet = find_applet_by_name(name); - while (*s) { - if (strcmp(name, s) == 0) - return i; - i++; - while (*s++ != '\0') - continue; + if (applet >= 0) { + for (i = 0; i < NUM_SCRIPTS; ++i) + if (applet_numbers[i] == applet) + return i; } - return -0x10000; /* make it so that NUM_APPLETS + is still < 0 */ + return -1; +} + +int scripted_main(int argc UNUSED_PARAM, char **argv) +{ + int script = find_script_by_name(applet_name); + if (script >= 0) + exit(ash_main(-script - 1, argv)); + return 0; } char* FAST_FUNC @@ -978,7 +977,7 @@ get_script_content(unsigned n) } # endif /* NUM_SCRIPTS > 0 */ -# if ENABLE_BUSYBOX || NUM_APPLETS > 0 || NUM_SCRIPTS > 0 +# if ENABLE_BUSYBOX || NUM_APPLETS > 0 static NORETURN void run_applet_and_exit(const char *name, char **argv) { # if ENABLE_BUSYBOX @@ -993,13 +992,6 @@ 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 618e7c221..b1e971f88 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -41,12 +41,6 @@ #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 @@ -812,20 +806,14 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) } pf_len = strlen(pfind); -# if ENABLE_FEATURE_SH_STANDALONE && (NUM_APPLETS != 1 || NUM_SCRIPTS > 0) +# if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 if (type == FIND_EXE_ONLY && !dirbuf) { - const char *p; -# if NUM_APPLETS != 1 && NUM_SCRIPTS > 0 - for (i = 0, p = applet_names; i < 2; i++, p = script_names) -# elif NUM_APPLETS != 1 /* and NUM_SCRIPTS == 0 */ - p = applet_names; -# else /* NUM_APPLETS == 1 && NUM_SCRIPTS > 0 */ - p = script_names; -# endif + const char *p = applet_names; + while (*p) { if (strncmp(pfind, p, pf_len) == 0) add_match(xstrdup(p)); - while (*p++) + while (*p++ != '\0') continue; } } diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts index 7245ba6e0..b7a023ce0 100755 --- a/scripts/embedded_scripts +++ b/scripts/embedded_scripts @@ -1,7 +1,8 @@ #!/bin/sh target="$1" -loc="$2" +custom_loc="$2" +applet_loc="$3" test "$target" || exit 1 test "$SED" || SED=sed @@ -14,46 +15,102 @@ if test $? != 0; then exit 1 fi -exec >"$target.$$" - -scripts="" -if [ -d "$loc" ] +custom_scripts="" +if [ -d "$custom_loc" ] then - scripts=$(cd $loc; ls * 2>/dev/null) + custom_scripts=$(cd $custom_loc; ls * 2>/dev/null) fi +all_scripts=$(applets/busybox.mkscripts) + +# all_scripts includes applet scripts and custom scripts, sort them out +applet_scripts="" +for i in $all_scripts +do + found=0 + for j in $custom_scripts + do + if [ "$i" = "$j" ] + then + found=1 + break; + fi + done + if [ $found -eq 0 ] + then + # anything that isn't a custom script is an applet script + applet_scripts="$applet_scripts $i" + fi +done -n=$(echo $scripts | wc -w) +# we know the custom scripts are present but applet scripts might have +# become detached from their configuration +for i in $applet_scripts +do + #if [ ! -f "$applet_loc/$i" -a ! -f "$custom_loc/$i" ] + if [ ! -f "$applet_loc/$i" ] + then + echo "missing applet script $i" + exit 1 + fi +done -if [ $n -ne 0 ] +n=$(echo $custom_scripts $applet_scripts | wc -w) +nall=$(echo $all_scripts | wc -w) + +if [ $n -ne $nall ] then - printf '#ifdef DEFINE_script_names\n' - printf 'const char script_names[] ALIGN1 = ' - for i in $scripts + echo "script mismatch $n != $nall" + exit 1 +fi + +concatenate_scripts() { + for i in $custom_scripts + do + cat $custom_loc/$i + printf '\000' + done + for i in $applet_scripts do - printf '"%s\\0"' $i + cat $applet_loc/$i + printf '\000' done - printf ';\n' +} + +exec >"$target.$$" + +if [ $n -ne 0 ] +then + printf '#ifdef DEFINE_SCRIPT_DATA\n' + if [ $n -ne 0 ] + then + printf 'const uint16_t applet_numbers[] = {\n' + for i in $custom_scripts $applet_scripts + do + # TODO support applets with names including invalid characters + printf '\tAPPLET_NO_%s,\n' $i + done + printf '};\n' + fi printf '#else\n' - printf 'extern const char script_names[] ALIGN1;\n' + if [ $n -ne 0 ] + then + printf 'extern const uint16_t applet_numbers[];\n' + fi printf '#endif\n' fi -printf "#define NUM_SCRIPTS $n\n\n" + +printf "\n" +printf '#define NUM_SCRIPTS %d\n' $n +printf "\n" if [ $n -ne 0 ] then printf '#define UNPACKED_SCRIPTS_LENGTH ' - for i in $scripts - do - cat $loc/$i - printf '\000' - done | wc -c + concatenate_scripts | wc -c printf '#define PACKED_SCRIPTS \\\n' - for i in $scripts - do - cat $loc/$i - printf '\000' - done | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | od -v -b \ + concatenate_scripts | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | \ + od -v -b \ | grep -v '^ ' \ | $SED -e 's/^[^ ]*//' \ -e 's/ //g' \ diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index f79fa2f83..64e4bffa9 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -17,12 +17,26 @@ status() { printf ' %-8s%s\n' "$1" "$2"; } gen() { status "GEN" "$@"; } chk() { status "CHK" "$@"; } +# scripts in the 'embed' directory are treated as fake applets +custom_scripts() +{ + custom_loc="$1" + if [ -d "$custom_loc" ] + then + for i in $(cd "$custom_loc"; ls *) + do + printf "APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, dummy)\n" $i; + done + fi +} + generate() { # NB: data to be inserted at INSERT line is coming on stdin src="$1" dst="$2" header="$3" + loc="$4" #chk "${dst}" { # Need to use printf: different shells have inconsistent @@ -32,6 +46,10 @@ generate() sed -n '/^INSERT$/ q; p' "${src}" # copy stdin to stdout cat + if [ -n "$loc" ] + then + custom_scripts "$loc" + fi # print everything after INSERT line sed -n '/^INSERT$/ { :l @@ -53,7 +71,8 @@ sed -n 's@^//applet:@@p' "$srctree"/*/*.c "$srctree"/*/*/*.c \ | generate \ "$srctree/include/applets.src.h" \ "include/applets.h" \ - "/* DO NOT EDIT. This file is generated from applets.src.h */" + "/* DO NOT EDIT. This file is generated from applets.src.h */" \ + "$srctree/embed" # (Re)generate include/usage.h # We add line continuation backslash after each line, diff --git a/shell/ash.c b/shell/ash.c index b1f8f15d2..44b3569dc 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -158,6 +158,10 @@ //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)) @@ -8016,9 +8020,6 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c { #if ENABLE_FEATURE_SH_STANDALONE if (applet_no >= 0) { -# if NUM_SCRIPTS > 0 - if (applet_no < NUM_APPLETS) -# endif if (APPLET_IS_NOEXEC(applet_no)) { clearenv(); while (*envp) @@ -8088,9 +8089,6 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) if (strchr(prog, '/') != NULL #if ENABLE_FEATURE_SH_STANDALONE || (applet_no = find_applet_by_name(prog)) >= 0 -# if NUM_SCRIPTS > 0 - || (applet_no = NUM_APPLETS + find_script_by_name(prog)) >= 0 -# endif #endif ) { tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); @@ -10192,10 +10190,6 @@ evalcommand(union node *cmd, int flags) */ /* find_command() encodes applet_no as (-2 - applet_no) */ int applet_no = (- cmdentry.u.index - 2); -# if NUM_SCRIPTS > 0 - /* Applets are ok, but not embedded scripts */ - if (applet_no < NUM_APPLETS) -# endif if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { char **sv_environ; @@ -13378,11 +13372,6 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) #if ENABLE_FEATURE_SH_STANDALONE { int applet_no = find_applet_by_name(name); -# if NUM_SCRIPTS > 0 - if (applet_no < 0) - /* embedded script indices are offset by NUM_APPLETS */ - applet_no = NUM_APPLETS + find_script_by_name(name); -# endif if (applet_no >= 0) { entry->cmdtype = CMDNORMAL; entry->u.index = -2 - applet_no; diff --git a/util-linux/nologin.c b/util-linux/nologin.c new file mode 100644 index 000000000..cc619bf8a --- /dev/null +++ b/util-linux/nologin.c @@ -0,0 +1,27 @@ +//config:config NOLOGIN +//config: bool "nologin" +//config: default y +//config: depends on ASH_EMBEDDED_SCRIPTS +//config: help +//config: Politely refuse a login +//config: +//config:config NOLOGIN_DEPENDENCIES +//config: bool "Dependencies for nologin" +//config: default y +//config: depends on NOLOGIN +//config: select CAT +//config: select ECHO +//config: select SLEEP +//config: help +//config: nologin is implemented as a shell script. It requires the +//config: following in the runtime environment: +//config: cat echo sleep +//config: If you know these will be available externally you can +//config: disable this option. + +//applet:IF_NOLOGIN(APPLET_SCRIPTED(nologin, scripted, BB_DIR_USR_SBIN, BB_SUID_DROP, nologin)) + +//usage:#define nologin_trivial_usage +//usage: "" +//usage:#define nologin_full_usage "\n\n" +//usage: "Politely refuse a login" -- cgit v1.2.3-55-g6feb From d1b2ae2d04eae05d76ad3c1a07e9092c7d46c773 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 18 Nov 2018 19:12:26 +0100 Subject: busybox: add '--show SCRIPT' option to display scripts Add an option to allow the content of embedded scripts to be displayed. This includes applet scripts, custom scripts and the .profile script. function old new delta busybox_main 624 701 +77 find_script_by_name - 24 +24 scripted_main 41 35 -6 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 101/-6) Total: 95 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- Config.in | 5 +++ libbb/appletlib.c | 92 ++++++++++++++++++++++++++++++++----------------------- 2 files changed, 59 insertions(+), 38 deletions(-) (limited to 'libbb') diff --git a/Config.in b/Config.in index ae21f52ef..01680af1f 100644 --- a/Config.in +++ b/Config.in @@ -178,6 +178,11 @@ config BUSYBOX Running "busybox APPLET [ARGS...]" will still work, of course. +config FEATURE_SHOW_SCRIPT + bool "Support --show SCRIPT" + default y + depends on BUSYBOX + config FEATURE_INSTALLER bool "Support --install [-s] to install applet links at runtime" default y diff --git a/libbb/appletlib.c b/libbb/appletlib.c index a0ebaca29..a79a37efb 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -756,6 +756,44 @@ static void install_links(const char *busybox UNUSED_PARAM, static void run_applet_and_exit(const char *name, char **argv) NORETURN; +# if NUM_SCRIPTS > 0 +static int find_script_by_name(const char *name) +{ + int i; + int applet = find_applet_by_name(name); + + if (applet >= 0) { + for (i = 0; i < NUM_SCRIPTS; ++i) + if (applet_numbers[i] == applet) + return i; + } + return -1; +} + +int scripted_main(int argc UNUSED_PARAM, char **argv) +{ + int script = find_script_by_name(applet_name); + if (script >= 0) + exit(ash_main(-script - 1, argv)); + return 0; +} + +char* FAST_FUNC +get_script_content(unsigned n) +{ + char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts), + UNPACKED_SCRIPTS_LENGTH); + if (t) { + while (n != 0) { + while (*t++ != '\0') + continue; + n--; + } + } + return t; +} +# endif /* NUM_SCRIPTS > 0 */ + # if ENABLE_BUSYBOX # if ENABLE_FEATURE_SH_STANDALONE && ENABLE_FEATURE_TAB_COMPLETION /* @@ -793,6 +831,9 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) "\n" "Usage: busybox [function [arguments]...]\n" " or: busybox --list"IF_FEATURE_INSTALLER("[-full]")"\n" +# if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0 + " or: busybox --show SCRIPT\n" +# endif IF_FEATURE_INSTALLER( " or: busybox --install [-s] [DIR]\n" ) @@ -838,6 +879,19 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) return 0; } +# if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0 + if (strcmp(argv[1], "--show") == 0) { + int n; + if (!argv[2]) + bb_error_msg_and_die(bb_msg_requires_arg, "--show"); + n = find_script_by_name(argv[2]); + if (n < 0) + bb_error_msg_and_die("script '%s' not found", argv[2]); + full_write1_str(get_script_content(n)); + return 0; + } +# endif + if (is_prefixed_with(argv[1], "--list")) { unsigned i = 0; const char *a = applet_names; @@ -939,44 +993,6 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar } # endif /* NUM_APPLETS > 0 */ -# if NUM_SCRIPTS > 0 -static int find_script_by_name(const char *name) -{ - int i; - int applet = find_applet_by_name(name); - - if (applet >= 0) { - for (i = 0; i < NUM_SCRIPTS; ++i) - if (applet_numbers[i] == applet) - return i; - } - return -1; -} - -int scripted_main(int argc UNUSED_PARAM, char **argv) -{ - int script = find_script_by_name(applet_name); - if (script >= 0) - exit(ash_main(-script - 1, argv)); - return 0; -} - -char* FAST_FUNC -get_script_content(unsigned n) -{ - char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts), - UNPACKED_SCRIPTS_LENGTH); - if (t) { - while (n != 0) { - while (*t++ != '\0') - continue; - n--; - } - } - return t; -} -# endif /* NUM_SCRIPTS > 0 */ - # if ENABLE_BUSYBOX || NUM_APPLETS > 0 static NORETURN void run_applet_and_exit(const char *name, char **argv) { -- cgit v1.2.3-55-g6feb From 26602b85a3f679017b4366d3c1b2f6c5aa950aa5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 19:14:52 +0100 Subject: wget: print the final newline only for non-tty output $ busybox wget URL 2>&1 | cat Connecting to .... install.iso 0% | | 2629k 0:02:05 ETA install.iso 7% |** | 25.7M 0:00:23 ETA install.iso 16% |***** | 54.1M 0:00:14 ETA install.iso 20% |****** | 67.4M 0:00:15 ETA install.iso 25% |******** | 81.0M 0:00:14 ETA install.iso 30% |********* | 97.3M 0:00:13 ETA install.iso 36% |*********** | 117M 0:00:12 ETA install.iso 41% |************* | 134M 0:00:11 ETA install.iso 47% |*************** | 152M 0:00:10 ETA install.iso 54% |***************** | 176M 0:00:08 ETA install.iso 61% |******************* | 200M 0:00:06 ETA install.iso 66% |********************* | 215M 0:00:06 ETA install.iso 71% |********************** | 231M 0:00:05 ETA install.iso 75% |************************ | 244M 0:00:04 ETA install.iso 79% |************************* | 257M 0:00:03 ETA install.iso 84% |*************************** | 275M 0:00:02 ETA install.iso 91% |***************************** | 297M 0:00:01 ETA install.iso 99% |******************************* | 321M 0:00:00 ETA install.iso 100% |********************************| 323M 0:00:00 ETA <-- no empty line here $ function old new delta bb_progress_update 622 632 +10 progress_meter 152 158 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 16/0) Total: 16 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- libbb/progress.c | 5 +++-- networking/wget.c | 7 +++++-- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index b041ce047..883457c0d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -2007,7 +2007,7 @@ typedef struct bb_progress_t { (p)->curfile = NULL; \ } while (0) void bb_progress_init(bb_progress_t *p, const char *curfile) FAST_FUNC; -void bb_progress_update(bb_progress_t *p, +int bb_progress_update(bb_progress_t *p, uoff_t beg_range, uoff_t transferred, uoff_t totalsize) FAST_FUNC; diff --git a/libbb/progress.c b/libbb/progress.c index 23e974ce7..d071ce705 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -69,7 +69,7 @@ void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile) * will be "totalsize" bytes. * If totalsize == 0, then it is unknown. */ -void FAST_FUNC bb_progress_update(bb_progress_t *p, +int FAST_FUNC bb_progress_update(bb_progress_t *p, uoff_t beg_size, uoff_t transferred, uoff_t totalsize) @@ -94,7 +94,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, * Do not update on every call * (we can be called on every network read!) */ - return; + return -1; } /* Before we lose real, unscaled sizes, produce human-readable size string */ @@ -211,4 +211,5 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, } if (notty) fputc('\n', stderr); + return notty; } diff --git a/networking/wget.c b/networking/wget.c index 65262e19d..44c481a99 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -283,13 +283,15 @@ enum { #if ENABLE_FEATURE_WGET_STATUSBAR static void progress_meter(int flag) { + int notty; + if (option_mask32 & WGET_OPT_QUIET) return; if (flag == PROGRESS_START) bb_progress_init(&G.pmt, G.curfile); - bb_progress_update(&G.pmt, + notty = bb_progress_update(&G.pmt, G.beg_range, G.transferred, (G.chunked || !G.got_clen) ? 0 : G.beg_range + G.transferred + G.content_len @@ -297,7 +299,8 @@ static void progress_meter(int flag) if (flag == PROGRESS_END) { bb_progress_free(&G.pmt); - bb_putchar_stderr('\n'); + if (notty == 0) + bb_putchar_stderr('\n'); /* it's tty */ G.transferred = 0; } } -- cgit v1.2.3-55-g6feb From f69f207490dd25b89380c21e816b1f6644a7529f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Nov 2018 13:00:28 +0100 Subject: libbb: add comment on sha384 Signed-off-by: Denys Vlasenko --- libbb/hash_md5_sha.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'libbb') diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index a53a382ce..9db79ea8b 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -794,6 +794,11 @@ static const uint32_t init512_lo[] = { }; #endif /* NEED_SHA512 */ +// Note: SHA-384 is identical to SHA-512, except that initial hash values are +// 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, +// 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4, +// and the output is constructed by omitting last two 64-bit words of it. + /* Initialize structure containing state of computation. (FIPS 180-2:5.3.2) */ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) -- cgit v1.2.3-55-g6feb From 71df2d3589e3e682cd6770f41f0b184841b78702 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 27 Nov 2018 14:34:25 +0000 Subject: hush: allow hush to run embedded scripts 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 Signed-off-by: Denys Vlasenko --- archival/libarchive/Kbuild.src | 2 +- docs/embedded-scripts.txt | 21 ++++++++------------- include/libbb.h | 5 +++++ libbb/appletlib.c | 8 +++++++- scripts/embedded_scripts | 8 ++++++++ scripts/gen_build_files.sh | 2 +- shell/Config.src | 14 ++++++++++++++ shell/ash.c | 16 +--------------- shell/hush.c | 16 ++++++++++++++++ util-linux/nologin.c | 2 +- 10 files changed, 62 insertions(+), 32 deletions(-) (limited to 'libbb') diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index 12e66a88b..d2f284b08 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src @@ -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) diff --git a/docs/embedded-scripts.txt b/docs/embedded-scripts.txt index 1b0c5b591..7a273d698 100644 --- a/docs/embedded-scripts.txt +++ b/docs/embedded-scripts.txt @@ -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 diff --git a/include/libbb.h b/include/libbb.h index ebd090e18..b560cc2eb 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -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); diff --git a/libbb/appletlib.c b/libbb/appletlib.c index a79a37efb..cd09b620c 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -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; } diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts index 86ad44d1d..aa7bf3e8a 100755 --- a/scripts/embedded_scripts +++ b/scripts/embedded_scripts @@ -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 if test $? != 0; then diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index 362632df3..92de681ac 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -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 } diff --git a/shell/Config.src b/shell/Config.src index 959d3cb42..bc7218fe5 100644 --- a/shell/Config.src +++ b/shell/Config.src @@ -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 diff --git a/shell/ash.c b/shell/ash.c index 04e4006c8..9ce1d1a76 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -148,20 +148,6 @@ //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)) @@ -195,7 +181,7 @@ #include #include /* 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 diff --git a/shell/hush.c b/shell/hush.c index 431010f09..90191408d 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -367,6 +367,11 @@ # 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(); diff --git a/util-linux/nologin.c b/util-linux/nologin.c index 0982fff3d..5e5e42305 100644 --- a/util-linux/nologin.c +++ b/util-linux/nologin.c @@ -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: -- cgit v1.2.3-55-g6feb