|
@@ -127,6 +127,7 @@
|
|
|
#endif
|
|
|
#endif
|
|
|
#define SPECIAL_VAR_SYMBOL 03
|
|
|
+#define SUBSTED_VAR_SYMBOL 04
|
|
|
#ifndef __U_BOOT__
|
|
|
#define FLAG_EXIT_FROM_LOOP 1
|
|
|
#define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */
|
|
@@ -499,6 +500,7 @@ static void remove_bg_job(struct pipe *pi);
|
|
|
/* local variable support */
|
|
|
static char **make_list_in(char **inp, char *name);
|
|
|
static char *insert_var_value(char *inp);
|
|
|
+static char *insert_var_value_sub(char *inp, int tag_subst);
|
|
|
|
|
|
#ifndef __U_BOOT__
|
|
|
/* Table of built-in functions. They can be forked or not, depending on
|
|
@@ -3088,6 +3090,21 @@ int parse_stream(o_string *dest, struct p_context *ctx,
|
|
|
return 1;
|
|
|
break;
|
|
|
#endif
|
|
|
+ case SUBSTED_VAR_SYMBOL:
|
|
|
+ dest->nonnull = 1;
|
|
|
+ while (ch = b_getch(input), ch != EOF &&
|
|
|
+ ch != SUBSTED_VAR_SYMBOL) {
|
|
|
+ debug_printf("subst, pass=%d\n", ch);
|
|
|
+ if (input->__promptme == 0)
|
|
|
+ return 1;
|
|
|
+ b_addchr(dest, ch);
|
|
|
+ }
|
|
|
+ debug_printf("subst, term=%d\n", ch);
|
|
|
+ if (ch == EOF) {
|
|
|
+ syntax();
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
default:
|
|
|
syntax(); /* this is really an internal logic error */
|
|
|
return 1;
|
|
@@ -3129,6 +3146,10 @@ void update_ifs_map(void)
|
|
|
mapset((uchar *)"\\$'\"`", 3); /* never flow through */
|
|
|
mapset((uchar *)"<>;&|(){}#", 1); /* flow through if quoted */
|
|
|
#else
|
|
|
+ {
|
|
|
+ uchar subst[2] = {SUBSTED_VAR_SYMBOL, 0};
|
|
|
+ mapset(subst, 3); /* never flow through */
|
|
|
+ }
|
|
|
mapset((uchar *)"\\$'\"", 3); /* never flow through */
|
|
|
mapset((uchar *)";&|#", 1); /* flow through if quoted */
|
|
|
#endif
|
|
@@ -3467,6 +3488,11 @@ final_return:
|
|
|
#endif
|
|
|
|
|
|
static char *insert_var_value(char *inp)
|
|
|
+{
|
|
|
+ return insert_var_value_sub(inp, 0);
|
|
|
+}
|
|
|
+
|
|
|
+static char *insert_var_value_sub(char *inp, int tag_subst)
|
|
|
{
|
|
|
int res_str_len = 0;
|
|
|
int len;
|
|
@@ -3474,19 +3500,46 @@ static char *insert_var_value(char *inp)
|
|
|
char *p, *p1, *res_str = NULL;
|
|
|
|
|
|
while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
|
|
|
+ /* check the beginning of the string for normal charachters */
|
|
|
if (p != inp) {
|
|
|
+ /* copy any charachters to the result string */
|
|
|
len = p - inp;
|
|
|
res_str = xrealloc(res_str, (res_str_len + len));
|
|
|
strncpy((res_str + res_str_len), inp, len);
|
|
|
res_str_len += len;
|
|
|
}
|
|
|
inp = ++p;
|
|
|
+ /* find the ending marker */
|
|
|
p = strchr(inp, SPECIAL_VAR_SYMBOL);
|
|
|
*p = '\0';
|
|
|
+ /* look up the value to substitute */
|
|
|
if ((p1 = lookup_param(inp))) {
|
|
|
- len = res_str_len + strlen(p1);
|
|
|
+ if (tag_subst)
|
|
|
+ len = res_str_len + strlen(p1) + 2;
|
|
|
+ else
|
|
|
+ len = res_str_len + strlen(p1);
|
|
|
res_str = xrealloc(res_str, (1 + len));
|
|
|
- strcpy((res_str + res_str_len), p1);
|
|
|
+ if (tag_subst) {
|
|
|
+ /*
|
|
|
+ * copy the variable value to the result
|
|
|
+ * string
|
|
|
+ */
|
|
|
+ strcpy((res_str + res_str_len + 1), p1);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * mark the replaced text to be accepted as
|
|
|
+ * is
|
|
|
+ */
|
|
|
+ res_str[res_str_len] = SUBSTED_VAR_SYMBOL;
|
|
|
+ res_str[res_str_len + 1 + strlen(p1)] =
|
|
|
+ SUBSTED_VAR_SYMBOL;
|
|
|
+ } else
|
|
|
+ /*
|
|
|
+ * copy the variable value to the result
|
|
|
+ * string
|
|
|
+ */
|
|
|
+ strcpy((res_str + res_str_len), p1);
|
|
|
+
|
|
|
res_str_len = len;
|
|
|
}
|
|
|
*p = SPECIAL_VAR_SYMBOL;
|
|
@@ -3550,9 +3603,14 @@ static char * make_string(char ** inp)
|
|
|
char *str = NULL;
|
|
|
int n;
|
|
|
int len = 2;
|
|
|
+ char *noeval_str;
|
|
|
+ int noeval = 0;
|
|
|
|
|
|
+ noeval_str = get_local_var("HUSH_NO_EVAL");
|
|
|
+ if (noeval_str != NULL && *noeval_str != '0' && *noeval_str != '\0')
|
|
|
+ noeval = 1;
|
|
|
for (n = 0; inp[n]; n++) {
|
|
|
- p = insert_var_value(inp[n]);
|
|
|
+ p = insert_var_value_sub(inp[n], noeval);
|
|
|
str = xrealloc(str, (len + strlen(p)));
|
|
|
if (n) {
|
|
|
strcat(str, " ");
|