[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [PATCH 2/2] Add an option to store applet names in compressed form
From:       Ron Yorston <rmy () pobox ! com>
Date:       2016-04-29 12:49:55
Message-ID: 57235873.yK0cVUx+fJX8SLEI%rmy () pobox ! com
[Download RAW message or body]

Add FEATURE_COMPRESS_NAMES to allow applet names to be stored as
a bzip2 compressed stream.  Since we don't want to decompress every
time an applet starts use a hash table of applet names to look up
commands.  This will result in invalid names being accepted too.

The names are stored uncompressed if the size of the compressed data
plus the hash table exceeds that of the uncompressed data.

With the default configuration storing compressed names gives:

function                                             old     new   delta
packed_names                                           -    1409   +1409
applet_hash                                            -     734    +734
unpack_data                                            -      65     +65
get_applet_names                                       -      20     +20
run_applet_and_exit                                  675     679      +4
applet_nameofs                                        14       -     -14
find_applet_by_name                                  112      69     -43
bb_show_usage                                        179     133     -46
applet_names                                        2536       -   -2536
------------------------------------------------------------------------------
(add/remove: 4/2 grow/shrink: 1/2 up/down: 2232/-2639)       Total: -407 bytes
   text	   data	    bss	    dec	    hex	filename
 764230	   2059	   1636	 767925	  bb7b5	busybox_old
 763823	   2059	   1636	 767518	  bb61e	busybox_unstripped

Signed-off-by: Ron Yorston <rmy@pobox.com>
---
 Config.in                | 12 +++++++++
 applets/.gitignore       |  1 +
 applets/Kbuild.src       | 15 ++++++++---
 applets/applet_tables.c  | 40 +++++++++++++++--------------
 applets/make_compressed  | 62 +++++++++++++++++++++++++++++++++++++++++++++
 applets/names.c          | 66 ++++++++++++++++++++++++++++++++++++++++++++++++
 applets/usage_compressed | 59 -------------------------------------------
 include/.gitignore       |  1 +
 include/busybox.h        |  1 -
 include/libbb.h          |  1 +
 libbb/Kbuild.src         |  2 +-
 libbb/appletlib.c        | 66 ++++++++++++++++++++++++++++++++++++++----------
 libbb/lineedit.c         |  5 +++-
 shell/ash.c              |  5 +++-
 14 files changed, 237 insertions(+), 99 deletions(-)
 create mode 100755 applets/make_compressed
 create mode 100644 applets/names.c
 delete mode 100755 applets/usage_compressed

diff --git a/Config.in b/Config.in
index 49ee333..e22a8b6 100644
--- a/Config.in
+++ b/Config.in
@@ -124,6 +124,18 @@ config STORE_APPLET_NAMES
 	  Disabling this will save some space but also disables useful
 	  features like the installer and listing applet names.
 
+config FEATURE_COMPRESS_NAMES
+	bool "Store applet names in compressed form"
+	default n
+	depends on STORE_APPLET_NAMES
+	help
+	  Store applet names in .bz compressed form, uncompress them
+	  on-the-fly when needed.
+
+	  If you have a really tiny busybox with few applets enabled (and
+	  bunzip2 isn't one of them), the overhead of the decompressor might
+	  be noticeable.
+
 config FEATURE_INSTALLER
 	bool "Support --install [-s] to install applet links at runtime"
 	default y
diff --git a/applets/.gitignore b/applets/.gitignore
index 459938d..613d100 100644
--- a/applets/.gitignore
+++ b/applets/.gitignore
@@ -1,3 +1,4 @@
 /applet_tables
 /usage
 /usage_pod
+/names
diff --git a/applets/Kbuild.src b/applets/Kbuild.src
index b612399..6bee15d 100644
--- a/applets/Kbuild.src
+++ b/applets/Kbuild.src
@@ -8,7 +8,7 @@ obj-y :=
 obj-y += applets.o
 
 hostprogs-y:=
-hostprogs-y += usage usage_pod applet_tables
+hostprogs-y += names usage usage_pod applet_tables
 
 always:= $(hostprogs-y)
 
@@ -27,16 +27,23 @@ HOSTCFLAGS_usage_pod.o = -I$(srctree_slash)include -Iinclude
 
 applets/applets.o: include/usage_compressed.h include/applet_tables.h
 
-applets/applet_tables: .config include/applets.h
+applets/applet_tables: .config include/applets.h include/names_compressed.h
+applets/names:         .config include/applets.h
 applets/usage:         .config include/applets.h
 applets/usage_pod:     .config include/applet_tables.h include/applets.h
 
 quiet_cmd_gen_usage_compressed = GEN     include/usage_compressed.h
-      cmd_gen_usage_compressed = $(srctree_slash)applets/usage_compressed \
include/usage_compressed.h applets +      cmd_gen_usage_compressed = \
$(srctree_slash)applets/make_compressed include/usage_compressed.h applets usage \
USAGE  
-include/usage_compressed.h: applets/usage $(srctree_slash)applets/usage_compressed
+include/usage_compressed.h: applets/usage $(srctree_slash)applets/make_compressed
 	$(call cmd,gen_usage_compressed)
 
+quiet_cmd_gen_names_compressed = GEN     include/names_compressed.h
+      cmd_gen_names_compressed = $(srctree_slash)applets/make_compressed \
include/names_compressed.h applets names NAMES +
+include/names_compressed.h: applets/names $(srctree_slash)applets/make_compressed
+	$(call cmd,gen_names_compressed)
+
 quiet_cmd_gen_applet_tables = GEN     include/applet_tables.h
       cmd_gen_applet_tables = applets/applet_tables include/applet_tables.h \
include/NUM_APPLETS.h  
diff --git a/applets/applet_tables.c b/applets/applet_tables.c
index 31ea188..efc9b26 100644
--- a/applets/applet_tables.c
+++ b/applets/applet_tables.c
@@ -40,6 +40,10 @@ struct bb_applet {
 
 /* Define struct bb_applet applets[] */
 #include "../include/applets.h"
+#include "../include/names_compressed.h"
+
+static const char unpacked_names [] = UNPACKED_NAMES;
+static const char packed_names[] = { PACKED_NAMES };
 
 enum { NUM_APPLETS = ARRAY_SIZE(applets) };
 
@@ -60,7 +64,7 @@ static int str_isalnum_(const char *s)
 	return 1;
 }
 
-#if !ENABLE_STORE_APPLET_NAMES
+#if !ENABLE_STORE_APPLET_NAMES || ENABLE_FEATURE_COMPRESS_NAMES
 static uint32_t hash(const char *s, uint32_t mul)
 {
 	uint32_t h = *s++;
@@ -136,27 +140,25 @@ int main(int argc, char **argv)
 
 	//printf("#ifndef SKIP_definitions\n");
 	mul = 0;
-#if ENABLE_STORE_APPLET_NAMES
-	printf("const char applet_names[] ALIGN1 = \"\"\n");
-	for (i = 0; i < NUM_APPLETS; i++) {
-		printf("\"%s\" \"\\0\"\n", applets[i].name);
-//		if (MAX_APPLET_NAME_LEN < strlen(applets[i].name))
-//			MAX_APPLET_NAME_LEN = strlen(applets[i].name);
-	}
-	printf(";\n\n");
-#else
-	mul = 1;
+#if !ENABLE_STORE_APPLET_NAMES || ENABLE_FEATURE_COMPRESS_NAMES
+	if (sizeof(packed_names)+2*NUM_APPLETS < sizeof(unpacked_names)) {
+		printf("/* compressed names + hash table < uncompressed names "
+				"(%u < %u) */\n",
+				sizeof(packed_names)+2*NUM_APPLETS,
+				sizeof(unpacked_names));
+		mul = 1;
  collision:
-	for (i = 0; i < NUM_APPLETS; i++) {
-		int j;
-		uint32_t h = hash(applets[i].name, mul);
-		for (j = 0; j < i; j++) {
-			if (h == applets[j].app_hash) {
-				mul += 2;
-				goto collision;
+		for (i = 0; i < NUM_APPLETS; i++) {
+			int j;
+			uint32_t h = hash(applets[i].name, mul);
+			for (j = 0; j < i; j++) {
+				if (h == applets[j].app_hash) {
+					mul += 2;
+					goto collision;
+				}
 			}
+			applets[i].app_hash = h;
 		}
-		applets[i].app_hash = h;
 	}
 #endif
 
diff --git a/applets/make_compressed b/applets/make_compressed
new file mode 100755
index 0000000..ce2f568
--- /dev/null
+++ b/applets/make_compressed
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+target="$1"
+loc="$2"
+prog="$3"
+name="$4"
+
+test "$target" || exit 1
+test "$loc" || loc=.
+test -x "$loc/$prog" || exit 1
+test "$name" || exit 1
+test "$SED" || SED=sed
+test "$DD" || DD=dd
+
+# Some people were bitten by their system lacking a (proper) od
+od -v -b </dev/null >/dev/null
+if test $? != 0; then
+	echo 'od tool is not installed or cannot accept "-v -b" options'
+	exit 1
+fi
+
+exec >"$target.$$"
+
+echo "#define UNPACKED_$name \"\" \\"
+"$loc/$prog" | od -v -b \
+| grep -v '^ ' \
+| $SED -e 's/^[^ ]*//' \
+	-e 's/ //g' \
+	-e '/^$/d' \
+	-e 's/\(...\)/\\\1/g' \
+	-e 's/^/"/' \
+	-e 's/$/" \\/'
+echo ''
+# "grep -v '^ '" is for toybox's od bug: od -b prints some extra lines:
+#0000000 010 000 010 000 133 055 144 146 135 040 133 055 143 040 103 117
+#         000010 000010 026533 063144 020135 026533 020143 047503
+#0000020 116 106 104 111 122 135 040 133 055 154 040 114 117 107 106 111
+#         043116 044504 056522 055440 066055 046040 043517 044506
+#0000040 114 105 135 040 133 055 141 040 101 103 124 111 117 116 106 111
+#         042514 020135 026533 020141 041501 044524 047117 044506
+
+echo "#define PACKED_$name \\"
+## Breaks on big-endian systems!
+## # Extra effort to avoid using "od -t x1": -t is not available
+## # in non-CONFIG_DESKTOPed busybox od
+##
+## "$loc/usage" | bzip2 -1 | od -v -x \
+## | $SED -e 's/^[^ ]*//' \
+##	-e 's/ //g' \
+##	-e '/^$/d' \
+##	-e 's/\(..\)\(..\)/0x\2,0x\1,/g'
+##	-e 's/$/ \\/'
+"$loc/$prog" | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | od -v -b \
+| grep -v '^ ' \
+| $SED -e 's/^[^ ]*//' \
+	-e 's/ //g' \
+	-e '/^$/d' \
+	-e 's/\(...\)/0\1,/g' \
+	-e 's/$/ \\/'
+echo ''
+
+mv -- "$target.$$" "$target"
diff --git a/applets/names.c b/applets/names.c
new file mode 100644
index 0000000..08c543a
--- /dev/null
+++ b/applets/names.c
@@ -0,0 +1,66 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Applet name generator.
+ * Runs on host and produces a list of null-separated applet names.
+ *
+ * Copyright (C) 2007 Denys Vlasenko <vda.linux@googlemail.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#undef ARRAY_SIZE
+#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
+
+#include "../include/autoconf.h"
+#include "../include/applet_metadata.h"
+
+struct bb_applet {
+	const char *name;
+	const char *main;
+	enum bb_install_loc_t install_loc;
+	enum bb_suid_t need_suid;
+	/* true if instead of fork(); exec("applet"); waitpid();
+	 * one can do fork(); exit(applet_main(argc,argv)); waitpid(); */
+	unsigned char noexec;
+	/* Even nicer */
+	/* true if instead of fork(); exec("applet"); waitpid();
+	 * one can simply call applet_main(argc,argv); */
+	unsigned char nofork;
+	uint32_t app_hash;
+};
+
+/* Define struct bb_applet applets[] */
+#include "../include/applets.h"
+
+enum { NUM_APPLETS = ARRAY_SIZE(applets) };
+
+static int cmp_name(const void *a, const void *b)
+{
+	const struct bb_applet *aa = a;
+	const struct bb_applet *bb = b;
+	return strcmp(aa->name, bb->name);
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+
+	qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name);
+
+	for (i = 0; i < NUM_APPLETS; i++) {
+		printf("%s", applets[i].name);
+		putchar('\0');
+	}
+	putchar('\0');
+
+	return 0;
+}
diff --git a/applets/usage_compressed b/applets/usage_compressed
deleted file mode 100755
index 186fcde..0000000
--- a/applets/usage_compressed
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-
-target="$1"
-loc="$2"
-
-test "$target" || exit 1
-test "$loc" || loc=.
-test -x "$loc/usage" || exit 1
-test "$SED" || SED=sed
-test "$DD" || DD=dd
-
-# Some people were bitten by their system lacking a (proper) od
-od -v -b </dev/null >/dev/null
-if test $? != 0; then
-	echo 'od tool is not installed or cannot accept "-v -b" options'
-	exit 1
-fi
-
-exec >"$target.$$"
-
-echo '#define UNPACKED_USAGE "" \'
-"$loc/usage" | od -v -b \
-| grep -v '^ ' \
-| $SED -e 's/^[^ ]*//' \
-	-e 's/ //g' \
-	-e '/^$/d' \
-	-e 's/\(...\)/\\\1/g' \
-	-e 's/^/"/' \
-	-e 's/$/" \\/'
-echo ''
-# "grep -v '^ '" is for toybox's od bug: od -b prints some extra lines:
-#0000000 010 000 010 000 133 055 144 146 135 040 133 055 143 040 103 117
-#         000010 000010 026533 063144 020135 026533 020143 047503
-#0000020 116 106 104 111 122 135 040 133 055 154 040 114 117 107 106 111
-#         043116 044504 056522 055440 066055 046040 043517 044506
-#0000040 114 105 135 040 133 055 141 040 101 103 124 111 117 116 106 111
-#         042514 020135 026533 020141 041501 044524 047117 044506
-
-echo '#define PACKED_USAGE \'
-## Breaks on big-endian systems!
-## # Extra effort to avoid using "od -t x1": -t is not available
-## # in non-CONFIG_DESKTOPed busybox od
-##
-## "$loc/usage" | bzip2 -1 | od -v -x \
-## | $SED -e 's/^[^ ]*//' \
-##	-e 's/ //g' \
-##	-e '/^$/d' \
-##	-e 's/\(..\)\(..\)/0x\2,0x\1,/g'
-##	-e 's/$/ \\/'
-"$loc/usage" | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | od -v -b \
-| grep -v '^ ' \
-| $SED -e 's/^[^ ]*//' \
-	-e 's/ //g' \
-	-e '/^$/d' \
-	-e 's/\(...\)/0\1,/g' \
-	-e 's/$/ \\/'
-echo ''
-
-mv -- "$target.$$" "$target"
diff --git a/include/.gitignore b/include/.gitignore
index 75afff9..21ac982 100644
--- a/include/.gitignore
+++ b/include/.gitignore
@@ -9,3 +9,4 @@
 /usage_compressed.h
 /usage.h
 /common_bufsiz.h*
+/names_compressed.h
diff --git a/include/busybox.h b/include/busybox.h
index 737627b..9929d10 100644
--- a/include/busybox.h
+++ b/include/busybox.h
@@ -13,7 +13,6 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
 
 /* Defined in appletlib.c (by including generated applet_tables.h) */
 /* Keep in sync with applets/applet_tables.c! */
-extern const char applet_names[] ALIGN1;
 extern int (*const applet_main[])(int argc, char **argv);
 extern const uint8_t applet_flags[] ALIGN1;
 extern const uint8_t applet_suid[] ALIGN1;
diff --git a/include/libbb.h b/include/libbb.h
index fd40ef7..a4eab52 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1229,6 +1229,7 @@ const struct hwtype *get_hwntype(int type) FAST_FUNC;
 
 #ifndef BUILD_INDIVIDUAL
 extern int find_applet_by_name(const char *name) FAST_FUNC;
+extern const char *get_applet_names(void) FAST_FUNC;
 /* Returns only if applet is not found. */
 extern void run_applet_and_exit(const char *name, char **argv) FAST_FUNC;
 extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index b08ce11..8c8d629 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -4,7 +4,7 @@
 #
 # Licensed under GPLv2, see file LICENSE in this source tree.
 
-libbb/appletlib.o: include/usage_compressed.h
+libbb/appletlib.o: include/usage_compressed.h include/names_compressed.h
 
 lib-y:=
 
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 9a4f367..d57b253 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -51,6 +51,7 @@
 #endif
 
 #include "usage_compressed.h"
+#include "names_compressed.h"
 
 
 #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
@@ -59,11 +60,15 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
 # define usage_messages 0
 #endif
 
-#if ENABLE_FEATURE_COMPRESS_USAGE
+#if ENABLE_STORE_APPLET_NAMES && !ENABLE_FEATURE_COMPRESS_NAMES
+static const char applet_names[] ALIGN1 = UNPACKED_NAMES;
+#else
+# define applet_names 0
+#endif
 
-static const char packed_usage[] ALIGN1 = { PACKED_USAGE };
+#if ENABLE_FEATURE_COMPRESS_USAGE || ENABLE_FEATURE_COMPRESS_NAMES
 # include "bb_archive.h"
-static const char *unpack_usage_messages(void)
+static const char *unpack_data(const char *data, int inlen, int outlen)
 {
 	char *outbuf = NULL;
 	bunzip_data *bd;
@@ -71,19 +76,27 @@ static const char *unpack_usage_messages(void)
 
 	i = start_bunzip(&bd,
 			/* src_fd: */ -1,
-			/* inbuf:  */ packed_usage,
-			/* len:    */ sizeof(packed_usage));
+			/* inbuf:  */ data,
+			/* len:    */ inlen);
 	/* read_bunzip can longjmp to start_bunzip, and ultimately
 	 * end up here with i != 0 on read data errors! Not trivial */
 	if (!i) {
 		/* Cannot use xmalloc: will leak bd in NOFORK case! */
-		outbuf = malloc_or_warn(sizeof(UNPACKED_USAGE));
+		outbuf = malloc_or_warn(outlen);
 		if (outbuf)
-			read_bunzip(bd, outbuf, sizeof(UNPACKED_USAGE));
+			read_bunzip(bd, outbuf, outlen);
 	}
 	dealloc_bunzip(bd);
 	return outbuf;
 }
+#endif
+
+#if ENABLE_FEATURE_COMPRESS_USAGE
+
+static const char packed_usage[] ALIGN1 = { PACKED_USAGE };
+
+# define unpack_usage_messages() \
+	unpack_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE))
 # define dealloc_usage_messages(s) free(s)
 
 #else
@@ -139,6 +152,26 @@ void FAST_FUNC bb_show_usage(void)
 	xfunc_die();
 }
 
+#if ENABLE_FEATURE_COMPRESS_NAMES
+
+static const char packed_names[] ALIGN1 = { PACKED_NAMES };
+
+# define unpack_names() \
+	unpack_data(packed_names, sizeof(packed_names), sizeof(UNPACKED_NAMES))
+# define dealloc_names(s) free(s)
+
+#else
+
+# define unpack_names() applet_names
+# define dealloc_names(s) ((void)(s))
+
+#endif /* FEATURE_COMPRESS_NAMES */
+
+const char * FAST_FUNC get_applet_names(void)
+{
+	return unpack_names();
+}
+
 #if APPNAME_HASH_MUL == 0
 int FAST_FUNC find_applet_by_name(const char *name)
 {
@@ -291,7 +324,6 @@ int FAST_FUNC find_applet_by_name(const char *name)
 }
 #endif
 
-
 void lbb_prepare(const char *applet
 		IF_FEATURE_INDIVIDUAL(, char **argv))
 				MAIN_EXTERNALLY_VISIBLE;
@@ -703,7 +735,8 @@ static void install_links(const char *busybox, int \
                use_symbolic_links,
 	 * busybox.h::bb_install_loc_t, or else... */
 	int (*lf)(const char *, const char *);
 	char *fpc;
-        const char *appname = applet_names;
+	const char *appname;
+	const char *names_string = appname = get_applet_names();
 	unsigned i;
 	int rc;
 
@@ -725,6 +758,8 @@ static void install_links(const char *busybox, int \
use_symbolic_links,  while (*appname++ != '\0')
 			continue;
 	}
+	if (ENABLE_FEATURE_CLEAN_UP)
+		dealloc_usage_messages((char*)names_string);
 }
 # else
 static void install_links(const char *busybox UNUSED_PARAM,
@@ -739,7 +774,7 @@ static int busybox_main(char **argv)
 {
 	if (!argv[1]) {
 		/* Called without arguments */
-		const char *a;
+		const char *a, *names_string;
 		int col;
 		unsigned output_width;
  help:
@@ -786,7 +821,7 @@ static int busybox_main(char **argv)
 		);
 #if ENABLE_STORE_APPLET_NAMES
 		col = 0;
-		a = applet_names;
+		names_string = a = get_applet_names();
 		/* prevent last comma to be in the very last pos */
 		output_width--;
 		while (*a) {
@@ -806,13 +841,16 @@ static int busybox_main(char **argv)
 			a += len2 - 1;
 		}
 		full_write2_str("\n\n");
+		if (ENABLE_FEATURE_CLEAN_UP)
+			dealloc_usage_messages((char*)names_string);
 #endif
 		return 0;
 	}
 
 	if (ENABLE_STORE_APPLET_NAMES && is_prefixed_with(argv[1], "--list")) {
 		unsigned i = 0;
-		const char *a = applet_names;
+		const char *a;
+		const char *names_string = a = get_applet_names();
 		dup2(1, 2);
 		while (*a) {
 # if ENABLE_FEATURE_INSTALLER
@@ -825,6 +863,8 @@ static int busybox_main(char **argv)
 			while (*a++ != '\0')
 				continue;
 		}
+		if (ENABLE_FEATURE_CLEAN_UP)
+			dealloc_usage_messages((char*)names_string);
 		return 0;
 	}
 
@@ -978,7 +1018,7 @@ int main(int argc UNUSED_PARAM, char **argv)
 		argv++;
 	}
 	/* applet_names in this case is just "applet\0\0" */
-	lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv));
+	lbb_prepare(SINGLE_APPLET_STR IF_FEATURE_INDIVIDUAL(, argv));
 	return SINGLE_APPLET_MAIN(argc, argv);
 #else
 	lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 2c35d50..a36a09a 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -777,7 +777,8 @@ static NOINLINE unsigned complete_cmd_dir_file(const char \
*command, int type)  
 #if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 && ENABLE_STORE_APPLET_NAMES
 	if (type == FIND_EXE_ONLY) {
-		const char *p = applet_names;
+		const char *p;
+		const char *names_string = p = get_applet_names();
 
 		while (*p) {
 			if (strncmp(pfind, p, pf_len) == 0)
@@ -785,6 +786,8 @@ static NOINLINE unsigned complete_cmd_dir_file(const char \
*command, int type)  while (*p++ != '\0')
 				continue;
 		}
+		if (ENABLE_FEATURE_COMPRESS_NAMES)
+			free((void *)names_string);
 	}
 #endif
 
diff --git a/shell/ash.c b/shell/ash.c
index acaf95c..29ea348 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -12590,7 +12590,8 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
 	}
 # if ENABLE_FEATURE_SH_STANDALONE && ENABLE_STORE_APPLET_NAMES
 	{
-		const char *a = applet_names;
+		const char *a;
+		const char *names_string = a = get_applet_names();
 		while (*a) {
 			col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
 			if (col > 60) {
@@ -12600,6 +12601,8 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
 			while (*a++ != '\0')
 				continue;
 		}
+		if (ENABLE_FEATURE_COMPRESS_NAMES)
+			free((void *)names_string);
 	}
 # endif
 	out1fmt("\n\n");
-- 
2.5.5

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic