return NULL;
}
+#if (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT) \
+ || (ENABLE_HUSH_LINENO_VAR || ENABLE_HUSH_GETOPTS)
static void handle_changed_special_names(const char *name, unsigned name_len)
{
if (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT
+ && G_interactive_fd
&& name_len == 3 && name[0] == 'P' && name[1] == 'S'
) {
cmdedit_update_prompt();
#endif
}
}
+#else
+/* Do not even bother evaluating arguments */
+# define handle_changed_special_names(...) ((void)0)
+#endif
/* str holds "NAME=VAL" and is expected to be malloced.
* We take ownership of it.
char *free_me = NULL;
char *eq_sign;
int name_len;
+ int retval;
unsigned local_lvl = (flags >> SETFLAG_VARLVL_SHIFT);
eq_sign = strchr(str, '=');
#endif
if (flags & SETFLAG_EXPORT)
cur->flg_export = 1;
+ retval = 0;
if (cur->flg_export) {
if (flags & SETFLAG_UNEXPORT) {
cur->flg_export = 0;
/* unsetenv was already done */
} else {
- int i;
debug_printf_env("%s: putenv '%s'/%u\n", __func__, cur->varstr, cur->var_nest_level);
- i = putenv(cur->varstr);
- /* only now we can free old exported malloced string */
- free(free_me);
- return i;
+ retval = putenv(cur->varstr);
+ /* fall through to "free(free_me)" -
+ * only now we can free old exported malloced string
+ */
}
}
free(free_me);
handle_changed_special_names(cur->varstr, name_len - 1);
- return 0;
+ return retval;
}
static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
} else {
debug_printf_env("%s: restoring variable '%s'/%u\n", __func__, var->varstr, var->var_nest_level);
}
+ /* Testcase (interactive):
+ * f() { local PS1='\w \$ '; }; f
+ * the below call is needed to notice restored PS1 when f returns.
+ */
+ handle_changed_special_names(var->varstr, endofname(var->varstr) - var->varstr);
var = next;
}
}
#if ENABLE_HUSH_LOOPS
if (ctx->ctx_res_w == RES_FOR) {
if (ctx->word.has_quoted_part
- || !is_well_formed_var_name(command->argv[0], '\0')
+ || endofname(command->argv[0])[0] != '\0'
) {
/* bash says just "not a valid identifier" */
syntax_error("not a valid identifier in for");
if ((ctx.is_assignment == MAYBE_ASSIGNMENT
|| ctx.is_assignment == WORD_IS_KEYWORD)
&& ch == '='
- && is_well_formed_var_name(ctx.word.data, '=')
+ && endofname(ctx.word.data)[0] == '='
) {
ctx.is_assignment = DEFINITELY_ASSIGNMENT;
debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
avoid_fd = 9;
#if ENABLE_HUSH_INTERACTIVE
- if (fd == G.interactive_fd) {
+ if (fd == G_interactive_fd) {
/* Testcase: "ls -l /proc/$$/fd 255>&-" should work */
- G.interactive_fd = xdup_CLOEXEC_and_close(G.interactive_fd, avoid_fd);
- debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G.interactive_fd);
+ G_interactive_fd = xdup_CLOEXEC_and_close(G_interactive_fd, avoid_fd);
+ debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G_interactive_fd);
return 1; /* "we closed fd" */
}
#endif
free(sq);
}
- /* If moved, G.interactive_fd stays on new fd, not restoring it */
+ /* If moved, G_interactive_fd stays on new fd, not restoring it */
}
#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
int i;
#if ENABLE_HUSH_INTERACTIVE
- if (fd == G.interactive_fd)
+ if (fd == G_interactive_fd)
return 1;
#endif
/* If this one of script's fds? */
*cur_pp = cur->next;
/* Free */
if (!cur->max_len) {
+ /* Testcase (interactive):
+ * f() { local PS1='\w \$ '; }; f
+ * we should forget local PS1:
+ */
+ handle_changed_special_names(cur->varstr, endofname(cur->varstr) - cur->varstr);
debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level);
free(cur->varstr);
}
{
do {
char *name = *argv;
- char *name_end = strchrnul(name, '=');
-
- /* So far we do not check that name is valid (TODO?) */
+ const char *name_end = endofname(name);
if (*name_end == '\0') {
struct variable *var, **vpp;
*/
name = xasprintf("%s=", name);
} else {
+ if (*name_end != '=') {
+ bb_error_msg("'%s': bad variable name", name);
+ /* do not parse following argv[]s: */
+ return 1;
+ }
/* (Un)exporting/making local NAME=VALUE */
name = xstrdup(name);
+ /* Testcase: export PS1='\w \$ ' */
+ unbackslash(name);
}
debug_printf_env("%s: set_local_var('%s')\n", __func__, name);
if (set_local_var(name, flags))