ash,hush: use HOME for tab completion and prompts
ash and hush correctly use the value of HOME for tilde expansion.
However the line editing code in libbb obtains the user's home
directory by calling getpwuid(). Thus tildes in tab completion
and prompts may be interpreted differently than in tilde expansion.
When the line editing code is invoked from a shell make it use the
shell's interpretation of tilde. This is similar to how GNU readline
and bash collaborate.
function old new delta
get_homedir_or_NULL 29 72 +43
optschanged 119 126 +7
hush_main 1204 1211 +7
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 57/0) Total: 57 bytes
v2: Always check for HOME before trying the password database: this
is what GNU readline does.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/include/libbb.h b/include/libbb.h
index 6aeec24..abbc9ac 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1924,6 +1924,7 @@
# define MAX_HISTORY 0
# endif
typedef const char *get_exe_name_t(int i) FAST_FUNC;
+typedef const char *sh_get_var_t(const char *name) FAST_FUNC;
typedef struct line_input_t {
int flags;
int timeout;
@@ -1937,9 +1938,8 @@
# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH
/* function to fetch additional application-specific names to match */
get_exe_name_t *get_exe_name;
-# define EDITING_HAS_get_exe_name 1
-# else
-# define EDITING_HAS_get_exe_name 0
+ /* function to fetch value of shell variable */
+ sh_get_var_t *sh_get_var;
# endif
# endif
# if MAX_HISTORY
@@ -1993,11 +1993,6 @@
read_line_input(prompt, command, maxsize)
#endif
-#ifndef EDITING_HAS_get_exe_name
-# define EDITING_HAS_get_exe_name 0
-#endif
-
-
#ifndef COMM_LEN
# ifdef TASK_COMM_LEN
enum { COMM_LEN = TASK_COMM_LEN };
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 8262475..b685399 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -259,6 +259,16 @@
static NOINLINE const char *get_homedir_or_NULL(void)
{
+ const char *home;
+
+# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH
+ home = state->sh_get_var ? state->sh_get_var("HOME") : getenv("HOME");
+# else
+ home = getenv("HOME");
+# endif
+ if (home != NULL && home[0] != '\0')
+ return home;
+
if (!got_user_strings)
get_user_strings();
return home_pwd_buf;
@@ -861,7 +871,7 @@
continue;
}
# endif
-# if EDITING_HAS_get_exe_name
+# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH
if (state->get_exe_name) {
i = 0;
for (;;) {
diff --git a/shell/ash.c b/shell/ash.c
index ef4a47a..d29de37 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9720,7 +9720,7 @@
}
/* setinteractive needs this forward reference */
-#if EDITING_HAS_get_exe_name
+#if ENABLE_FEATURE_EDITING
static const char *get_builtin_name(int i) FAST_FUNC;
#endif
@@ -9757,9 +9757,8 @@
#if ENABLE_FEATURE_EDITING
if (!line_input_state) {
line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
-# if EDITING_HAS_get_exe_name
line_input_state->get_exe_name = get_builtin_name;
-# endif
+ line_input_state->sh_get_var = lookupvar;
}
#endif
}
@@ -10262,7 +10261,7 @@
return bp;
}
-#if EDITING_HAS_get_exe_name
+#if ENABLE_FEATURE_EDITING
static const char * FAST_FUNC
get_builtin_name(int i)
{
diff --git a/shell/hush.c b/shell/hush.c
index ae81f0d..051b123 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -8188,7 +8188,7 @@
return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
}
-#if ENABLE_HUSH_JOB && EDITING_HAS_get_exe_name
+#if ENABLE_HUSH_JOB && ENABLE_FEATURE_EDITING
static const char * FAST_FUNC get_builtin_name(int i)
{
if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) {
@@ -10668,9 +10668,8 @@
# if ENABLE_FEATURE_EDITING
G.line_input_state = new_line_input_t(FOR_SHELL);
-# if EDITING_HAS_get_exe_name
G.line_input_state->get_exe_name = get_builtin_name;
-# endif
+ G.line_input_state->sh_get_var = get_local_var_value;
# endif
# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
{