mirror of
https://github.com/sheumann/hush.git
synced 2024-08-20 04:28:57 +00:00
hush: fix NOMMU bug (analogous to preceding commit for MMU)
This commit is contained in:
parent
d29084dd7d
commit
f886fd2bc7
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Busybox version: 1.12.0.svn
|
# Busybox version: 1.13.0.svn
|
||||||
# Wed Aug 20 00:24:07 2008
|
# Mon Oct 13 14:30:37 2008
|
||||||
#
|
#
|
||||||
CONFIG_HAVE_DOT_CONFIG=y
|
CONFIG_HAVE_DOT_CONFIG=y
|
||||||
|
|
||||||
@ -13,8 +13,8 @@ CONFIG_HAVE_DOT_CONFIG=y
|
|||||||
# General Configuration
|
# General Configuration
|
||||||
#
|
#
|
||||||
CONFIG_DESKTOP=y
|
CONFIG_DESKTOP=y
|
||||||
# CONFIG_EXTRA_COMPAT is not set
|
CONFIG_EXTRA_COMPAT=y
|
||||||
CONFIG_FEATURE_ASSUME_UNICODE=y
|
# CONFIG_FEATURE_ASSUME_UNICODE is not set
|
||||||
CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
|
CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
|
||||||
# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
|
# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
|
||||||
# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
|
# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
|
||||||
@ -153,7 +153,7 @@ CONFIG_DD=y
|
|||||||
CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
|
CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
|
||||||
CONFIG_FEATURE_DD_IBS_OBS=y
|
CONFIG_FEATURE_DD_IBS_OBS=y
|
||||||
CONFIG_DF=y
|
CONFIG_DF=y
|
||||||
CONFIG_FEATURE_DF_INODE=y
|
CONFIG_FEATURE_DF_FANCY=y
|
||||||
CONFIG_DIRNAME=y
|
CONFIG_DIRNAME=y
|
||||||
CONFIG_DOS2UNIX=y
|
CONFIG_DOS2UNIX=y
|
||||||
CONFIG_UNIX2DOS=y
|
CONFIG_UNIX2DOS=y
|
||||||
@ -283,6 +283,8 @@ CONFIG_FEATURE_RESIZE_PRINT=y
|
|||||||
CONFIG_SETCONSOLE=y
|
CONFIG_SETCONSOLE=y
|
||||||
CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y
|
CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y
|
||||||
CONFIG_SETFONT=y
|
CONFIG_SETFONT=y
|
||||||
|
CONFIG_FEATURE_SETFONT_TEXTUAL_MAP=y
|
||||||
|
CONFIG_DEFAULT_SETFONT_DIR=""
|
||||||
CONFIG_SETKEYCODES=y
|
CONFIG_SETKEYCODES=y
|
||||||
CONFIG_SETLOGCONS=y
|
CONFIG_SETLOGCONS=y
|
||||||
CONFIG_SHOWKEY=y
|
CONFIG_SHOWKEY=y
|
||||||
@ -690,6 +692,10 @@ CONFIG_FEATURE_FANCY_PING=y
|
|||||||
CONFIG_PSCAN=y
|
CONFIG_PSCAN=y
|
||||||
CONFIG_ROUTE=y
|
CONFIG_ROUTE=y
|
||||||
CONFIG_SENDMAIL=y
|
CONFIG_SENDMAIL=y
|
||||||
|
CONFIG_FEATURE_SENDMAIL_MAILX=y
|
||||||
|
CONFIG_FEATURE_SENDMAIL_MAILXX=y
|
||||||
|
CONFIG_FEATURE_SENDMAIL_SSL=y
|
||||||
|
CONFIG_FEATURE_SENDMAIL_CHARSET="utf-8"
|
||||||
CONFIG_FETCHMAIL=y
|
CONFIG_FETCHMAIL=y
|
||||||
CONFIG_SLATTACH=y
|
CONFIG_SLATTACH=y
|
||||||
CONFIG_TELNET=y
|
CONFIG_TELNET=y
|
||||||
@ -760,9 +766,9 @@ CONFIG_WATCH=y
|
|||||||
# Shells
|
# Shells
|
||||||
#
|
#
|
||||||
# CONFIG_FEATURE_SH_IS_ASH is not set
|
# CONFIG_FEATURE_SH_IS_ASH is not set
|
||||||
# CONFIG_FEATURE_SH_IS_HUSH is not set
|
CONFIG_FEATURE_SH_IS_HUSH=y
|
||||||
# CONFIG_FEATURE_SH_IS_MSH is not set
|
# CONFIG_FEATURE_SH_IS_MSH is not set
|
||||||
CONFIG_FEATURE_SH_IS_NONE=y
|
# CONFIG_FEATURE_SH_IS_NONE is not set
|
||||||
# CONFIG_ASH is not set
|
# CONFIG_ASH is not set
|
||||||
# CONFIG_ASH_BASH_COMPAT is not set
|
# CONFIG_ASH_BASH_COMPAT is not set
|
||||||
# CONFIG_ASH_JOB_CONTROL is not set
|
# CONFIG_ASH_JOB_CONTROL is not set
|
||||||
|
158
shell/hush.c
158
shell/hush.c
@ -103,6 +103,7 @@
|
|||||||
#define debug_printf_parse(...) do {} while (0)
|
#define debug_printf_parse(...) do {} while (0)
|
||||||
#define debug_print_tree(a, b) do {} while (0)
|
#define debug_print_tree(a, b) do {} while (0)
|
||||||
#define debug_printf_exec(...) do {} while (0)
|
#define debug_printf_exec(...) do {} while (0)
|
||||||
|
#define debug_printf_env(...) do {} while (0)
|
||||||
#define debug_printf_jobs(...) do {} while (0)
|
#define debug_printf_jobs(...) do {} while (0)
|
||||||
#define debug_printf_expand(...) do {} while (0)
|
#define debug_printf_expand(...) do {} while (0)
|
||||||
#define debug_printf_glob(...) do {} while (0)
|
#define debug_printf_glob(...) do {} while (0)
|
||||||
@ -122,6 +123,10 @@
|
|||||||
#define debug_printf_exec(...) fprintf(stderr, __VA_ARGS__)
|
#define debug_printf_exec(...) fprintf(stderr, __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef debug_printf_env
|
||||||
|
#define debug_printf_env(...) fprintf(stderr, __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef debug_printf_jobs
|
#ifndef debug_printf_jobs
|
||||||
#define debug_printf_jobs(...) fprintf(stderr, __VA_ARGS__)
|
#define debug_printf_jobs(...) fprintf(stderr, __VA_ARGS__)
|
||||||
#define DEBUG_JOBS 1
|
#define DEBUG_JOBS 1
|
||||||
@ -522,16 +527,21 @@ static void setup_string_in_str(struct in_str *i, const char *s);
|
|||||||
static int free_pipe_list(struct pipe *head, int indent);
|
static int free_pipe_list(struct pipe *head, int indent);
|
||||||
static int free_pipe(struct pipe *pi, int indent);
|
static int free_pipe(struct pipe *pi, int indent);
|
||||||
/* really run the final data structures: */
|
/* really run the final data structures: */
|
||||||
static int setup_redirects(struct command *prog, int squirrel[]);
|
typedef struct nommu_save_t {
|
||||||
static int run_list(struct pipe *pi);
|
char **new_env;
|
||||||
|
char **old_env;
|
||||||
|
char **argv;
|
||||||
|
} nommu_save_t;
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
#define pseudo_exec_argv(ptr_ptrs2free, argv, assignment_cnt, argv_expanded) \
|
#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
|
||||||
pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
|
pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
|
||||||
#define pseudo_exec(ptr_ptrs2free, command, argv_expanded) \
|
#define pseudo_exec(nommu_save, command, argv_expanded) \
|
||||||
pseudo_exec(command, argv_expanded)
|
pseudo_exec(command, argv_expanded)
|
||||||
#endif
|
#endif
|
||||||
static void pseudo_exec_argv(char ***ptr_ptrs2free, char **argv, int assignment_cnt, char **argv_expanded) NORETURN;
|
static void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignment_cnt, char **argv_expanded) NORETURN;
|
||||||
static void pseudo_exec(char ***ptr_ptrs2free, struct command *command, char **argv_expanded) NORETURN;
|
static void pseudo_exec(nommu_save_t *nommu_save, struct command *command, char **argv_expanded) NORETURN;
|
||||||
|
static int setup_redirects(struct command *prog, int squirrel[]);
|
||||||
|
static int run_list(struct pipe *pi);
|
||||||
static int run_pipe(struct pipe *pi);
|
static int run_pipe(struct pipe *pi);
|
||||||
/* data structure manipulation: */
|
/* data structure manipulation: */
|
||||||
static int setup_redirect(struct parse_context *ctx, int fd, redir_type style, struct in_str *input);
|
static int setup_redirect(struct parse_context *ctx, int fd, redir_type style, struct in_str *input);
|
||||||
@ -655,8 +665,10 @@ static void putenv_all(char **strings)
|
|||||||
{
|
{
|
||||||
if (!strings)
|
if (!strings)
|
||||||
return;
|
return;
|
||||||
while (*strings)
|
while (*strings) {
|
||||||
|
debug_printf_env("putenv '%s'\n", *strings);
|
||||||
putenv(*strings++);
|
putenv(*strings++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char **putenv_all_and_save_old(char **strings)
|
static char **putenv_all_and_save_old(char **strings)
|
||||||
@ -667,10 +679,20 @@ static char **putenv_all_and_save_old(char **strings)
|
|||||||
if (!strings)
|
if (!strings)
|
||||||
return old;
|
return old;
|
||||||
while (*strings) {
|
while (*strings) {
|
||||||
char *v = getenv(*strings++);
|
char *v, *eq;
|
||||||
if (!v)
|
|
||||||
continue;
|
eq = strchr(*strings, '=');
|
||||||
old = add_string_to_strings(old, v);
|
if (eq) {
|
||||||
|
*eq = '\0';
|
||||||
|
v = getenv(*strings);
|
||||||
|
*eq = '=';
|
||||||
|
if (v) {
|
||||||
|
/* v points to VAL in VAR=VAL, go back to VAR */
|
||||||
|
v -= (eq - *strings) + 1;
|
||||||
|
old = add_string_to_strings(old, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strings++;
|
||||||
}
|
}
|
||||||
putenv_all(s);
|
putenv_all(s);
|
||||||
return old;
|
return old;
|
||||||
@ -687,21 +709,13 @@ static void free_strings_and_unsetenv(char **strings, int unset)
|
|||||||
while (*v) {
|
while (*v) {
|
||||||
if (unset) {
|
if (unset) {
|
||||||
char *copy;
|
char *copy;
|
||||||
#if !BB_MMU
|
|
||||||
/* If this is a magic guard pointer, do not free it,
|
|
||||||
* and stop unsetting */
|
|
||||||
if (*v == hush_version_str) {
|
|
||||||
unset = 0;
|
|
||||||
v++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* *strchrnul(*v, '=') = '\0'; -- BAD
|
/* *strchrnul(*v, '=') = '\0'; -- BAD
|
||||||
* In case *v was putenv'ed, we can't
|
* In case *v was putenv'ed, we can't
|
||||||
* unsetenv(*v) after taking out '=':
|
* unsetenv(*v) after taking out '=':
|
||||||
* it won't work, env is modified by taking out!
|
* it won't work, env is modified by taking out!
|
||||||
* horror :( */
|
* horror :( */
|
||||||
copy = xstrndup(*v, strchrnul(*v, '=') - *v);
|
copy = xstrndup(*v, strchrnul(*v, '=') - *v);
|
||||||
|
debug_printf_env("unsetenv '%s'\n", copy);
|
||||||
unsetenv(copy);
|
unsetenv(copy);
|
||||||
free(copy);
|
free(copy);
|
||||||
}
|
}
|
||||||
@ -1431,16 +1445,26 @@ static void restore_redirects(int squirrel[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char **expand_assignments(char **argv, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char **p = NULL;
|
||||||
|
/* Expand assignments into one string each */
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
p = add_string_to_strings(p, expand_string_to_string(argv[i]));
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/* Called after [v]fork() in run_pipe(), or from builtin_exec().
|
/* Called after [v]fork() in run_pipe(), or from builtin_exec().
|
||||||
* Never returns.
|
* Never returns.
|
||||||
* XXX no exit() here. If you don't exec, use _exit instead.
|
* XXX no exit() here. If you don't exec, use _exit instead.
|
||||||
* The at_exit handlers apparently confuse the calling process,
|
* The at_exit handlers apparently confuse the calling process,
|
||||||
* in particular stdin handling. Not sure why? -- because of vfork! (vda) */
|
* in particular stdin handling. Not sure why? -- because of vfork! (vda) */
|
||||||
static void pseudo_exec_argv(char ***ptr_ptrs2free, char **argv, int assignment_cnt, char **argv_expanded)
|
static void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignment_cnt, char **argv_expanded)
|
||||||
{
|
{
|
||||||
int i, rcode;
|
int rcode;
|
||||||
char *p;
|
char **new_env;
|
||||||
const struct built_in_command *x;
|
const struct built_in_command *x;
|
||||||
|
|
||||||
/* If a variable is assigned in a forest, and nobody listens,
|
/* If a variable is assigned in a forest, and nobody listens,
|
||||||
@ -1449,24 +1473,20 @@ static void pseudo_exec_argv(char ***ptr_ptrs2free, char **argv, int assignment_
|
|||||||
if (!argv[assignment_cnt])
|
if (!argv[assignment_cnt])
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
|
|
||||||
for (i = 0; i < assignment_cnt; i++) {
|
new_env = expand_assignments(argv, assignment_cnt);
|
||||||
debug_printf_exec("pid %d environment modification: %s\n",
|
#if BB_MMU
|
||||||
getpid(), *argv);
|
putenv_all(new_env);
|
||||||
p = expand_string_to_string(*argv);
|
free(new_env); /* optional */
|
||||||
putenv(p);
|
#else
|
||||||
#if !BB_MMU
|
nommu_save->new_env = new_env;
|
||||||
*ptr_ptrs2free = add_string_to_strings(*ptr_ptrs2free, p);
|
nommu_save->old_env = putenv_all_and_save_old(new_env);
|
||||||
#endif
|
#endif
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
if (argv_expanded) {
|
if (argv_expanded) {
|
||||||
argv = argv_expanded;
|
argv = argv_expanded;
|
||||||
} else {
|
} else {
|
||||||
argv = expand_strvec_to_strvec(argv);
|
argv = expand_strvec_to_strvec(argv);
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
/* Inserting magic guard pointer to not unsetenv junk later */
|
nommu_save->argv = argv;
|
||||||
*ptr_ptrs2free = add_string_to_strings(*ptr_ptrs2free, (char*)hush_version_str);
|
|
||||||
*ptr_ptrs2free = add_string_to_strings(*ptr_ptrs2free, (char*)argv);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1512,10 +1532,10 @@ static void pseudo_exec_argv(char ***ptr_ptrs2free, char **argv, int assignment_
|
|||||||
|
|
||||||
/* Called after [v]fork() in run_pipe()
|
/* Called after [v]fork() in run_pipe()
|
||||||
*/
|
*/
|
||||||
static void pseudo_exec(char ***ptr_ptrs2free, struct command *command, char **argv_expanded)
|
static void pseudo_exec(nommu_save_t *nommu_save, struct command *command, char **argv_expanded)
|
||||||
{
|
{
|
||||||
if (command->argv)
|
if (command->argv)
|
||||||
pseudo_exec_argv(ptr_ptrs2free, command->argv, command->assignment_cnt, argv_expanded);
|
pseudo_exec_argv(nommu_save, command->argv, command->assignment_cnt, argv_expanded);
|
||||||
|
|
||||||
if (command->group) {
|
if (command->group) {
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
@ -1785,17 +1805,6 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe)
|
|||||||
* Returns -1 only if started some children. IOW: we have to
|
* Returns -1 only if started some children. IOW: we have to
|
||||||
* mask out retvals of builtins etc with 0xff!
|
* mask out retvals of builtins etc with 0xff!
|
||||||
*/
|
*/
|
||||||
/* A little helper first */
|
|
||||||
static char **expand_assignments(char **argv, int count)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char **p = NULL;
|
|
||||||
/* Expand assignments into one string each */
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
p = add_string_to_strings(p, expand_string_to_string(argv[i]));
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
static int run_pipe(struct pipe *pi)
|
static int run_pipe(struct pipe *pi)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -1876,11 +1885,13 @@ static int run_pipe(struct pipe *pi)
|
|||||||
old_env = putenv_all_and_save_old(new_env);
|
old_env = putenv_all_and_save_old(new_env);
|
||||||
debug_printf_exec(": builtin '%s' '%s'...\n", x->cmd, argv_expanded[1]);
|
debug_printf_exec(": builtin '%s' '%s'...\n", x->cmd, argv_expanded[1]);
|
||||||
rcode = x->function(argv_expanded) & 0xff;
|
rcode = x->function(argv_expanded) & 0xff;
|
||||||
USE_FEATURE_SH_STANDALONE(clean_up_and_ret:)
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
|
clean_up_and_ret:
|
||||||
|
#endif
|
||||||
restore_redirects(squirrel);
|
restore_redirects(squirrel);
|
||||||
free_strings_and_unsetenv(new_env, 1);
|
free_strings_and_unsetenv(new_env, 1);
|
||||||
putenv_all(old_env);
|
putenv_all(old_env);
|
||||||
free_strings(old_env);
|
free(old_env); /* not free_strings()! */
|
||||||
clean_up_and_ret1:
|
clean_up_and_ret1:
|
||||||
free(argv_expanded);
|
free(argv_expanded);
|
||||||
IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
|
IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
|
||||||
@ -1915,12 +1926,11 @@ static int run_pipe(struct pipe *pi)
|
|||||||
|
|
||||||
for (i = 0; i < pi->num_cmds; i++) {
|
for (i = 0; i < pi->num_cmds; i++) {
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
/* Avoid confusion WHAT is volatile. Pointer is volatile,
|
volatile nommu_save_t nommu_save;
|
||||||
* not the stuff it points to. */
|
nommu_save.new_env = NULL;
|
||||||
typedef char **ppchar_t;
|
nommu_save.old_env = NULL;
|
||||||
volatile ppchar_t shared_across_vfork = NULL;
|
nommu_save.argv = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
command = &(pi->cmds[i]);
|
command = &(pi->cmds[i]);
|
||||||
if (command->argv) {
|
if (command->argv) {
|
||||||
debug_printf_exec(": pipe member '%s' '%s'...\n", command->argv[0], command->argv[1]);
|
debug_printf_exec(": pipe member '%s' '%s'...\n", command->argv[0], command->argv[1]);
|
||||||
@ -1966,15 +1976,18 @@ static int run_pipe(struct pipe *pi)
|
|||||||
set_jobctrl_sighandler(SIG_DFL);
|
set_jobctrl_sighandler(SIG_DFL);
|
||||||
set_misc_sighandler(SIG_DFL);
|
set_misc_sighandler(SIG_DFL);
|
||||||
signal(SIGCHLD, SIG_DFL);
|
signal(SIGCHLD, SIG_DFL);
|
||||||
/* comment how it sets env????
|
/* Stores to nommu_save list of env vars putenv'ed
|
||||||
for single_and_fg, it's already set yes? */
|
* (NOMMU, on MMU we don't need that) */
|
||||||
pseudo_exec((char ***) &shared_across_vfork, command, argv_expanded);
|
/* cast away volatility... */
|
||||||
|
pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
|
||||||
/* pseudo_exec() does not return */
|
/* pseudo_exec() does not return */
|
||||||
}
|
}
|
||||||
/* parent */
|
/* parent */
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
//BUG: does not restore OLD env var contents
|
/* Clean up after vforked child */
|
||||||
free_strings_and_unsetenv((char **)shared_across_vfork, 1);
|
free(nommu_save.argv);
|
||||||
|
free_strings_and_unsetenv(nommu_save.new_env, 1);
|
||||||
|
putenv_all(nommu_save.old_env);
|
||||||
#endif
|
#endif
|
||||||
free(argv_expanded);
|
free(argv_expanded);
|
||||||
argv_expanded = NULL;
|
argv_expanded = NULL;
|
||||||
@ -2829,6 +2842,7 @@ static int set_local_var(char *str, int flg_export)
|
|||||||
free(str);
|
free(str);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
|
||||||
unsetenv(str); /* just in case */
|
unsetenv(str); /* just in case */
|
||||||
*value = '=';
|
*value = '=';
|
||||||
if (strcmp(cur->varstr, str) == 0) {
|
if (strcmp(cur->varstr, str) == 0) {
|
||||||
@ -2858,8 +2872,10 @@ static int set_local_var(char *str, int flg_export)
|
|||||||
exp:
|
exp:
|
||||||
if (flg_export)
|
if (flg_export)
|
||||||
cur->flg_export = 1;
|
cur->flg_export = 1;
|
||||||
if (cur->flg_export)
|
if (cur->flg_export) {
|
||||||
|
debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr);
|
||||||
return putenv(cur->varstr);
|
return putenv(cur->varstr);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2879,9 +2895,10 @@ static void unset_local_var(const char *name)
|
|||||||
bb_error_msg("%s: readonly variable", name);
|
bb_error_msg("%s: readonly variable", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* prev is ok to use here because 1st variable, HUSH_VERSION,
|
/* prev is ok to use here because 1st variable, HUSH_VERSION,
|
||||||
* is ro, and we cannot reach this code on the 1st pass */
|
* is ro, and we cannot reach this code on the 1st pass */
|
||||||
prev->next = cur->next;
|
prev->next = cur->next;
|
||||||
|
debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
|
||||||
unsetenv(cur->varstr);
|
unsetenv(cur->varstr);
|
||||||
if (!cur->max_len)
|
if (!cur->max_len)
|
||||||
free(cur->varstr);
|
free(cur->varstr);
|
||||||
@ -3467,11 +3484,9 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
|
|||||||
endch = ")";
|
endch = ")";
|
||||||
command->subshell = 1;
|
command->subshell = 1;
|
||||||
}
|
}
|
||||||
#if 0 /* TODO function support */
|
//TODO if (ch == 'F') { /* function definition */
|
||||||
if (ch == 'F') { /* function definition */
|
// command->subshell = 2;
|
||||||
command->subshell = 2;
|
// }
|
||||||
}
|
|
||||||
#endif
|
|
||||||
rcode = parse_stream(dest, &sub, input, endch);
|
rcode = parse_stream(dest, &sub, input, endch);
|
||||||
if (rcode == 0) {
|
if (rcode == 0) {
|
||||||
done_word(dest, &sub); /* finish off the final word in the subcontext */
|
done_word(dest, &sub); /* finish off the final word in the subcontext */
|
||||||
@ -4175,6 +4190,7 @@ int hush_main(int argc, char **argv)
|
|||||||
/* Deal with HUSH_VERSION */
|
/* Deal with HUSH_VERSION */
|
||||||
G.shell_ver = const_shell_ver; /* copying struct here */
|
G.shell_ver = const_shell_ver; /* copying struct here */
|
||||||
G.top_var = &G.shell_ver;
|
G.top_var = &G.shell_ver;
|
||||||
|
debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
|
||||||
unsetenv("HUSH_VERSION"); /* in case it exists in initial env */
|
unsetenv("HUSH_VERSION"); /* in case it exists in initial env */
|
||||||
/* Initialize our shell local variables with the values
|
/* Initialize our shell local variables with the values
|
||||||
* currently living in the environment */
|
* currently living in the environment */
|
||||||
@ -4191,6 +4207,7 @@ int hush_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
|
debug_printf_env("putenv '%s'\n", hush_version_str);
|
||||||
putenv((char *)hush_version_str); /* reinstate HUSH_VERSION */
|
putenv((char *)hush_version_str); /* reinstate HUSH_VERSION */
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING
|
#if ENABLE_FEATURE_EDITING
|
||||||
@ -4415,10 +4432,10 @@ static int builtin_exec(char **argv)
|
|||||||
return EXIT_SUCCESS; /* bash does this */
|
return EXIT_SUCCESS; /* bash does this */
|
||||||
{
|
{
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
char **ptrs2free = NULL;
|
nommu_save_t dummy;
|
||||||
#endif
|
#endif
|
||||||
// FIXME: if exec fails, bash does NOT exit! We do...
|
// FIXME: if exec fails, bash does NOT exit! We do...
|
||||||
pseudo_exec_argv(&ptrs2free, argv + 1, 0, NULL);
|
pseudo_exec_argv(&dummy, argv + 1, 0, NULL);
|
||||||
/* never returns */
|
/* never returns */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4462,6 +4479,7 @@ static int builtin_export(char **argv)
|
|||||||
var = get_local_var(name);
|
var = get_local_var(name);
|
||||||
if (var) {
|
if (var) {
|
||||||
var->flg_export = 1;
|
var->flg_export = 1;
|
||||||
|
debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
|
||||||
putenv(var->varstr);
|
putenv(var->varstr);
|
||||||
}
|
}
|
||||||
/* bash does not return an error when trying to export
|
/* bash does not return an error when trying to export
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
a=a
|
a=b
|
||||||
a=a
|
a=b
|
||||||
a=a
|
a=b
|
||||||
OK
|
OK
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
export a=a
|
export a=b
|
||||||
|
|
||||||
# external program
|
# external program
|
||||||
a=b /bin/true
|
a=c /bin/true
|
||||||
env | grep ^a=
|
env | grep ^a=
|
||||||
|
|
||||||
# builtin
|
# builtin
|
||||||
a=b true
|
a=d true
|
||||||
env | grep ^a=
|
env | grep ^a=
|
||||||
|
|
||||||
# exec with redirection only
|
# exec with redirection only
|
||||||
# in bash, this leaks!
|
# in bash, this leaks!
|
||||||
a=b exec 1>&1
|
a=e exec 1>&1
|
||||||
env | grep ^a=
|
env | grep ^a=
|
||||||
|
|
||||||
echo OK
|
echo OK
|
||||||
|
Loading…
Reference in New Issue
Block a user