[PATCH] ash: allow a profile script to be embedded in the binary

Ron Yorston rmy at pobox.com
Sat Nov 3 10:56:23 UTC 2018


If the file embed/.profile exists at build time it is placed at the
start of the block of compressed scripts.  Its name isn't included
in the list of scripts so it can't be run directly by the user.
Instead it is executed when a login shell is started, after /etc/profile
but before ~/.profile.

If an empty .profile is present bloatcheck reports:

function                                             old     new   delta
ash_main                                            1346    1398     +52
.rodata                                           168516  168528     +12
find_script_by_name                                   57      60      +3
packed_scripts                                       123     122      -1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/1 up/down: 67/-1)              Total: 66 bytes

Signed-off-by: Ron Yorston <rmy at pobox.com>
---
 .gitignore               |  1 +
 Makefile                 |  2 +-
 libbb/appletlib.c        |  9 ++++++---
 libbb/lineedit.c         |  1 +
 scripts/embedded_scripts | 12 ++++++++++--
 shell/ash.c              | 14 +++++++++++++-
 6 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/.gitignore b/.gitignore
index c03c2e8a6..d8b02f13b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@ Config.in
 # Never ignore these
 #
 !.gitignore
+!embed/.profile
 
 #
 # Normal output
diff --git a/Makefile b/Makefile
index 8a0dbdf49..5d9be032f 100644
--- a/Makefile
+++ b/Makefile
@@ -853,7 +853,7 @@ quiet_cmd_split_autoconf   = SPLIT   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
 #bbox# piggybacked generation of few .h files
-include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard embed/*) scripts/embedded_scripts
+include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard embed/*) $(if $(wildcard embed/.profile),embed/.profile,) scripts/embedded_scripts
 	$(call cmd,split_autoconf)
 	$(call cmd,gen_bbconfigopts)
 	$(call cmd,gen_common_bufsiz)
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 6dfaf1f41..afdee39d6 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -55,8 +55,9 @@
 # include "embedded_scripts.h"
 #else
 # define NUM_SCRIPTS 0
+# define HAS_PROFILE 0
 #endif
-#if NUM_SCRIPTS > 0
+#if NUM_SCRIPTS > 0 || HAS_PROFILE
 # include "bb_archive.h"
 static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS };
 #endif
@@ -950,7 +951,7 @@ int FAST_FUNC
 find_script_by_name(const char *name)
 {
 	const char *s = script_names;
-	int i = 0;
+	int i = HAS_PROFILE;
 
 	while (*s) {
 		if (strcmp(name, s) == 0)
@@ -961,7 +962,9 @@ find_script_by_name(const char *name)
 	}
 	return -0x10000; /* make it so that NUM_APPLETS + <error> is still < 0 */
 }
+# endif /* NUM_SCRIPTS > 0 */
 
+# if NUM_SCRIPTS > 0 || HAS_PROFILE
 char* FAST_FUNC
 get_script_content(unsigned n)
 {
@@ -976,7 +979,7 @@ get_script_content(unsigned n)
 	}
 	return t;
 }
-# endif /* NUM_SCRIPTS > 0 */
+# endif /* NUM_SCRIPTS > 0 || HAS_PROFILE */
 
 # if ENABLE_BUSYBOX || NUM_APPLETS > 0 || NUM_SCRIPTS > 0
 static NORETURN void run_applet_and_exit(const char *name, char **argv)
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 618e7c221..3561f3d85 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -45,6 +45,7 @@
 # include "embedded_scripts.h"
 #else
 # define NUM_SCRIPTS 0
+# define HAS_PROFILE 0
 #endif
 
 #ifndef _POSIX_VDISABLE
diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts
index 7245ba6e0..09f050d1b 100755
--- a/scripts/embedded_scripts
+++ b/scripts/embedded_scripts
@@ -37,9 +37,17 @@ 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"
 
-if [ $n -ne 0 ]
+if [ -f $loc/.profile ]
+then
+	scripts=".profile $scripts"
+	printf "#define HAS_PROFILE 1\n\n"
+else
+	printf "#define HAS_PROFILE 0\n\n"
+fi
+
+if [ $n -ne 0 -o -f $loc/.profile ]
 then
 	printf '#define UNPACKED_SCRIPTS_LENGTH '
 	for i in $scripts
diff --git a/shell/ash.c b/shell/ash.c
index 88f2b5bd6..39d5b5b1b 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -195,6 +195,7 @@
 # include "embedded_scripts.h"
 #else
 # define NUM_SCRIPTS 0
+# define HAS_PROFILE 0
 #endif
 
 /* So far, all bash compat is controlled by one config option */
@@ -14235,7 +14236,18 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
 		const char *hp;
 
 		state = 1;
-		read_profile("/etc/profile");
+		read_profile("/etc/Profile");
+#if HAS_PROFILE
+		{
+			char *profile = get_script_content(0);
+			if (profile) {
+				setinputstring(profile);
+				cmdloop(0);
+				free(profile);
+				popfile();
+			}
+		}
+#endif
  state1:
 		state = 2;
 		hp = lookupvar("HOME");
-- 
2.19.1



More information about the busybox mailing list