[PATCH 3/3] Allow a profile script to be embedded in the binary

Ron Yorston rmy at pobox.com
Fri Nov 9 11:51:08 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, before
/etc/profile.

With no embed/.profile the binary is unchanged; with an empty script:

function                                             old     new   delta
packed_scripts                                       123     122      -1
.rodata                                           168561  168560      -1
ash_main                                            1346    1301     -45
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-47)             Total: -47 bytes

Signed-off-by: Ron Yorston <rmy at pobox.com>
---
 Makefile                 |  2 +-
 libbb/appletlib.c        | 11 +++++++----
 scripts/embedded_scripts |  9 ++++++++-
 shell/ash.c              | 19 +++++++++++++++++++
 4 files changed, 35 insertions(+), 6 deletions(-)

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 17b1ff2a8..c58ea6f53 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -55,11 +55,12 @@
 # include "embedded_scripts.h"
 #else
 # define NUM_SCRIPTS 0
+# define HAS_PROFILE 0
 # define NUM_CUSTOM_SCRIPTS 0
 # define NUM_APPLET_SCRIPTS 0
 # define IF_CUSTOM_SCRIPTS(...)
 #endif
-#if NUM_SCRIPTS > 0
+#if NUM_SCRIPTS > 0 || HAS_PROFILE
 # include "bb_archive.h"
 static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS };
 #endif
@@ -973,7 +974,7 @@ find_script_by_name(const char *name)
 	if (applet > 0) {
 		for (i=0; i<NUM_APPLET_SCRIPTS; ++i)
 			if (applet_numbers[i] == applet)
-				return NUM_CUSTOM_SCRIPTS + i;
+				return NUM_CUSTOM_SCRIPTS + HAS_PROFILE + i;
 	}
 #  endif
 
@@ -981,7 +982,7 @@ find_script_by_name(const char *name)
 	{
 		const char *s = script_names;
 
-		i = 0;
+		i = HAS_PROFILE;
 		while (*s) {
 			if (strcmp(name, s) == 0)
 				return i;
@@ -994,7 +995,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)
 {
@@ -1009,7 +1012,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/scripts/embedded_scripts b/scripts/embedded_scripts
index e6e8c3415..e257a698a 100755
--- a/scripts/embedded_scripts
+++ b/scripts/embedded_scripts
@@ -49,7 +49,7 @@ concatenate_scripts() {
 
 exec >"$target.$$"
 
-if [ $n -ne 0 ]
+if [ $n -ne 0 -o -f $loc/.profile ]
 then
 	printf '#ifdef DEFINE_SCRIPT_DATA\n'
 	if [ $num_cscripts -ne 0 ]
@@ -85,6 +85,13 @@ fi
 
 printf "\n"
 printf '#define NUM_SCRIPTS %d\n' $n
+if [ -f $loc/.profile ]
+then
+	custom_scripts=".profile $custom_scripts"
+	printf "#define HAS_PROFILE 1\n"
+else
+	printf "#define HAS_PROFILE 0\n"
+fi
 printf '#define NUM_CUSTOM_SCRIPTS %d\n' $num_cscripts
 printf '#define NUM_APPLET_SCRIPTS %d\n' $num_ascripts
 if [ $num_cscripts -ne 0 ]
diff --git a/shell/ash.c b/shell/ash.c
index 80c0089e8..dd9eea1ac 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -199,6 +199,7 @@
 # include "embedded_scripts.h"
 #else
 # define NUM_SCRIPTS 0
+# define HAS_PROFILE 0
 # define NUM_CUSTOM_SCRIPTS 0
 # define NUM_APPLET_SCRIPTS 0
 #endif
@@ -14181,6 +14182,9 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
 	struct jmploc jmploc;
 	struct stackmark smark;
 	int login_sh;
+#if HAS_PROFILE
+	char *profile;
+#endif
 
 	/* Initialize global data */
 	INIT_G_misc();
@@ -14216,6 +14220,10 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
 
 		popstackmark(&smark);
 		FORCE_INT_ON; /* enable interrupts */
+#if HAS_PROFILE
+		if (s == 0x1a)
+			goto state1a;
+#endif
 		if (s == 1)
 			goto state1;
 		if (s == 2)
@@ -14244,6 +14252,17 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
 	if (login_sh) {
 		const char *hp;
 
+#if HAS_PROFILE
+		state = 0x1a;
+		profile = get_script_content(0);
+		if (profile) {
+			setinputstring(profile);
+			cmdloop(0);
+			popfile();
+		}
+ state1a:
+		free(profile);
+#endif
 		state = 1;
 		read_profile("/etc/profile");
  state1:
-- 
2.19.1



More information about the busybox mailing list