aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-10-22 09:12:07 +0100
committerRon Yorston <rmy@pobox.com>2018-10-22 09:20:19 +0100
commit3994d5a52b8fa70637bffe4173f165267e6169fb (patch)
tree33268801c1adaa10797e6bee98ef737293fe6711
parenteee3722fd32c8c0929cfbacdbe0b6524e1fd645c (diff)
downloadbusybox-w32-3994d5a52b8fa70637bffe4173f165267e6169fb.tar.gz
busybox-w32-3994d5a52b8fa70637bffe4173f165267e6169fb.tar.bz2
busybox-w32-3994d5a52b8fa70637bffe4173f165267e6169fb.zip
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. This patch adds two configuration options to the shell: - '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. - 'Allow the contents of embedded scripts to be listed' makes the shell argument '-L name' list the contents of the named script. Both options are off by default. When scripts are embedded in the binary: - The shell argument '-L' lists the names of the scripts. - Scripts can be run as 'sh name arg...'. - An alias is added for each script, equivalent to "alias name='sh name'".
-rw-r--r--.gitignore5
-rw-r--r--archival/libarchive/Kbuild.src1
-rw-r--r--include/.gitignore1
-rw-r--r--shell/Kbuild.src10
-rw-r--r--shell/ash.c140
-rwxr-xr-xshell/embedded_scripts62
6 files changed, 218 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 517e750c1..cc485189e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,8 @@ cscope.po.out
58# 58#
59tags 59tags
60TAGS 60TAGS
61
62#
63# user-supplied scripts
64#
65/embed
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.
91lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o 91lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o
92lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o 92lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o
93lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o 93lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o
94lib-$(CONFIG_ASH_EMBEDDED_SCRIPTS) += open_transformer.o decompress_bunzip2.o
94 95
95ifneq ($(lib-y),) 96ifneq ($(lib-y),)
96lib-y += $(COMMON_FILES) 97lib-y += $(COMMON_FILES)
diff --git a/include/.gitignore b/include/.gitignore
index 75afff9ca..13a96e018 100644
--- a/include/.gitignore
+++ b/include/.gitignore
@@ -5,6 +5,7 @@
5/autoconf.h 5/autoconf.h
6/bbconfigopts_bz2.h 6/bbconfigopts_bz2.h
7/bbconfigopts.h 7/bbconfigopts.h
8/embedded_scripts.h
8/NUM_APPLETS.h 9/NUM_APPLETS.h
9/usage_compressed.h 10/usage_compressed.h
10/usage.h 11/usage.h
diff --git a/shell/Kbuild.src b/shell/Kbuild.src
index a287fce4e..34dd93d48 100644
--- a/shell/Kbuild.src
+++ b/shell/Kbuild.src
@@ -10,3 +10,13 @@ INSERT
10 10
11lib-$(CONFIG_FEATURE_SH_MATH) += math.o 11lib-$(CONFIG_FEATURE_SH_MATH) += math.o
12lib-$(CONFIG_FEATURE_PRNG_SHELL) += random.o 12lib-$(CONFIG_FEATURE_PRNG_SHELL) += random.o
13
14quiet_cmd_gen_embedded_scripts = GEN include/embedded_scripts.h
15 cmd_gen_embedded_scripts = $(srctree_slash)shell/embedded_scripts include/embedded_scripts.h embed
16
17ifdef CONFIG_ASH_EMBEDDED_SCRIPTS
18shell/ash.o: include/embedded_scripts.h
19endif
20
21include/embedded_scripts.h: $(wildcard embed/*) shell/embedded_scripts
22 $(call cmd,gen_embedded_scripts)
diff --git a/shell/ash.c b/shell/ash.c
index 7131609e4..9d7ef032c 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -175,6 +175,25 @@
175//config: from a GUI application. Disable this if your platform doesn't 175//config: from a GUI application. Disable this if your platform doesn't
176//config: support the required APIs. 176//config: support the required APIs.
177//config: 177//config:
178//config:config ASH_EMBEDDED_SCRIPTS
179//config: bool "Embed scripts in the binary"
180//config: default n
181//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
182//config: help
183//config: Allow scripts to be compressed and embedded in the BusyBox
184//config: binary. The scripts should be placed in the 'embed' directory.
185//config: Such scripts can only be run by giving their name as an
186//config: argument to the shell, though aliases are set up to do this.
187//config: The names of the scripts are listed by the '-L' shell argument.
188//config:
189//config:config ASH_LIST_EMBEDDED_SCRIPTS
190//config: bool "Allow the contents of embedded scripts to be listed"
191//config: default n
192//config: depends on ASH_EMBEDDED_SCRIPTS
193//config: help
194//config: Allow the contents of embedded script to be listed using
195//config: the '-L name' shell argument.
196//config:
178//config:endif # ash options 197//config:endif # ash options
179 198
180//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) 199//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
@@ -209,6 +228,16 @@
209#include <sys/utsname.h> /* for setting $HOSTNAME */ 228#include <sys/utsname.h> /* for setting $HOSTNAME */
210#include "busybox.h" /* for applet_names */ 229#include "busybox.h" /* for applet_names */
211 230
231#if ENABLE_ASH_EMBEDDED_SCRIPTS
232#include "embedded_scripts.h"
233#else
234#define NUM_SCRIPTS 0
235#endif
236
237#if NUM_SCRIPTS
238static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS };
239#endif
240
212/* So far, all bash compat is controlled by one config option */ 241/* So far, all bash compat is controlled by one config option */
213/* Separate defines document which part of code implements what */ 242/* Separate defines document which part of code implements what */
214/* function keyword */ 243/* function keyword */
@@ -11490,6 +11519,76 @@ setparam(char **argv)
11490#endif 11519#endif
11491} 11520}
11492 11521
11522#if NUM_SCRIPTS
11523#define BB_ARCHIVE_PUBLIC
11524# include "bb_archive.h"
11525static char *unpack_scripts(void)
11526{
11527 char *outbuf = NULL;
11528 bunzip_data *bd;
11529 int i;
11530 jmp_buf jmpbuf;
11531
11532 /* Setup for I/O error handling via longjmp */
11533 i = setjmp(jmpbuf);
11534 if (i == 0) {
11535 i = start_bunzip(&jmpbuf,
11536 &bd,
11537 /* src_fd: */ -1,
11538 /* inbuf: */ packed_scripts,
11539 /* len: */ sizeof(packed_scripts)
11540 );
11541 }
11542 /* read_bunzip can longjmp and end up here with i != 0
11543 * on read data errors! Not trivial */
11544 if (i == 0) {
11545 /* Cannot use xmalloc: will leak bd in NOFORK case! */
11546 outbuf = malloc_or_warn(UNPACKED_SCRIPTS_LENGTH);
11547 if (outbuf)
11548 read_bunzip(bd, outbuf, UNPACKED_SCRIPTS_LENGTH);
11549 }
11550 dealloc_bunzip(bd);
11551 return outbuf;
11552}
11553
11554static char *
11555check_embedded(const char *arg)
11556{
11557 int i;
11558 char *scripts;
11559 const char *s;
11560
11561 i = 0;
11562 for (s=script_names; *s; s+=strlen(s)+1) {
11563 if (strcmp(arg, s) == 0) {
11564 break;
11565 }
11566 ++i;
11567 }
11568
11569 if (i != NUM_SCRIPTS && (scripts=unpack_scripts()) != NULL) {
11570 char *t = scripts;
11571 while (i != 0) {
11572 t += strlen(t) + 1;
11573 --i;
11574 }
11575 return t;
11576 }
11577
11578 return NULL;
11579}
11580
11581static void
11582alias_embedded(void)
11583{
11584 const char *s;
11585
11586 for (s=script_names; *s; s+=strlen(s)+1) {
11587 setalias(s, auto_string(xasprintf("sh %s", s)));
11588 }
11589}
11590#endif
11591
11493/* 11592/*
11494 * Process shell options. The global variable argptr contains a pointer 11593 * Process shell options. The global variable argptr contains a pointer
11495 * to the argument list; we advance it past the options. 11594 * to the argument list; we advance it past the options.
@@ -11600,6 +11699,26 @@ options(int cmdline, int *login_sh)
11600 *login_sh = 1; 11699 *login_sh = 1;
11601 } 11700 }
11602 break; 11701 break;
11702#if NUM_SCRIPTS
11703 } else if (cmdline && (c == 'L')) {
11704#if ENABLE_ASH_LIST_EMBEDDED_SCRIPTS
11705 if (*argptr) {
11706 char *script;
11707
11708 if ((script=check_embedded(*argptr)) != NULL) {
11709 printf(script);
11710 }
11711 } else
11712#endif
11713 {
11714 const char *s;
11715
11716 for (s=script_names; *s; s+=strlen(s)+1) {
11717 printf("%s\n", s);
11718 }
11719 }
11720 exit(0);
11721#endif
11603 } else { 11722 } else {
11604 setoption(c, val); 11723 setoption(c, val);
11605 } 11724 }
@@ -14643,9 +14762,17 @@ init(void)
14643 } 14762 }
14644} 14763}
14645 14764
14646
14647//usage:#define ash_trivial_usage 14765//usage:#define ash_trivial_usage
14648//usage: "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]" 14766//usage: "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
14767//usage: IF_ASH_EMBEDDED_SCRIPTS(
14768//usage: " [-L"
14769//usage: )
14770//usage: IF_ASH_LIST_EMBEDDED_SCRIPTS(
14771//usage: " [name]"
14772//usage: )
14773//usage: IF_ASH_EMBEDDED_SCRIPTS(
14774//usage: "]"
14775//usage: )
14649//usage:#define ash_full_usage "\n\n" 14776//usage:#define ash_full_usage "\n\n"
14650//usage: "Unix shell interpreter" 14777//usage: "Unix shell interpreter"
14651 14778
@@ -14689,12 +14816,23 @@ procargs(char **argv)
14689#if DEBUG == 2 14816#if DEBUG == 2
14690 debug = 1; 14817 debug = 1;
14691#endif 14818#endif
14819#if NUM_SCRIPTS
14820 alias_embedded();
14821#endif
14692 /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */ 14822 /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14693 if (xminusc) { 14823 if (xminusc) {
14694 minusc = *xargv++; 14824 minusc = *xargv++;
14695 if (*xargv) 14825 if (*xargv)
14696 goto setarg0; 14826 goto setarg0;
14697 } else if (!sflag) { 14827 } else if (!sflag) {
14828#if NUM_SCRIPTS
14829 char *script;
14830 if ((script=check_embedded(*xargv)) != NULL) {
14831 setinputstring(script);
14832 xflag = 0;
14833 goto setarg0;
14834 }
14835#endif
14698 setinputfile(*xargv, 0); 14836 setinputfile(*xargv, 0);
14699#if ENABLE_PLATFORM_MINGW32 14837#if ENABLE_PLATFORM_MINGW32
14700 convert_slashes(*xargv); 14838 convert_slashes(*xargv);
diff --git a/shell/embedded_scripts b/shell/embedded_scripts
new file mode 100755
index 000000000..0ca89b91e
--- /dev/null
+++ b/shell/embedded_scripts
@@ -0,0 +1,62 @@
1#!/bin/sh
2
3target="$1"
4loc="$2"
5
6test "$target" || exit 1
7test "$SED" || SED=sed
8test "$DD" || DD=dd
9
10# Some people were bitten by their system lacking a (proper) od
11od -v -b </dev/null >/dev/null
12if test $? != 0; then
13 echo 'od tool is not installed or cannot accept "-v -b" options'
14 exit 1
15fi
16
17exec >"$target.$$"
18
19scripts=""
20if [ -d "$loc" ]
21then
22 scripts=$(cd $loc; ls * 2>/dev/null)
23fi
24
25n=$(echo $scripts | wc -w)
26
27if [ $n -ne 0 ]
28then
29 printf 'static const char script_names[] ALIGN1 = '
30 for i in $scripts
31 do
32 printf '"%s\\0"' $i
33 done
34 printf '"\\0";\n'
35fi
36printf "#define NUM_SCRIPTS $n\n\n"
37
38if [ $n -ne 0 ]
39then
40 printf '#define UNPACKED_SCRIPTS_LENGTH '
41 for i in $scripts
42 do
43 cat $loc/$i
44 printf '\000'
45 done | wc -c
46
47 printf '#define PACKED_SCRIPTS \\\n'
48 for i in $scripts
49 do
50 cat $loc/$i
51 printf '\000'
52 done | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | od -v -b \
53 | grep -v '^ ' \
54 | $SED -e 's/^[^ ]*//' \
55 -e 's/ //g' \
56 -e '/^$/d' \
57 -e 's/\(...\)/0\1,/g' \
58 -e 's/$/ \\/'
59 printf '\n'
60fi
61
62mv -- "$target.$$" "$target"