diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rwxr-xr-x | applets/busybox.mkscripts | 16 | ||||
-rw-r--r-- | applets_sh/README | 5 | ||||
-rwxr-xr-x | applets_sh/dos2unix | 5 | ||||
-rwxr-xr-x | applets_sh/nologin | 3 | ||||
-rwxr-xr-x | applets_sh/tac | 7 | ||||
-rwxr-xr-x | applets_sh/unix2dos | 5 | ||||
-rwxr-xr-x | embed/nologin | 4 | ||||
-rw-r--r-- | include/applets.src.h | 21 | ||||
-rw-r--r-- | include/libbb.h | 2 | ||||
-rw-r--r-- | libbb/appletlib.c | 72 | ||||
-rw-r--r-- | libbb/lineedit.c | 20 | ||||
-rwxr-xr-x | scripts/embedded_scripts | 107 | ||||
-rwxr-xr-x | scripts/gen_build_files.sh | 21 | ||||
-rw-r--r-- | shell/ash.c | 19 | ||||
-rw-r--r-- | util-linux/nologin.c | 27 |
17 files changed, 217 insertions, 126 deletions
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 @@ -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 + <error> 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" |