Now that scripts can be embedded in the BusyBox binary it's possible to implement applets as scripts.
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. This patch implements the 'nologin' applet as a script. The 'embed' directory can be used for scripts that aren't intended to be treated as applets. v2: Tidy up config settings and embedded_scripts script If custom scripts are presents add a 'busybox --scripts' option to list them. Signed-off-by: Ron Yorston <r...@pobox.com> --- .gitignore | 5 +++ applets/busybox.mkscripts | 16 ++++++++ {embed => applets_sh}/nologin | 0 include/applets.src.h | 15 +++++++ include/libbb.h | 1 + libbb/appletlib.c | 76 ++++++++++++++++++++++------------- scripts/embedded_scripts | 59 +++++++++++++++++++-------- shell/ash.c | 4 ++ util-linux/nologin.c | 13 ++++++ 9 files changed, 143 insertions(+), 46 deletions(-) create mode 100755 applets/busybox.mkscripts rename {embed => applets_sh}/nologin (100%) create mode 100644 util-linux/nologin.c 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/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/embed/nologin b/applets_sh/nologin similarity index 100% rename from embed/nologin rename to applets_sh/nologin diff --git a/include/applets.src.h b/include/applets.src.h index 2ddf120ad..161a97ee8 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -27,36 +27,49 @@ s - suid type: # 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 +77,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, 0, 1, 1 }, #endif #if ENABLE_INSTALL_NO_USR @@ -84,3 +98,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..3fcff421b 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1324,6 +1324,7 @@ void bb_logenv_override(void) FAST_FUNC; /* 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 UNUSED_PARAM, char** argv) FAST_FUNC; /* 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..e16c75cc5 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -55,6 +55,8 @@ # include "embedded_scripts.h" #else # define NUM_SCRIPTS 0 +# define NUM_CUSTOM_SCRIPTS 0 +# define IF_CUSTOM_SCRIPTS(...) #endif #if NUM_SCRIPTS > 0 # include "bb_archive.h" @@ -754,6 +756,14 @@ static void install_links(const char *busybox UNUSED_PARAM, } # endif +int FAST_FUNC 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; +} + static void run_applet_and_exit(const char *name, char **argv) NORETURN; # if ENABLE_BUSYBOX @@ -775,6 +785,9 @@ static # endif int busybox_main(int argc UNUSED_PARAM, char **argv) { +# if NUM_CUSTOM_SCRIPTS > 0 + int do_custom; +# endif if (!argv[1]) { /* Called without arguments */ const char *a; @@ -793,6 +806,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_CUSTOM_SCRIPTS( + " or: busybox --scripts\n" + ) IF_FEATURE_INSTALLER( " or: busybox --install [-s] [DIR]\n" ) @@ -815,42 +831,47 @@ 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--; - 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; } - if (is_prefixed_with(argv[1], "--list")) { +# if NUM_CUSTOM_SCRIPTS > 0 + do_custom = strcmp(argv[1], "--scripts") == 0; +# endif + if (is_prefixed_with(argv[1], "--list") IF_CUSTOM_SCRIPTS(|| do_custom)) { unsigned i = 0; const char *a = applet_names; +# if NUM_CUSTOM_SCRIPTS > 0 + if (do_custom) + a = script_names; +# endif dup2(1, 2); while (*a) { +# if NUM_CUSTOM_SCRIPTS > 0 + if (do_custom && i == NUM_CUSTOM_SCRIPTS) + break; +# endif # if ENABLE_FEATURE_INSTALLER - if (argv[1][6]) /* --list-full? */ + if (argv[1][6] IF_CUSTOM_SCRIPTS(&& !do_custom)) /* --list-full? */ full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); # endif full_write2_str(a); @@ -993,12 +1014,9 @@ 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)); - } +# if NUM_CUSTOM_SCRIPTS > 0 + /* returns if script is not found */ + scripted_main(0, argv); # endif /*bb_error_msg_and_die("applet not found"); - links in printf */ diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts index 7245ba6e0..0abb132f8 100755 --- a/scripts/embedded_scripts +++ b/scripts/embedded_scripts @@ -14,21 +14,46 @@ if test $? != 0; then exit 1 fi -exec >"$target.$$" - -scripts="" +custom_scripts="" if [ -d "$loc" ] then - scripts=$(cd $loc; ls * 2>/dev/null) + custom_scripts=$(cd $loc; ls * 2>/dev/null) fi +applet_scripts=$(applets/busybox.mkscripts) + +for i in $applet_scripts +do + if [ ! -f applets_sh/$i ] + then + echo "missing applet script $i" + exit 1 + fi +done -n=$(echo $scripts | wc -w) +n=$(echo $custom_scripts $applet_scripts | wc -w) +num_cscripts=$(echo $custom_scripts | wc -w) +num_ascripts=$(echo $applet_scripts | wc -w) + +concatenate_scripts() { + for i in $custom_scripts + do + cat $loc/$i + printf '\000' + done + for i in $applet_scripts + do + cat applets_sh/$i + printf '\000' + done +} + +exec >"$target.$$" if [ $n -ne 0 ] then printf '#ifdef DEFINE_script_names\n' printf 'const char script_names[] ALIGN1 = ' - for i in $scripts + for i in $custom_scripts $applet_scripts do printf '"%s\\0"' $i done @@ -37,23 +62,23 @@ then printf 'extern const char script_names[] ALIGN1;\n' printf '#endif\n' fi -printf "#define NUM_SCRIPTS $n\n\n" +printf "#define NUM_SCRIPTS $n\n" +printf "#define NUM_CUSTOM_SCRIPTS $num_cscripts\n" +if [ $num_cscripts -ne 0 ] +then + printf "#define IF_CUSTOM_SCRIPTS(...) __VA_ARGS__\n\n" +else + printf "#define IF_CUSTOM_SCRIPTS(...)\n\n" +fi 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/shell/ash.c b/shell/ash.c index 90eaf6faf..0fa30b7b6 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)) diff --git a/util-linux/nologin.c b/util-linux/nologin.c new file mode 100644 index 000000000..152404b5d --- /dev/null +++ b/util-linux/nologin.c @@ -0,0 +1,13 @@ +//config:config NOLOGIN +//config: bool "nologin" +//config: default y +//config: depends on ASH_EMBEDDED_SCRIPTS +//config: help +//config: Politely refuse a login + +//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: "Display a message that an account is not available and exit non-zero." -- 2.19.1 _______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox