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
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 \
+++ /dev/null
-#!/bin/sh
-cat /etc/nologin.txt 2>/dev/null || echo "This account is not available"
-sleep 5
-exit 1
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)
--- /dev/null
+#!/bin/sh
+cat /etc/nologin.txt 2>/dev/null || echo "This account is not available"
+sleep 5
+exit 1
/autoconf.h
/bbconfigopts_bz2.h
/bbconfigopts.h
+/embedded_scripts.h
/NUM_APPLETS.h
/usage_compressed.h
/usage.h
#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);
#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"
}
# 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
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);
#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
--- /dev/null
+#!/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 >/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"
//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))
#include <sys/times.h>
#include <sys/utsname.h> /* 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 */
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);
*/
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;
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: "));