diff options
Diffstat (limited to 'common/hush.c')
| -rw-r--r-- | common/hush.c | 85 | 
1 files changed, 78 insertions, 7 deletions
| diff --git a/common/hush.c b/common/hush.c index eeb970cd5..47680edec 100644 --- a/common/hush.c +++ b/common/hush.c @@ -290,6 +290,7 @@ char **global_argv;  unsigned int global_argc;  #endif  unsigned int last_return_code; +int nesting_level;  #ifndef __U_BOOT__  extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */  #endif @@ -416,7 +417,9 @@ static int b_check_space(o_string *o, int len);  static int b_addchr(o_string *o, int ch);  static void b_reset(o_string *o);  static int b_addqchr(o_string *o, int ch, int quote); +#ifndef __U_BOOT__  static int b_adduint(o_string *o, unsigned int i); +#endif  /*  in_str manipulations: */  static int static_get(struct in_str *i);  static int static_peek(struct in_str *i); @@ -936,6 +939,7 @@ char *simple_itoa(unsigned int i)  	return p + 1;  } +#ifndef __U_BOOT__  static int b_adduint(o_string *o, unsigned int i)  {  	int r; @@ -944,6 +948,7 @@ static int b_adduint(o_string *o, unsigned int i)  	do r=b_addchr(o, *p++); while (r==0 && *p);  	return r;  } +#endif  static int static_get(struct in_str *i)  { @@ -1921,6 +1926,10 @@ static int run_list_real(struct pipe *pi)  		}  		last_return_code=rcode;  #else +		if (rcode < -1) { +			last_return_code = -rcode - 2; +			return -2;	/* exit */ +		}  		last_return_code=(rcode == 0) ? 0 : 1;  #endif  #ifndef __U_BOOT__ @@ -2145,6 +2154,10 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)  }  #endif +#ifdef __U_BOOT__ +static char *get_dollar_var(char ch); +#endif +  /* This is used to get/check local shell variables */  static char *get_local_var(const char *s)  { @@ -2152,6 +2165,12 @@ static char *get_local_var(const char *s)  	if (!s)  		return NULL; + +#ifdef __U_BOOT__ +	if (*s == '$') +		return get_dollar_var(s[1]); +#endif +  	for (cur = top_vars; cur; cur=cur->next)  		if(strcmp(cur->name, s)==0)  			return cur->value; @@ -2168,12 +2187,19 @@ static int set_local_var(const char *s, int flg_export)  	int result=0;  	struct variables *cur; +#ifdef __U_BOOT__ +	/* might be possible! */ +	if (!isalpha(*s)) +		return -1; +#endif +  	name=strdup(s);  #ifdef __U_BOOT__  	if (getenv(name) != NULL) {  		printf ("ERROR: "  				"There is a global environment variable with the same name.\n"); +		free(name);  		return -1;  	}  #endif @@ -2278,7 +2304,10 @@ static void unset_local_var(const char *name)  static int is_assignment(const char *s)  { -	if (s==NULL || !isalpha(*s)) return 0; +	if (s == NULL) +		return 0; + +	if (!isalpha(*s)) return 0;  	++s;  	while(isalnum(*s) || *s=='_') ++s;  	return *s=='='; @@ -2749,15 +2778,35 @@ static int parse_group(o_string *dest, struct p_context *ctx,   * see the bash man page under "Parameter Expansion" */  static char *lookup_param(char *src)  { -	char *p=NULL; -	if (src) { +	char *p; + +	if (!src) +		return NULL; +  		p = getenv(src);  		if (!p)  			p = get_local_var(src); -	} +  	return p;  } +#ifdef __U_BOOT__ +static char *get_dollar_var(char ch) +{ +	static char buf[40]; + +	buf[0] = '\0'; +	switch (ch) { +		case '?': +			sprintf(buf, "%u", (unsigned int)last_return_code); +			break; +		default: +			return NULL; +	} +	return buf; +} +#endif +  /* return code: 0 for OK, 1 for syntax error */  static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)  { @@ -2799,7 +2848,15 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i  			break;  #endif  		case '?': +#ifndef __U_BOOT__  			b_adduint(dest,last_return_code); +#else +			ctx->child->sp++; +			b_addchr(dest, SPECIAL_VAR_SYMBOL); +			b_addchr(dest, '$'); +			b_addchr(dest, '?'); +			b_addchr(dest, SPECIAL_VAR_SYMBOL); +#endif  			advance = 1;  			break;  #ifndef __U_BOOT__ @@ -2885,8 +2942,11 @@ int parse_stream(o_string *dest, struct p_context *ctx,  		if (input->__promptme == 0) return 1;  #endif  		next = (ch == '\n') ? 0 : b_peek(input); -		debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d\n", -			ch,ch,m,dest->quote); + +		debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n", +			ch >= ' ' ? ch : '.', ch, m, +			dest->quote, ctx->stack == NULL ? '*' : '.'); +  		if (m==0 || ((m==1 || m==2) && dest->quote)) {  			b_addqchr(dest, ch, dest->quote);  		} else { @@ -3107,7 +3167,18 @@ int parse_stream_outer(struct in_str *inp, int flag)  #ifndef __U_BOOT__  			run_list(ctx.list_head);  #else -			if (((code = run_list(ctx.list_head)) == -1)) +			code = run_list(ctx.list_head); +			if (code == -2) {	/* exit */ +				b_free(&temp); +				code = 0; +				/* XXX hackish way to not allow exit from main loop */ +				if (inp->peek == file_peek) { +					printf("exit not allowed from main input shell.\n"); +					continue; +				} +				break; +			} +			if (code == -1)  			    flag_repeat = 0;  #endif  		} else { |