summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--Makefile4
-rwxr-xr-xapplets/busybox.mkscripts16
-rw-r--r--applets_sh/README5
-rwxr-xr-xapplets_sh/dos2unix5
-rwxr-xr-xapplets_sh/nologin3
-rwxr-xr-xapplets_sh/tac7
-rwxr-xr-xapplets_sh/unix2dos5
-rwxr-xr-xembed/nologin4
-rw-r--r--include/applets.src.h21
-rw-r--r--include/libbb.h2
-rw-r--r--libbb/appletlib.c72
-rw-r--r--libbb/lineedit.c20
-rwxr-xr-xscripts/embedded_scripts107
-rwxr-xr-xscripts/gen_build_files.sh21
-rw-r--r--shell/ash.c19
-rw-r--r--util-linux/nologin.c27
17 files changed, 217 insertions, 126 deletions
diff --git a/.gitignore b/.gitignore
index c03c2e8..becd9bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,3 +56,8 @@ cscope.po.out
#
tags
TAGS
+
+#
+# user-supplied scripts
+#
+/embed
diff --git a/Makefile b/Makefile
index 8a0dbdf..c192804 100644
--- a/Makefile
+++ b/Makefile
@@ -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 0000000..935685c
--- /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 9dcd38a..0000000
--- 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 0fd5206..0000000
--- 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 0000000..4ed5f6c
--- /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 c5a8e39..0000000
--- 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 70e0429..0000000
--- 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 3768eaa..0000000
--- 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 2ddf120..a9db5d1 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 a32608e..aa9e9d0 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 6dfaf1f..a0ebaca 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 618e7c2..b1e971f 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 7245ba6..b7a023c 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 f79fa2f..64e4bff 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 b1f8f15..44b3569 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 0000000..cc619bf
--- /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"