diff options
Diffstat (limited to 'common/hush.c')
| -rw-r--r-- | common/hush.c | 107 | 
1 files changed, 101 insertions, 6 deletions
| diff --git a/common/hush.c b/common/hush.c index 1eff182ef..4c84c2f50 100644 --- a/common/hush.c +++ b/common/hush.c @@ -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 @@ -2743,13 +2745,50 @@ static int parse_group(o_string *dest, struct p_context *ctx,  static char *lookup_param(char *src)  {  	char *p; +	char *sep; +	char *default_val = NULL; +	int assign = 0; +	int expand_empty = 0;  	if (!src)  		return NULL; -		p = getenv(src); -		if (!p) -			p = get_local_var(src); +	sep = strchr(src, ':'); + +	if (sep) { +		*sep = '\0'; +		if (*(sep + 1) == '-') +			default_val = sep+2; +		if (*(sep + 1) == '=') { +			default_val = sep+2; +			assign = 1; +		} +		if (*(sep + 1) == '+') { +			default_val = sep+2; +			expand_empty = 1; +		} +	} + +	p = getenv(src); +	if (!p) +		p = get_local_var(src); + +	if (!p || strlen(p) == 0) { +		p = default_val; +		if (assign) { +			char *var = malloc(strlen(src)+strlen(default_val)+2); +			if (var) { +				sprintf(var, "%s=%s", src, default_val); +				set_local_var(var, 0); +			} +			free(var); +		} +	} else if (expand_empty) { +		p += strlen(p); +	} + +	if (sep) +		*sep = ':';  	return p;  } @@ -3051,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; @@ -3092,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 @@ -3431,25 +3489,57 @@ final_return:  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;  	int done = 0;  	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; @@ -3513,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, " "); |