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

Reply via email to