mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* hush fixes and cleanups
@ 2012-04-30 11:19 Sascha Hauer
  2012-04-30 11:19 ` [PATCH 01/13] hush: safe indention level by continueing a loop Sascha Hauer
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

The following series generally cleans up the hush code and fixes
some longstanding bugs.

Since busybox hush has evolved a lot (looks completely different than
our version) and U-Boots hush version does not evolve much (so no useful
commits there) it's no longer worth to keep the original coding style,
so this series cleans up the coding style making it better readable.

Also some longstanding bugs are fixed. It is now possible to echo ' and "
to the console. These quotes were either removed or were printed with
the preceeding \ to the console. Also the quotes from the stream are now
removed at the end of parsing which means that a

me=sascha; echo "hello $me"

now correctly passed as

argv[1] = "hello sascha"

instead of

argv[1] = "hello", argv[2] = "sascha".

Also the bug that hush expands glob wildcards at the beginning of a
script instead of right before executing a command is fixed. This
makes the 'hush hack' script in the default environment unnecessary.

Sascha

----------------------------------------------------------------
Sascha Hauer (13):
      hush: safe indention level by continueing a loop
      hush: safe an indention level by continueing a loop
      hush: cleanup coding style
      hush: remove bogus 'else'
      hush: run_pipe_real must have num_progs == 1
      hush: run_pipe_real: bail out early to safe an indention level
      hush: remove quotes at end of processing
      hush: simplify globhack
      hush: pass GLOB_NOCHECK to glob
      glob: activate GLOB_NOCHECK flag
      hush: Fix globbing
      hush: allow to run interactive shell in do_sh
      defaultenv: remove now unnecessary hush-hack

 common/hush.c            |  779 ++++++++++++++++++++++++++++------------------
 defaultenv/bin/hush_hack |    1 -
 defaultenv/bin/init      |    5 +-
 lib/glob.c               |   10 +-
 4 files changed, 476 insertions(+), 319 deletions(-)
 delete mode 100644 defaultenv/bin/hush_hack

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/13] hush: safe indention level by continueing a loop
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 02/13] hush: safe an " Sascha Hauer
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |  160 +++++++++++++++++++++++++++++----------------------------
 1 file changed, 81 insertions(+), 79 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index 2d89f2b..091938d 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1284,95 +1284,97 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 			ch >= ' ' ? ch : '.', ch, m,
 			dest->quote, ctx->stack == NULL ? '*' : '.');
 
-		if (m==0 || ((m==1 || m==2) && dest->quote)) {
+		if (m == 0 || ((m == 1 || m == 2) && dest->quote)) {
 			b_addqchr(dest, ch, dest->quote);
-		} else {
-			if (m==2) {  /* unquoted IFS */
-				if (done_word(dest, ctx)) {
-					return 1;
-				}
-				/* If we aren't performing a substitution, treat a newline as a
-				 * command separator.  */
-				if (end_trigger != '\0' && ch=='\n')
-					done_pipe(ctx,PIPE_SEQ);
-			}
-			if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
-				debug("leaving parse_stream (triggered)\n");
-				return 0;
+			continue;
+		}
+
+		if (m == 2) {  /* unquoted IFS */
+			if (done_word(dest, ctx)) {
+				return 1;
 			}
-			if (m!=2) {
-				switch (ch) {
-				case '#':
-					if (dest->length == 0 && !dest->quote) {
-						while(ch=b_peek(input),ch!=EOF && ch!='\n') {
-							b_getch(input);
-						}
-					} else {
-						b_addqchr(dest, ch, dest->quote);
-					}
-					break;
-				case '\\':
-					if (next == EOF) {
-						syntax();
-						return 1;
-					}
-					b_addqchr(dest, '\\', dest->quote);
-					b_addqchr(dest, b_getch(input), dest->quote);
-					break;
-				case '$':
-					if (handle_dollar(dest, ctx, input)!=0)
-						return 1;
-					break;
-				case '\'':
-					dest->nonnull = 1;
-					while(ch=b_getch(input),ch!=EOF && ch!='\'') {
-						if(input->__promptme == 0)
-							return 1;
-						b_addchr(dest,ch);
-					}
-					if (ch==EOF) {
-						syntax();
-						return 1;
-					}
-					break;
-				case '"':
-					dest->nonnull = 1;
-					dest->quote = !dest->quote;
-					break;
-				case ';':
-					done_word(dest, ctx);
-					done_pipe(ctx,PIPE_SEQ);
-					break;
-				case '&':
-					done_word(dest, ctx);
-					if (next=='&') {
+			/* If we aren't performing a substitution, treat a newline as a
+			 * command separator.  */
+			if (end_trigger != '\0' && ch=='\n')
+				done_pipe(ctx,PIPE_SEQ);
+		}
+		if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
+			debug("leaving parse_stream (triggered)\n");
+			return 0;
+		}
+		if (m != 2) {
+			switch (ch) {
+			case '#':
+				if (dest->length == 0 && !dest->quote) {
+					while (ch = b_peek(input), ch != EOF && ch!='\n') {
 						b_getch(input);
-						done_pipe(ctx,PIPE_AND);
-					} else {
-						syntax_err();
-						return 1;
 					}
-					break;
-				case '|':
-					done_word(dest, ctx);
-					if (next=='|') {
-						b_getch(input);
-						done_pipe(ctx,PIPE_OR);
-					} else {
-						/* we could pick up a file descriptor choice here
-						 * with redirect_opt_num(), but bash doesn't do it.
-						 * "echo foo 2| cat" yields "foo 2". */
-						syntax_err();
+				} else {
+					b_addqchr(dest, ch, dest->quote);
+				}
+				break;
+			case '\\':
+				if (next == EOF) {
+					syntax();
+					return 1;
+				}
+				b_addqchr(dest, '\\', dest->quote);
+				b_addqchr(dest, b_getch(input), dest->quote);
+				break;
+			case '$':
+				if (handle_dollar(dest, ctx, input)!=0)
+					return 1;
+				break;
+			case '\'':
+				dest->nonnull = 1;
+				while (ch = b_getch(input), ch!=EOF && ch != '\'') {
+					if (input->__promptme == 0)
 						return 1;
-					}
-					break;
-				default:
-					syntax();   /* this is really an internal logic error */
+					b_addchr(dest,ch);
+				}
+				if (ch == EOF) {
+					syntax();
+					return 1;
+				}
+				break;
+			case '"':
+				dest->nonnull = 1;
+				dest->quote = !dest->quote;
+				break;
+			case ';':
+				done_word(dest, ctx);
+				done_pipe(ctx, PIPE_SEQ);
+				break;
+			case '&':
+				done_word(dest, ctx);
+				if (next == '&') {
+					b_getch(input);
+					done_pipe(ctx, PIPE_AND);
+				} else {
+					syntax_err();
 					return 1;
 				}
+				break;
+			case '|':
+				done_word(dest, ctx);
+				if (next == '|') {
+					b_getch(input);
+					done_pipe(ctx, PIPE_OR);
+				} else {
+					/* we could pick up a file descriptor choice here
+					 * with redirect_opt_num(), but bash doesn't do it.
+					 * "echo foo 2| cat" yields "foo 2". */
+					syntax_err();
+					return 1;
+				}
+				break;
+			default:
+				syntax();   /* this is really an internal logic error */
+				return 1;
 			}
 		}
 	}
+
 	/* complain if quote?  No, maybe we just finished a command substitution
 	 * that was quoted.  Example:
 	 * $ echo "`cat foo` plus more"
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 02/13] hush: safe an indention level by continueing a loop
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
  2012-04-30 11:19 ` [PATCH 01/13] hush: safe indention level by continueing a loop Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 03/13] hush: cleanup coding style Sascha Hauer
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |  135 +++++++++++++++++++++++++++++----------------------------
 1 file changed, 69 insertions(+), 66 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index 091938d..9b512f9 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1274,7 +1274,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 	 * found.  When recursing, quote state is passed in via dest->quote. */
 
 	debug("parse_stream, end_trigger=%d\n",end_trigger);
-	while ((ch=b_getch(input))!=EOF) {
+	while ((ch = b_getch(input)) != EOF) {
 		m = map[ch];
 		if (input->__promptme == 0)
 			return 1;
@@ -1298,80 +1298,83 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 			if (end_trigger != '\0' && ch=='\n')
 				done_pipe(ctx,PIPE_SEQ);
 		}
+
 		if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
 			debug("leaving parse_stream (triggered)\n");
 			return 0;
 		}
-		if (m != 2) {
-			switch (ch) {
-			case '#':
-				if (dest->length == 0 && !dest->quote) {
-					while (ch = b_peek(input), ch != EOF && ch!='\n') {
-						b_getch(input);
-					}
-				} else {
-					b_addqchr(dest, ch, dest->quote);
-				}
-				break;
-			case '\\':
-				if (next == EOF) {
-					syntax();
-					return 1;
-				}
-				b_addqchr(dest, '\\', dest->quote);
-				b_addqchr(dest, b_getch(input), dest->quote);
-				break;
-			case '$':
-				if (handle_dollar(dest, ctx, input)!=0)
-					return 1;
-				break;
-			case '\'':
-				dest->nonnull = 1;
-				while (ch = b_getch(input), ch!=EOF && ch != '\'') {
-					if (input->__promptme == 0)
-						return 1;
-					b_addchr(dest,ch);
-				}
-				if (ch == EOF) {
-					syntax();
-					return 1;
-				}
-				break;
-			case '"':
-				dest->nonnull = 1;
-				dest->quote = !dest->quote;
-				break;
-			case ';':
-				done_word(dest, ctx);
-				done_pipe(ctx, PIPE_SEQ);
-				break;
-			case '&':
-				done_word(dest, ctx);
-				if (next == '&') {
+
+		if (m == 2)
+			continue;
+
+		switch (ch) {
+		case '#':
+			if (dest->length == 0 && !dest->quote) {
+				while (ch = b_peek(input), ch != EOF && ch!='\n') {
 					b_getch(input);
-					done_pipe(ctx, PIPE_AND);
-				} else {
-					syntax_err();
-					return 1;
 				}
-				break;
-			case '|':
-				done_word(dest, ctx);
-				if (next == '|') {
-					b_getch(input);
-					done_pipe(ctx, PIPE_OR);
-				} else {
-					/* we could pick up a file descriptor choice here
-					 * with redirect_opt_num(), but bash doesn't do it.
-					 * "echo foo 2| cat" yields "foo 2". */
-					syntax_err();
+			} else {
+				b_addqchr(dest, ch, dest->quote);
+			}
+			break;
+		case '\\':
+			if (next == EOF) {
+				syntax();
+				return 1;
+			}
+			b_addqchr(dest, '\\', dest->quote);
+			b_addqchr(dest, b_getch(input), dest->quote);
+			break;
+		case '$':
+			if (handle_dollar(dest, ctx, input)!=0)
+				return 1;
+			break;
+		case '\'':
+			dest->nonnull = 1;
+			while (ch = b_getch(input), ch!=EOF && ch != '\'') {
+				if (input->__promptme == 0)
 					return 1;
-				}
-				break;
-			default:
-				syntax();   /* this is really an internal logic error */
+				b_addchr(dest,ch);
+			}
+			if (ch == EOF) {
+				syntax();
 				return 1;
 			}
+			break;
+		case '"':
+			dest->nonnull = 1;
+			dest->quote = !dest->quote;
+			break;
+		case ';':
+			done_word(dest, ctx);
+			done_pipe(ctx, PIPE_SEQ);
+			break;
+		case '&':
+			done_word(dest, ctx);
+			if (next == '&') {
+				b_getch(input);
+				done_pipe(ctx, PIPE_AND);
+			} else {
+				syntax_err();
+				return 1;
+			}
+			break;
+		case '|':
+			done_word(dest, ctx);
+			if (next == '|') {
+				b_getch(input);
+				done_pipe(ctx, PIPE_OR);
+			} else {
+				/* we could pick up a file descriptor choice here
+				 * with redirect_opt_num(), but bash doesn't do it.
+				 * "echo foo 2| cat" yields "foo 2". */
+				syntax_err();
+				return 1;
+			}
+			break;
+		default:
+			syntax();   /* this is really an internal logic error */
+			return 1;
 		}
 	}
 
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 03/13] hush: cleanup coding style
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
  2012-04-30 11:19 ` [PATCH 01/13] hush: safe indention level by continueing a loop Sascha Hauer
  2012-04-30 11:19 ` [PATCH 02/13] hush: safe an " Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 04/13] hush: remove bogus 'else' Sascha Hauer
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

General coding style cleanup

- add some blank lines
- add whitespaces on on both sides of operators

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |  330 ++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 221 insertions(+), 109 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index 9b512f9..017f96d 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -327,12 +327,15 @@ static int b_check_space(o_string *o, int len)
 
 static int b_addchr(o_string *o, int ch)
 {
-	debug("b_addchr: %c %d %p\n", ch, o->length, o);
+	debug("%s: %c %d %p\n", __func__, ch, o->length, o);
+
 	if (b_check_space(o, 1))
 		return B_NOSPAC;
+
 	o->data[o->length] = ch;
 	o->length++;
 	o->data[o->length] = '\0';
+
 	return 0;
 }
 
@@ -340,7 +343,9 @@ static void b_reset(o_string *o)
 {
 	o->length = 0;
 	o->nonnull = 0;
-	if (o->data != NULL) *o->data = '\0';
+
+	if (o->data != NULL)
+		*o->data = '\0';
 }
 
 static void b_free(o_string *o)
@@ -358,10 +363,12 @@ static int b_addqchr(o_string *o, int ch, int quote)
 {
 	if (quote && strchr("*?[",ch)) {
 		int rc;
+
 		rc = b_addchr(o, '\\');
 		if (rc)
 			return rc;
 	}
+
 	return b_addchr(o, ch);
 }
 
@@ -369,19 +376,22 @@ static int b_adduint(o_string *o, unsigned int i)
 {
 	int r;
 	char *p = simple_itoa(i);
+
 	/* no escape checking necessary */
 	do {
-		r=b_addchr(o, *p++);
-	} while (r==0 && *p);
+		r = b_addchr(o, *p++);
+	} while (r == 0 && *p);
 
 	return r;
 }
 
 static int static_get(struct in_str *i)
 {
-	int ch=*i->p++;
-	if (ch=='\0')
+	int ch = *i->p++;
+
+	if (ch == '\0')
 		return EOF;
+
 	return ch;
 }
 
@@ -413,18 +423,21 @@ static void get_user_input(struct in_str *i)
 	static char the_command[CONFIG_CBSIZE];
 
 	i->__promptme = 1;
+
 	if (i->promptmode == 1) {
 		n = readline(getprompt(), console_buffer, CONFIG_CBSIZE);
 	} else {
 		n = readline(CONFIG_PROMPT_HUSH_PS2, console_buffer, CONFIG_CBSIZE);
 	}
+
 	if (n == -1 ) {
 		i->__promptme = 0;
 		n = 0;
 	}
 
 	console_buffer[n] = '\n';
-	console_buffer[n+1]= '\0';
+	console_buffer[n + 1]= '\0';
+
 	if (i->promptmode == 1) {
 		strcpy(the_command,console_buffer);
 		i->p = the_command;
@@ -433,8 +446,8 @@ static void get_user_input(struct in_str *i)
 			if (strlen(the_command) + strlen(console_buffer)
 			    < CONFIG_CBSIZE) {
 				n = strlen(the_command);
-				the_command[n-1] = ' ';
-				strcpy(&the_command[n],console_buffer);
+				the_command[n - 1] = ' ';
+				strcpy(&the_command[n], console_buffer);
 			}
 			else {
 				the_command[0] = '\n';
@@ -458,18 +471,18 @@ static int file_get(struct in_str *i)
 	ch = 0;
 	/* If there is data waiting, eat it up */
 	if (i->p && *i->p) {
-		ch=*i->p++;
+		ch = *i->p++;
 	} else {
 		/* need to double check i->file because we might be doing something
 		 * more complicated by now, like sourcing or substituting. */
-			while(! i->p  || strlen(i->p)==0 ) {
+			while (!i->p  || strlen(i->p) == 0 ) {
 				get_user_input(i);
 			}
-			i->promptmode=2;
+			i->promptmode = 2;
 			if (i->p && *i->p) {
-				ch=*i->p++;
+				ch = *i->p++;
 			}
-		debug("b_getch: got a %d\n", ch);
+		debug("%s: got a %d\n", __func__, ch);
 	}
 	return ch;
 }
@@ -486,8 +499,8 @@ static void setup_file_in_str(struct in_str *i)
 {
 	i->peek = file_peek;
 	i->get = file_get;
-	i->__promptme=1;
-	i->promptmode=1;
+	i->__promptme = 1;
+	i->promptmode = 1;
 	i->p = NULL;
 }
 
@@ -495,8 +508,8 @@ static void setup_string_in_str(struct in_str *i, const char *s)
 {
 	i->peek = static_peek;
 	i->get = static_get;
-	i->__promptme=1;
-	i->promptmode=1;
+	i->__promptme = 1;
+	i->promptmode = 1;
 	i->p = s;
 }
 
@@ -518,7 +531,7 @@ static int builtin_getopt(struct p_context *ctx, struct child_prog *child)
 	getopt_context_store(&gc);
 
 	if (!ctx->options_parsed) {
-		while((opt = getopt(ctx->global_argc, ctx->global_argv, optstring)) > 0) {
+		while ((opt = getopt(ctx->global_argc, ctx->global_argv, optstring)) > 0) {
 			o = xzalloc(sizeof(*o));
 			o->opt = opt;
 			o->optarg = xstrdup(optarg);
@@ -588,17 +601,23 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 	 * pseudo_exec.  "echo foo | read bar" doesn't work on bash, either.
 	 */
 	if (pi->num_progs == 1)
-		child = & (pi->progs[0]);
+		child = &pi->progs[0];
+
 	if (pi->num_progs == 1 && child->group) {
 		int rcode;
+
 		debug("non-subshell grouping\n");
 		rcode = run_list_real(ctx, child->group);
+
 		return rcode;
 	} else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
-		for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ }
-		if (i!=0 && child->argv[i]==NULL) {
+
+		for (i = 0; is_assignment(child->argv[i]); i++)
+			{ /* nothing */ }
+
+		if (i != 0 && child->argv[i] == NULL) {
 			/* assignments, but no command: set the local environment */
-			for (i=0; child->argv[i]!=NULL; i++) {
+			for (i = 0; child->argv[i] != NULL; i++) {
 
 				/* Ok, this case is tricky.  We have to decide if this is a
 				 * local variable, or an already exported variable.  If it is
@@ -606,16 +625,20 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 				 * not exported, we need only set this as a local variable.
 				 * This junk is all to decide whether or not to export this
 				 * variable. */
-				int export_me=0;
+				int export_me = 0;
 				char *name, *value;
+
 				name = xstrdup(child->argv[i]);
 				debug("Local environment set: %s\n", name);
 				value = strchr(name, '=');
+
 				if (value)
-					*value=0;
+					*value = 0;
+
 				free(name);
 				p = insert_var_value(child->argv[i]);
 				set_local_var(p, export_me);
+
 				if (p != child->argv[i])
 					free(p);
 			}
@@ -624,6 +647,7 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 		for (i = 0; is_assignment(child->argv[i]); i++) {
 			p = insert_var_value(child->argv[i]);
 			set_local_var(p, 0);
+
 			if (p != child->argv[i]) {
 				child->sp--;
 				free(p);
@@ -632,10 +656,12 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 		if (child->sp) {
 			char * str = NULL;
 			struct p_context ctx1;
+
 			str = make_string((child->argv + i));
 			parse_string_outer(&ctx1, str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
 			release_context(&ctx1);
 			free(str);
+
 			return last_return_code;
 		}
 #ifdef CONFIG_HUSH_GETOPT
@@ -657,7 +683,8 @@ static int run_list_real(struct p_context *ctx, struct pipe *pi)
 	int rcode=0, flag_skip=1;
 	int flag_restore = 0;
 	int if_code=0, next_if_code=0;  /* need double-buffer to handle elif */
-	reserved_style rmode, skip_more_in_this_rmode=RES_XXXX;
+	reserved_style rmode, skip_more_in_this_rmode = RES_XXXX;
+
 	/* check syntax for "for" */
 	for (rpipe = pi; rpipe; rpipe = rpipe->next) {
 		if ((rpipe->r_mode == RES_IN ||
@@ -688,26 +715,35 @@ static int run_list_real(struct p_context *ctx, struct pipe *pi)
 				}
 		}
 		rmode = pi->r_mode;
-		debug("rmode=%d  if_code=%d  next_if_code=%d skip_more=%d\n", rmode, if_code, next_if_code, skip_more_in_this_rmode);
+		debug("rmode=%d  if_code=%d  next_if_code=%d skip_more=%d\n",
+				rmode, if_code, next_if_code, skip_more_in_this_rmode);
 		if (rmode == skip_more_in_this_rmode && flag_skip) {
-			if (pi->followup == PIPE_SEQ) flag_skip=0;
+			if (pi->followup == PIPE_SEQ)
+				flag_skip=0;
 			continue;
 		}
+
 		flag_skip = 1;
 		skip_more_in_this_rmode = RES_XXXX;
+
 		if (rmode == RES_THEN || rmode == RES_ELSE)
 			if_code = next_if_code;
+
 		if (rmode == RES_THEN &&  if_code)
 			continue;
+
 		if (rmode == RES_ELSE && !if_code)
 			continue;
+
 		if (rmode == RES_ELIF && !if_code)
 			break;
+
 		if (rmode == RES_FOR && pi->num_progs) {
 			if (!list) {
 				/* if no variable values after "in" we skip "for" */
 				if (!pi->next->progs->argv)
 					continue;
+
 				/* create list of variable values */
 				list = make_list_in(pi->next->progs->argv,
 					pi->progs->argv[0]);
@@ -732,35 +768,45 @@ static int run_list_real(struct p_context *ctx, struct pipe *pi)
 		}
 		if (rmode == RES_IN)
 			continue;
+
 		if (rmode == RES_DO) {
 			if (!flag_rep)
 				continue;
 		}
-		if ((rmode == RES_DONE)) {
+
+		if (rmode == RES_DONE) {
 			if (flag_rep) {
 				flag_restore = 1;
 			} else {
 				rpipe = NULL;
 			}
 		}
+
 		if (pi->num_progs == 0)
 			continue;
+
 		rcode = run_pipe_real(ctx, pi);
 		debug("run_pipe_real returned %d\n",rcode);
+
 		if (rcode < -1) {
 			last_return_code = -rcode - 2;
 			return rcode;	/* exit */
 		}
-		last_return_code=rcode;
-		if ( rmode == RES_IF || rmode == RES_ELIF )
-			next_if_code=rcode;  /* can be overwritten a number of times */
+
+		last_return_code = rcode;
+
+		if (rmode == RES_IF || rmode == RES_ELIF )
+			next_if_code = rcode;  /* can be overwritten a number of times */
+
 		if (rmode == RES_WHILE)
 			flag_rep = !last_return_code;
+
 		if (rmode == RES_UNTIL)
 			flag_rep = last_return_code;
-		if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||
-		     (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )
-			skip_more_in_this_rmode=rmode;
+
+		if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR) ||
+		     (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND) )
+			skip_more_in_this_rmode = rmode;
 	}
 	return rcode;
 }
@@ -769,8 +815,8 @@ static int run_list_real(struct p_context *ctx, struct pipe *pi)
 /* broken, of course, but OK for testing */
 static char *indenter(int i)
 {
-	static char blanks[]="                                    ";
-	return &blanks[sizeof(blanks)-i-1];
+	static char blanks[] = "                                    ";
+	return &blanks[sizeof(blanks) - i - 1];
 }
 #endif
 
@@ -779,17 +825,20 @@ static int free_pipe(struct pipe *pi, int indent)
 {
 	char **p;
 	struct child_prog *child;
-	int a, i, ret_code=0;
+	int a, i, ret_code = 0;
+
+	for (i = 0; i < pi->num_progs; i++) {
 
-	for (i=0; i<pi->num_progs; i++) {
 		child = &pi->progs[i];
-		final_printf("%s  command %d:\n",indenter(indent),i);
+		final_printf("%s  command %d:\n", indenter(indent), i);
+
 		if (child->argv) {
-			for (a=0,p=child->argv; *p; a++,p++) {
-				final_printf("%s   argv[%d] = %s\n",indenter(indent),a,*p);
+			for (a = 0,p = child->argv; *p; a++,p++) {
+				final_printf("%s   argv[%d] = %s\n",
+						indenter(indent),a,*p);
 			}
 			globfree(&child->glob_result);
-			child->argv=NULL;
+			child->argv = NULL;
 		} else if (child->group) {
 			ret_code = free_pipe_list(child->group,indent+3);
 			final_printf("%s   end group\n",indenter(indent));
@@ -797,21 +846,24 @@ static int free_pipe(struct pipe *pi, int indent)
 			final_printf("%s   (nil)\n",indenter(indent));
 		}
 	}
+
 	free(pi->progs);   /* children are an array, they get freed all at once */
-	pi->progs=NULL;
+	pi->progs = NULL;
+
 	return ret_code;
 }
 
 static int free_pipe_list(struct pipe *head, int indent)
 {
-	int rcode=0;   /* if list has no members */
+	int rcode = 0;   /* if list has no members */
 	struct pipe *pi, *next;
-	for (pi=head; pi; pi=next) {
+
+	for (pi = head; pi; pi = next) {
 		final_printf("%s pipe reserved mode %d\n", indenter(indent), pi->r_mode);
 		rcode = free_pipe(pi, indent);
 		final_printf("%s pipe followup code %d\n", indenter(indent), pi->followup);
-		next=pi->next;
-		pi->next=NULL;
+		next = pi->next;
+		pi->next = NULL;
 		free(pi);
 	}
 	return rcode;
@@ -826,15 +878,18 @@ static int free_pipe_list(struct pipe *head, int indent)
  */
 static int globhack(const char *src, int flags, glob_t *pglob)
 {
-	int cnt=0, pathc;
+	int cnt = 0, pathc;
 	const char *s;
 	char *dest;
 
-	for (cnt=1, s=src; s && *s; s++) {
-		if (*s == '\\' && strchr("*[?", *(s + 1))) s++;
+	for (cnt = 1, s = src; s && *s; s++) {
+		if (*s == '\\' && strchr("*[?", *(s + 1)))
+			s++;
 		cnt++;
 	}
+
 	dest = xmalloc(cnt);
+
 	if (!(flags & GLOB_APPEND)) {
 		globfree(pglob);
 		pglob->gl_pathv = NULL;
@@ -842,14 +897,18 @@ static int globhack(const char *src, int flags, glob_t *pglob)
 		pglob->gl_offs = 0;
 	}
 	pathc = ++pglob->gl_pathc;
-	pglob->gl_pathv = xrealloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv));
-	pglob->gl_pathv[pathc-1] = dest;
+	pglob->gl_pathv = xrealloc(pglob->gl_pathv, (pathc + 1) * sizeof(*pglob->gl_pathv));
+	pglob->gl_pathv[pathc - 1] = dest;
 	pglob->gl_pathv[pathc] = NULL;
-	for (s=src; s && *s; s++, dest++) {
-		if (*s == '\\' && strchr("*[?", *(s + 1))) s++;
+
+	for (s = src; s && *s; s++, dest++) {
+		if (*s == '\\' && strchr("*[?", *(s + 1)))
+			s++;
 		*dest = *s;
 	}
-	*dest='\0';
+
+	*dest = '\0';
+
 	return 0;
 }
 
@@ -858,7 +917,8 @@ static int glob_needed(const char *s)
 {
 #ifdef CONFIG_GLOB
 	for (; *s; s++) {
-		if (*s == '\\') s++;
+		if (*s == '\\')
+			s++;
 		if (strchr("*[?",*s))
 			return 1;
 	}
@@ -895,7 +955,9 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
 	if (gr != 0) { /* GLOB_ABORTED ? */
 		error_msg("glob(3) error %d",gr);
 	}
+
 	/* globprint(glob_target); */
+
 	return gr;
 }
 
@@ -909,7 +971,8 @@ static int run_list(struct p_context *ctx, struct pipe *pi)
 	/* free_pipe_list has the side effect of clearing memory
 	 * In the long run that function can be merged with run_list_real,
 	 * but doing that now would hobble the debugging effort. */
-	free_pipe_list(pi,0);
+	free_pipe_list(pi, 0);
+
 	return rcode;
 }
 
@@ -955,26 +1018,30 @@ static int is_assignment(const char *s)
 
 	if (!isalpha(*s))
 		return 0;
+
 	++s;
+
 	while(isalnum(*s) || *s=='_' || *s=='.')
 		++s;
+
 	return *s=='=';
 }
 
 
-static struct pipe *new_pipe(void) {
-	return (struct pipe *)xzalloc(sizeof(struct pipe));
+static struct pipe *new_pipe(void)
+{
+	return xzalloc(sizeof(struct pipe));
 }
 
 static void initialize_context(struct p_context *ctx)
 {
-	ctx->pipe=NULL;
-	ctx->child=NULL;
-	ctx->list_head=new_pipe();
-	ctx->pipe=ctx->list_head;
-	ctx->w=RES_NONE;
-	ctx->stack=NULL;
-	ctx->old_flag=0;
+	ctx->pipe = NULL;
+	ctx->child = NULL;
+	ctx->list_head = new_pipe();
+	ctx->pipe = ctx->list_head;
+	ctx->w = RES_NONE;
+	ctx->stack = NULL;
+	ctx->old_flag = 0;
 	ctx->options_parsed = 0;
 	INIT_LIST_HEAD(&ctx->options);
 	done_command(ctx);   /* creates the memory for working child */
@@ -1025,44 +1092,56 @@ static struct reserved_combo reserved_list[] = {
 static int reserved_word(o_string *dest, struct p_context *ctx)
 {
 	struct reserved_combo *r;
-	for (r=reserved_list;
-		r<reserved_list+NRES; r++) {
+
+	for (r = reserved_list; r < reserved_list + NRES; r++) {
 		if (strcmp(dest->data, r->literal) == 0) {
+
 			debug("found reserved word %s, code %d\n",r->literal,r->code);
+
 			if (r->flag & FLAG_START) {
 				struct p_context *new = xmalloc(sizeof(struct p_context));
+
 				debug("push stack\n");
+
 				if (ctx->w == RES_IN || ctx->w == RES_FOR) {
 					syntax();
 					free(new);
 					ctx->w = RES_SNTX;
 					b_reset(dest);
+
 					return 1;
 				}
 				*new = *ctx;   /* physical copy */
 				initialize_context(ctx);
-				ctx->stack=new;
-			} else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
+				ctx->stack = new;
+			} else if (ctx->w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
 				syntax();
 				ctx->w = RES_SNTX;
 				b_reset(dest);
 				return 1;
 			}
-			ctx->w=r->code;
+
+			ctx->w = r->code;
 			ctx->old_flag = r->flag;
+
 			if (ctx->old_flag & FLAG_END) {
 				struct p_context *old;
+
 				debug("pop stack\n");
+
 				done_pipe(ctx,PIPE_SEQ);
 				old = ctx->stack;
 				old->child->group = ctx->list_head;
 				*ctx = *old;   /* physical copy */
 				free(old);
 			}
-			b_reset (dest);
+
+			b_reset(dest);
+
 			return 1;
 		}
 	}
+
 	return 0;
 }
 
@@ -1070,11 +1149,11 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
  * Syntax or xglob errors return 1. */
 static int done_word(o_string *dest, struct p_context *ctx)
 {
-	struct child_prog *child=ctx->child;
+	struct child_prog *child = ctx->child;
 	glob_t *glob_target;
 	int gr, flags = 0;
 
-	debug("done_word: %s %p\n", dest->data, child);
+	debug("%s: %s %p\n", __func__, dest->data, child);
 	if (dest->length == 0 && !dest->nonnull) {
 		debug("  true null, ignored\n");
 		return 0;
@@ -1086,7 +1165,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
 	if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) {
 		debug("checking %s for reserved-ness\n",dest->data);
 		if (reserved_word(dest,ctx))
-			return ctx->w==RES_SNTX;
+			return ctx->w == RES_SNTX;
 	}
 
 	glob_target = &child->glob_result;
@@ -1106,6 +1185,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
 		done_word(dest,ctx);
 		done_pipe(ctx,PIPE_SEQ);
 	}
+
 	return 0;
 }
 
@@ -1118,21 +1198,19 @@ static int done_command(struct p_context *ctx)
 	 * Only real trickiness here is that the uncommitted
 	 * child structure, to which ctx->child points, is not
 	 * counted in pi->num_progs. */
-	struct pipe *pi=ctx->pipe;
-	struct child_prog *prog=ctx->child;
+	struct pipe *pi = ctx->pipe;
+	struct child_prog *prog = ctx->child;
 
-	if (prog && prog->group == NULL
-		 && prog->argv == NULL
-										) {
-		debug("done_command: skipping null command\n");
+	if (prog && prog->group == NULL && prog->argv == NULL) {
+		debug("%s: skipping null command\n", __func__);
 		return 0;
 	} else if (prog) {
 		pi->num_progs++;
-		debug("done_command: num_progs incremented to %d\n",pi->num_progs);
+		debug("%s: num_progs incremented to %d\n", __func__, pi->num_progs);
 	} else {
-		debug("done_command: initializing\n");
+		debug("%s: initializing\n", __func__);
 	}
-	pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));
+	pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs + 1));
 
 	prog = pi->progs + pi->num_progs;
 	prog->glob_result.gl_pathv = NULL;
@@ -1150,15 +1228,26 @@ static int done_command(struct p_context *ctx)
 static int done_pipe(struct p_context *ctx, pipe_style type)
 {
 	struct pipe *new_p;
+
 	done_command(ctx);  /* implicit closure of previous command */
-	debug("done_pipe, type %d\n", type);
+<<<<<<< HEAD
+
+	debug("%s: type %d\n", __func__, type);
+
+=======
+	debug("%s: type %d\n", __func__, type);
+>>>>>>> f5c1f0c... hush use func
 	ctx->pipe->followup = type;
 	ctx->pipe->r_mode = ctx->w;
-	new_p=new_pipe();
+
+	new_p = new_pipe();
+
 	ctx->pipe->next = new_p;
 	ctx->pipe = new_p;
 	ctx->child = NULL;
+
 	done_command(ctx);  /* set up new pipe to accept commands */
+
 	return 0;
 }
 
@@ -1179,7 +1268,9 @@ static const char *lookup_param(char *src)
 static int parse_string(o_string *dest, struct p_context *ctx, const char *src)
 {
 	struct in_str foo;
+
 	setup_string_in_str(&foo, src);
+
 	return parse_stream(dest, ctx, &foo, '\0');
 }
 
@@ -1188,6 +1279,7 @@ 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);
@@ -1203,15 +1295,20 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
 {
 	int advance = 0, i;
 	int ch = input->peek(input);  /* first character after the $ */
-	debug("handle_dollar: ch=%c\n",ch);
+
+	debug("%s: ch=%c\n", __func__, ch);
+
 	if (isalpha(ch)) {
 		b_addchr(dest, SPECIAL_VAR_SYMBOL);
 		ctx->child->sp++;
-		while(ch=b_peek(input),isalnum(ch) || ch=='_' || ch=='.') {
+
+		while (ch = b_peek(input),isalnum(ch) || ch == '_' || ch == '.') {
 			b_getch(input);
 			b_addchr(dest,ch);
 		}
+
 		b_addchr(dest, SPECIAL_VAR_SYMBOL);
+
 	} else if (isdigit(ch)) {
 
 		i = ch - '0';	/* XXX is $0 special? */
@@ -1237,8 +1334,10 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
 			b_addchr(dest, SPECIAL_VAR_SYMBOL);
 			ctx->child->sp++;
 			b_getch(input);
+
 			/* XXX maybe someone will try to escape the '}' */
-			while(ch=b_getch(input),ch!=EOF && ch!='}') {
+
+			while(ch = b_getch(input),ch != EOF && ch != '}') {
 				b_addchr(dest,ch);
 			}
 			if (ch != '}') {
@@ -1258,6 +1357,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
 	 */
 	if (advance)
 		b_getch(input);
+
 	return 0;
 }
 
@@ -1273,16 +1373,18 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 	 * A single-quote triggers a bypass of the main loop until its mate is
 	 * found.  When recursing, quote state is passed in via dest->quote. */
 
-	debug("parse_stream, end_trigger=%d\n",end_trigger);
+	debug("%s: end_trigger=%d\n", __func__, end_trigger);
+
 	while ((ch = b_getch(input)) != EOF) {
 		m = map[ch];
 		if (input->__promptme == 0)
 			return 1;
 		next = (ch == '\n') ? 0 : b_peek(input);
 
-		debug("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n",
-			ch >= ' ' ? ch : '.', ch, m,
-			dest->quote, ctx->stack == NULL ? '*' : '.');
+		debug("%s: ch=%c (%d) m=%d quote=%d - %c\n",
+				__func__,
+				ch >= ' ' ? ch : '.', ch, m,
+				dest->quote, ctx->stack == NULL ? '*' : '.');
 
 		if (m == 0 || ((m == 1 || m == 2) && dest->quote)) {
 			b_addqchr(dest, ch, dest->quote);
@@ -1295,12 +1397,12 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 			}
 			/* If we aren't performing a substitution, treat a newline as a
 			 * command separator.  */
-			if (end_trigger != '\0' && ch=='\n')
-				done_pipe(ctx,PIPE_SEQ);
+			if (end_trigger != '\0' && ch == '\n')
+				done_pipe(ctx, PIPE_SEQ);
 		}
 
 		if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
-			debug("leaving parse_stream (triggered)\n");
+			debug("%s: leaving (triggered)\n", __func__);
 			return 0;
 		}
 
@@ -1386,15 +1488,19 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 	 * that is, we were really supposed to get end_trigger, and never got
 	 * one before the EOF.  Can't use the standard "syntax error" return code,
 	 * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
-	debug("leaving parse_stream (EOF)\n");
-	if (end_trigger != '\0') return -1;
+	debug("%s: leaving (EOF)\n", __func__);
+
+	if (end_trigger != '\0')
+		return -1;
 	return 0;
 }
 
 static void mapset(const unsigned char *set, int code)
 {
 	const unsigned char *s;
-	for (s=set; *s; s++) map[*s] = code;
+
+	for (s = set; *s; s++)
+		map[*s] = code;
 }
 
 static void update_ifs_map(void)
@@ -1402,40 +1508,46 @@ static void update_ifs_map(void)
 	/* char *ifs and char map[256] are both globals. */
 	ifs = (uchar *)getenv("IFS");
 	ifs = NULL;
-	if (ifs == NULL) ifs=(uchar *)" \t\n";
+	if (ifs == NULL)
+		ifs = (uchar *)" \t\n";
+
 	/* Precompute a list of 'flow through' behavior so it can be treated
 	 * quickly up front.  Computation is necessary because of IFS.
 	 * Special case handling of IFS == " \t\n" is not implemented.
 	 * The map[] array only really needs two bits each, and on most machines
 	 * that would be faster because of the reduced L1 cache footprint.
 	 */
-	memset(map,0,sizeof(map)); /* most characters flow through always */
-	mapset((uchar *)"\\$'\"", 3);       /* never flow through */
-	mapset((uchar *)";&|#", 1);         /* flow through if quoted */
-	mapset(ifs, 2);            /* also flow through if quoted */
+	memset(map, 0, sizeof(map));	/* most characters flow through always */
+	mapset((uchar *)"\\$'\"", 3);	/* never flow through */
+	mapset((uchar *)";&|#", 1);	/* flow through if quoted */
+	mapset(ifs, 2);			/* also flow through if quoted */
 }
 
 /* most recursion does not come through here, the exeception is
  * from builtin_source() */
 static int parse_stream_outer(struct p_context *ctx, struct in_str *inp, int flag)
 {
-	o_string temp=NULL_O_STRING;
+	o_string temp = NULL_O_STRING;
 	int rcode;
 	int code = 0;
+
 	do {
 		ctx->type = flag;
 		initialize_context(ctx);
 		update_ifs_map();
+
 		if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING))
 			mapset((uchar *)";$&|", 0);
-		inp->promptmode=1;
+
+		inp->promptmode = 1;
 		rcode = parse_stream(&temp, ctx, inp, '\n');
+
 		if (rcode != 1 && ctx->old_flag != 0) {
 			syntax();
 		}
 		if (rcode != 1 && ctx->old_flag == 0) {
 			done_word(&temp, ctx);
-			done_pipe(ctx,PIPE_SEQ);
+			done_pipe(ctx, PIPE_SEQ);
 			if (ctx->list_head->num_progs) {
 				code = run_list(ctx, ctx->list_head);
 			} else {
@@ -1457,7 +1569,7 @@ static int parse_stream_outer(struct p_context *ctx, struct in_str *inp, int fla
 			temp.nonnull = 0;
 			temp.quote = 0;
 			inp->p = NULL;
-			free_pipe_list(ctx->list_head,0);
+			free_pipe_list(ctx->list_head, 0);
 		}
 		b_free(&temp);
 	} while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP));   /* loop on syntax errors, return on EOF */
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 04/13] hush: remove bogus 'else'
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (2 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 03/13] hush: cleanup coding style Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 05/13] hush: run_pipe_real must have num_progs == 1 Sascha Hauer
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/common/hush.c b/common/hush.c
index 017f96d..4e78577 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -610,7 +610,9 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 		rcode = run_list_real(ctx, child->group);
 
 		return rcode;
-	} else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
+	}
+
+	if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
 
 		for (i = 0; is_assignment(child->argv[i]); i++)
 			{ /* nothing */ }
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 05/13] hush: run_pipe_real must have num_progs == 1
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (3 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 04/13] hush: remove bogus 'else' Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 06/13] hush: run_pipe_real: bail out early to safe an indention level Sascha Hauer
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |   16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index 4e78577..362f544 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -596,14 +596,16 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 
 	nextin = 0;
 
-	/* Check if this is a simple builtin (not part of a pipe).
-	 * Builtins within pipes have to fork anyway, and are handled in
-	 * pseudo_exec.  "echo foo | read bar" doesn't work on bash, either.
+	/*
+	 * We do not support pipes in barebox, so pi->num_progs can't
+	 * be bigger than 1. pi->num_progs == 0 is already catched in
+	 * the caller, so everything else than 1 is a bug.
 	 */
-	if (pi->num_progs == 1)
-		child = &pi->progs[0];
+	BUG_ON(pi->num_progs != 1);
+
+	child = &pi->progs[0];
 
-	if (pi->num_progs == 1 && child->group) {
+	if (child->group) {
 		int rcode;
 
 		debug("non-subshell grouping\n");
@@ -612,7 +614,7 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 		return rcode;
 	}
 
-	if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
+	if (pi->progs[0].argv != NULL) {
 
 		for (i = 0; is_assignment(child->argv[i]); i++)
 			{ /* nothing */ }
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 06/13] hush: run_pipe_real: bail out early to safe an indention level
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (4 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 05/13] hush: run_pipe_real must have num_progs == 1 Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 07/13] hush: remove quotes at end of processing Sascha Hauer
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |   98 +++++++++++++++++++++++++++------------------------------
 1 file changed, 47 insertions(+), 51 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index 362f544..cd2afef 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -614,67 +614,67 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 		return rcode;
 	}
 
-	if (pi->progs[0].argv != NULL) {
-
-		for (i = 0; is_assignment(child->argv[i]); i++)
-			{ /* nothing */ }
+	if (!pi->progs[0].argv)
+		return -1;
 
-		if (i != 0 && child->argv[i] == NULL) {
-			/* assignments, but no command: set the local environment */
-			for (i = 0; child->argv[i] != NULL; i++) {
+	for (i = 0; is_assignment(child->argv[i]); i++)
+		{ /* nothing */ }
 
-				/* Ok, this case is tricky.  We have to decide if this is a
-				 * local variable, or an already exported variable.  If it is
-				 * already exported, we have to export the new value.  If it is
-				 * not exported, we need only set this as a local variable.
-				 * This junk is all to decide whether or not to export this
-				 * variable. */
-				int export_me = 0;
-				char *name, *value;
+	if (i != 0 && child->argv[i] == NULL) {
+		/* assignments, but no command: set the local environment */
+		for (i = 0; child->argv[i] != NULL; i++) {
 
-				name = xstrdup(child->argv[i]);
-				debug("Local environment set: %s\n", name);
-				value = strchr(name, '=');
+			/* Ok, this case is tricky.  We have to decide if this is a
+			 * local variable, or an already exported variable.  If it is
+			 * already exported, we have to export the new value.  If it is
+			 * not exported, we need only set this as a local variable.
+			 * This junk is all to decide whether or not to export this
+			 * variable. */
+			int export_me = 0;
+			char *name, *value;
 
-				if (value)
-					*value = 0;
+			name = xstrdup(child->argv[i]);
+			debug("Local environment set: %s\n", name);
+			value = strchr(name, '=');
 
-				free(name);
-				p = insert_var_value(child->argv[i]);
-				set_local_var(p, export_me);
+			if (value)
+				*value = 0;
 
-				if (p != child->argv[i])
-					free(p);
-			}
-			return EXIT_SUCCESS;   /* don't worry about errors in set_local_var() yet */
-		}
-		for (i = 0; is_assignment(child->argv[i]); i++) {
+			free(name);
 			p = insert_var_value(child->argv[i]);
-			set_local_var(p, 0);
+			set_local_var(p, export_me);
 
-			if (p != child->argv[i]) {
-				child->sp--;
+			if (p != child->argv[i])
 				free(p);
-			}
 		}
-		if (child->sp) {
-			char * str = NULL;
-			struct p_context ctx1;
-
-			str = make_string((child->argv + i));
-			parse_string_outer(&ctx1, str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
-			release_context(&ctx1);
-			free(str);
+		return EXIT_SUCCESS;   /* don't worry about errors in set_local_var() yet */
+	}
+	for (i = 0; is_assignment(child->argv[i]); i++) {
+		p = insert_var_value(child->argv[i]);
+		set_local_var(p, 0);
 
-			return last_return_code;
+		if (p != child->argv[i]) {
+			child->sp--;
+			free(p);
 		}
+	}
+	if (child->sp) {
+		char * str = NULL;
+		struct p_context ctx1;
+
+		str = make_string((child->argv + i));
+		parse_string_outer(&ctx1, str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
+		release_context(&ctx1);
+		free(str);
+
+		return last_return_code;
+	}
+
 #ifdef CONFIG_HUSH_GETOPT
-		if (!strcmp(child->argv[i], "getopt"))
-			return builtin_getopt(ctx, child);
+	if (!strcmp(child->argv[i], "getopt"))
+		return builtin_getopt(ctx, child);
 #endif
-		return execute_binfmt(child->argc - i, &child->argv[i]);
-	}
-	return -1;
+	return execute_binfmt(child->argc - i, &child->argv[i]);
 }
 
 static int run_list_real(struct p_context *ctx, struct pipe *pi)
@@ -1234,13 +1234,9 @@ static int done_pipe(struct p_context *ctx, pipe_style type)
 	struct pipe *new_p;
 
 	done_command(ctx);  /* implicit closure of previous command */
-<<<<<<< HEAD
 
 	debug("%s: type %d\n", __func__, type);
 
-=======
-	debug("%s: type %d\n", __func__, type);
->>>>>>> f5c1f0c... hush use func
 	ctx->pipe->followup = type;
 	ctx->pipe->r_mode = ctx->w;
 
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 07/13] hush: remove quotes at end of processing
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (5 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 06/13] hush: run_pipe_real: bail out early to safe an indention level Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 08/13] hush: simplify globhack Sascha Hauer
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

hush removes the quotes from strings too early. This leads to some bugs.
When hush executes

echo "hello sascha"

it correctly results in:

argv[0] = "echo"
argv[1] = "hello sascha"

However, the following behaves incorrect:

a="hello sascha"
echo "$a"

results in:

argv[0] = "echo"
argv[1] = "hello"
argv[2] = "sascha"

This is because hush removes the quotes and inserts variable values in a
single loop, so

echo "$a"

becomes:

echo hello sascha

after the loop.

Instead, keep the quotes until all variables are inserted and remove them
at the end.

This also fixes that echo \" resulted in \" instead of ".

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |   89 ++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 66 insertions(+), 23 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index cd2afef..e32e884 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -270,7 +270,6 @@ static void syntax_err(void) {
 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);
 /*  in_str manipulations: */
 static int static_get(struct in_str *i);
 static int static_peek(struct in_str *i);
@@ -356,22 +355,6 @@ static void b_free(o_string *o)
 	o->maxlen = 0;
 }
 
-/* My analysis of quoting semantics tells me that state information
- * is associated with a destination, not a source.
- */
-static int b_addqchr(o_string *o, int ch, int quote)
-{
-	if (quote && strchr("*?[",ch)) {
-		int rc;
-
-		rc = b_addchr(o, '\\');
-		if (rc)
-			return rc;
-	}
-
-	return b_addchr(o, ch);
-}
-
 static int b_adduint(o_string *o, unsigned int i)
 {
 	int r;
@@ -565,6 +548,59 @@ out:
 BAREBOX_MAGICVAR(OPTARG, "optarg for hush builtin getopt");
 #endif
 
+static void remove_quotes_in_str(char *src)
+{
+	char *trg = src;
+
+	while (*src) {
+		if (*src == '\'') {
+			src++;
+			while (*src != '\'')
+				*trg++ = *src++;
+			src++;
+			continue;
+		}
+
+		/* drop quotes */
+		if (*src == '"') {
+			src++;
+			continue;
+		}
+
+		/* replace \" with " */
+		if (*src == '\\' && *(src + 1) == '"') {
+			*trg++ = '"';
+			src += 2;
+			continue;
+		}
+
+		/* replace \' with ' */
+		if (*src == '\\' && *(src + 1) == '\'') {
+			*trg++ = '\'';
+			src += 2;
+			continue;
+		}
+
+		/* replace \\ with \ */
+		if (*src == '\\' && *(src + 1) == '\\') {
+			*trg++ = '\\';
+			src += 2;
+			continue;
+		}
+
+		*trg++ = *src++;
+	}
+	*trg = 0;
+}
+
+static void remove_quotes(int argc, char *argv[])
+{
+	int i;
+
+	for (i = 0; i < argc; i++)
+		remove_quotes_in_str(argv[i]);
+}
+
 /* run_pipe_real() starts all the jobs, but doesn't wait for anything
  * to finish.  See checkjobs().
  *
@@ -670,6 +706,8 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 		return last_return_code;
 	}
 
+	remove_quotes(child->argc - i, &child->argv[i]);
+
 #ifdef CONFIG_HUSH_GETOPT
 	if (!strcmp(child->argv[i], "getopt"))
 		return builtin_getopt(ctx, child);
@@ -1007,6 +1045,8 @@ static int set_local_var(const char *s, int flg_export)
 	}
 	*value++ = 0;
 
+	remove_quotes_in_str(value);
+
 	ret = setenv(name, value);
 	free(name);
 
@@ -1347,7 +1387,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
 			b_addchr(dest, SPECIAL_VAR_SYMBOL);
 			break;
 		default:
-			b_addqchr(dest,'$',dest->quote);
+			b_addchr(dest, '$');
 		}
 	}
 	/* Eat the character if the flag was set.  If the compiler
@@ -1387,7 +1427,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 				dest->quote, ctx->stack == NULL ? '*' : '.');
 
 		if (m == 0 || ((m == 1 || m == 2) && dest->quote)) {
-			b_addqchr(dest, ch, dest->quote);
+			b_addchr(dest, ch);
 			continue;
 		}
 
@@ -1416,7 +1456,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 					b_getch(input);
 				}
 			} else {
-				b_addqchr(dest, ch, dest->quote);
+				b_addchr(dest, ch);
 			}
 			break;
 		case '\\':
@@ -1424,8 +1464,8 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 				syntax();
 				return 1;
 			}
-			b_addqchr(dest, '\\', dest->quote);
-			b_addqchr(dest, b_getch(input), dest->quote);
+			b_addchr(dest, '\\');
+			b_addchr(dest, b_getch(input));
 			break;
 		case '$':
 			if (handle_dollar(dest, ctx, input)!=0)
@@ -1433,11 +1473,13 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 			break;
 		case '\'':
 			dest->nonnull = 1;
-			while (ch = b_getch(input), ch!=EOF && ch != '\'') {
+			b_addchr(dest, '\'');
+			while (ch = b_getch(input), ch != EOF && ch != '\'') {
 				if (input->__promptme == 0)
 					return 1;
 				b_addchr(dest,ch);
 			}
+			b_addchr(dest, '\'');
 			if (ch == EOF) {
 				syntax();
 				return 1;
@@ -1445,6 +1487,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
 			break;
 		case '"':
 			dest->nonnull = 1;
+			b_addchr(dest, '"');
 			dest->quote = !dest->quote;
 			break;
 		case ';':
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 08/13] hush: simplify globhack
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (6 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 07/13] hush: remove quotes at end of processing Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 09/13] hush: pass GLOB_NOCHECK to glob Sascha Hauer
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

hush used to escape '*' '[' '?' during parsing because the quotes
got removed in the first parsing loop.

globhack is used to remove these escapes again for glob. Since we now
keep the quotes until the end of parsing and we no longer escape glob
wildcards, we do no longer have to remove any quotes. With this globhack
can be much simpler.

While at it, change the prototype to match the one from glob() and rename
the function to fake_glob, because that's what it is: it just copies the
input string into the output struct without actually globbing.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |   39 ++++++++-------------------------------
 1 file changed, 8 insertions(+), 31 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index e32e884..ea6e53b 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -911,26 +911,11 @@ static int free_pipe_list(struct pipe *head, int indent)
 	return rcode;
 }
 
-/* The API for glob is arguably broken.  This routine pushes a non-matching
- * string into the output structure, removing non-backslashed backslashes.
- * If someone can prove me wrong, by performing this function within the
- * original glob(3) api, feel free to rewrite this routine into oblivion.
- * Return code (0 vs. GLOB_NOSPACE) matches glob(3).
- * XXX broken if the last character is '\\', check that before calling.
- */
-static int globhack(const char *src, int flags, glob_t *pglob)
+static int fake_glob(const char *src, int flags,
+		int (*errfunc) (const char *epath, int eerrno),
+		glob_t *pglob)
 {
-	int cnt = 0, pathc;
-	const char *s;
-	char *dest;
-
-	for (cnt = 1, s = src; s && *s; s++) {
-		if (*s == '\\' && strchr("*[?", *(s + 1)))
-			s++;
-		cnt++;
-	}
-
-	dest = xmalloc(cnt);
+	int pathc;
 
 	if (!(flags & GLOB_APPEND)) {
 		globfree(pglob);
@@ -940,17 +925,9 @@ static int globhack(const char *src, int flags, glob_t *pglob)
 	}
 	pathc = ++pglob->gl_pathc;
 	pglob->gl_pathv = xrealloc(pglob->gl_pathv, (pathc + 1) * sizeof(*pglob->gl_pathv));
-	pglob->gl_pathv[pathc - 1] = dest;
+	pglob->gl_pathv[pathc - 1] = xstrdup(src);
 	pglob->gl_pathv[pathc] = NULL;
 
-	for (s = src; s && *s; s++, dest++) {
-		if (*s == '\\' && strchr("*[?", *(s + 1)))
-			s++;
-		*dest = *s;
-	}
-
-	*dest = '\0';
-
 	return 0;
 }
 
@@ -977,7 +954,7 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
 	if (dest->length == 0) {
 		if (dest->nonnull) {
 			/* bash man page calls this an "explicit" null */
-			gr = globhack(dest->data, flags, pglob);
+			gr = fake_glob(dest->data, flags, NULL, pglob);
 			debug("globhack returned %d\n",gr);
 		} else {
 			return 0;
@@ -987,11 +964,11 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
 		debug("glob returned %d\n",gr);
 		if (gr == GLOB_NOMATCH) {
 			/* quote removal, or more accurately, backslash removal */
-			gr = globhack(dest->data, flags, pglob);
+			gr = fake_glob(dest->data, flags, NULL, pglob);
 			debug("globhack returned %d\n",gr);
 		}
 	} else {
-		gr = globhack(dest->data, flags, pglob);
+		gr = fake_glob(dest->data, flags, NULL, pglob);
 		debug("globhack returned %d\n",gr);
 	}
 	if (gr != 0) { /* GLOB_ABORTED ? */
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 09/13] hush: pass GLOB_NOCHECK to glob
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (7 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 08/13] hush: simplify globhack Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 10/13] glob: activate GLOB_NOCHECK flag Sascha Hauer
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

By doing so glob will not return GLOB_NOMATCH anymore but instead
just does what fake_glob would do.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |    7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index ea6e53b..d7ed624 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -962,11 +962,6 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
 	} else if (glob_needed(dest->data)) {
 		gr = glob(dest->data, flags, NULL, pglob);
 		debug("glob returned %d\n",gr);
-		if (gr == GLOB_NOMATCH) {
-			/* quote removal, or more accurately, backslash removal */
-			gr = fake_glob(dest->data, flags, NULL, pglob);
-			debug("globhack returned %d\n",gr);
-		}
 	} else {
 		gr = fake_glob(dest->data, flags, NULL, pglob);
 		debug("globhack returned %d\n",gr);
@@ -1172,7 +1167,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
 {
 	struct child_prog *child = ctx->child;
 	glob_t *glob_target;
-	int gr, flags = 0;
+	int gr, flags = GLOB_NOCHECK;
 
 	debug("%s: %s %p\n", __func__, dest->data, child);
 	if (dest->length == 0 && !dest->nonnull) {
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 10/13] glob: activate GLOB_NOCHECK flag
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (8 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 09/13] hush: pass GLOB_NOCHECK to glob Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 11/13] hush: Fix globbing Sascha Hauer
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

Needed for hush.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 lib/glob.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/lib/glob.c b/lib/glob.c
index 43d2f67..74d2b12 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -209,7 +209,7 @@ int glob(const char *pattern, int flags,
 
 		if (pglob->gl_pathc == oldcount) {
 			/* No matches.  */
-#ifdef CONFIG_GLOB_NOCHECK
+
 			if (flags & GLOB_NOCHECK) {
 				size_t len = strlen(pattern) + 1;
 				char *patcopy = (char *)xmalloc(len);
@@ -232,9 +232,7 @@ int glob(const char *pattern, int flags,
 				pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
 				pglob->gl_pathv[pglob->gl_pathc] = NULL;
 				pglob->gl_flags = flags;
-			} else
-#endif
-			{
+			} else {
 				status = GLOB_NOMATCH;
 				goto out;
 			}
@@ -367,7 +365,7 @@ static int glob_in_dir(const char *pattern, const char *directory,
 				break;
 		}
 	}
-#ifdef CONFIG_GLOB_NOCHECK
+
 	if (nfound == 0 && (flags & GLOB_NOCHECK)) {
 		size_t len = strlen(pattern);
 		nfound = 1;
@@ -378,7 +376,7 @@ static int glob_in_dir(const char *pattern, const char *directory,
 		memcpy(names->name, pattern, len);
 		names->name[len] = '\0';
 	}
-#endif
+
 	pglob->gl_pathv
 	    = (char **)xrealloc(pglob->gl_pathv,
 			       (pglob->gl_pathc +
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 11/13] hush: Fix globbing
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (9 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 10/13] glob: activate GLOB_NOCHECK flag Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 12/13] hush: allow to run interactive shell in do_sh Sascha Hauer
  2012-04-30 11:19 ` [PATCH 13/13] defaultenv: remove now unnecessary hush-hack Sascha Hauer
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

hush has a long standing and anoying glob bug. hush expands wildcards
during parsing of the script or command stream. When the command stream
begins to execute the wildcards are already expanded which leads to:

mkdir /tmp
cd /tmp
mkdir foo; ls *
ls: *: No such file or directory

To fix this expand wildcards right before executing the command. Since
'for' loops are not executed in commands, we have to keep the old behaviour
in here so that 'for i in *' still works.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |  127 +++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 79 insertions(+), 48 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index d7ed624..ab513af 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -497,7 +497,8 @@ static void setup_string_in_str(struct in_str *i, const char *s)
 }
 
 #ifdef CONFIG_HUSH_GETOPT
-static int builtin_getopt(struct p_context *ctx, struct child_prog *child)
+static int builtin_getopt(struct p_context *ctx, struct child_prog *child,
+		int argc, char *argv[])
 {
 	char *optstring, *var;
 	int opt, ret = 0;
@@ -505,11 +506,11 @@ static int builtin_getopt(struct p_context *ctx, struct child_prog *child)
 	struct option *o;
 	struct getopt_context gc;
 
-	if (child->argc != 3)
+	if (argc != 3)
 		return -2 - 1;
 
-	optstring = child->argv[1];
-	var = child->argv[2];
+	optstring = argv[1];
+	var = argv[2];
 
 	getopt_context_store(&gc);
 
@@ -546,6 +547,12 @@ out:
 }
 
 BAREBOX_MAGICVAR(OPTARG, "optarg for hush builtin getopt");
+#else
+static int builtin_getopt(struct p_context *ctx, struct child_prog *child,
+		int argc, char *argv[])
+{
+	return -1;
+}
 #endif
 
 static void remove_quotes_in_str(char *src)
@@ -601,6 +608,57 @@ static void remove_quotes(int argc, char *argv[])
 		remove_quotes_in_str(argv[i]);
 }
 
+static int fake_glob(const char *src, int flags,
+		int (*errfunc) (const char *epath, int eerrno),
+		glob_t *pglob)
+{
+	int pathc;
+
+	if (!(flags & GLOB_APPEND)) {
+		globfree(pglob);
+		pglob->gl_pathv = NULL;
+		pglob->gl_pathc = 0;
+		pglob->gl_offs = 0;
+	}
+	pathc = ++pglob->gl_pathc;
+	pglob->gl_pathv = xrealloc(pglob->gl_pathv, (pathc + 1) * sizeof(*pglob->gl_pathv));
+	pglob->gl_pathv[pathc - 1] = xstrdup(src);
+	pglob->gl_pathv[pathc] = NULL;
+
+	return 0;
+}
+
+#ifdef CONFIG_GLOB
+static int do_glob(const char *src, int flags,
+		int (*errfunc) (const char *epath, int eerrno),
+		glob_t *pglob)
+{
+	return glob(src, flags, errfunc, pglob);
+}
+#else
+static int do_glob(const char *src, int flags,
+		int (*errfunc) (const char *epath, int eerrno),
+		glob_t *pglob)
+{
+	return fake_glob(src, flags, errfunc, pglob);
+}
+#endif
+
+static void do_glob_in_argv(glob_t *globbuf, int argc, char **argv)
+{
+	int i;
+	int flags;
+
+	globbuf->gl_offs = 0;
+	flags = GLOB_DOOFFS | GLOB_NOCHECK;
+
+	for (i = 0; i < argc; i++) {
+		int ret;
+		ret = do_glob(argv[i], flags, NULL, globbuf);
+		flags |= GLOB_APPEND;
+	}
+}
+
 /* run_pipe_real() starts all the jobs, but doesn't wait for anything
  * to finish.  See checkjobs().
  *
@@ -623,6 +681,8 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 	int nextin;
 	struct child_prog *child;
 	char *p;
+	glob_t globbuf = {};
+	int ret;
 # if __GNUC__
 	/* Avoid longjmp clobbering */
 	(void) &i;
@@ -706,13 +766,18 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
 		return last_return_code;
 	}
 
-	remove_quotes(child->argc - i, &child->argv[i]);
+	do_glob_in_argv(&globbuf, child->argc - i, &child->argv[i]);
 
-#ifdef CONFIG_HUSH_GETOPT
-	if (!strcmp(child->argv[i], "getopt"))
-		return builtin_getopt(ctx, child);
-#endif
-	return execute_binfmt(child->argc - i, &child->argv[i]);
+	remove_quotes(globbuf.gl_pathc, globbuf.gl_pathv);
+
+	if (!strcmp(globbuf.gl_pathv[0], "getopt"))
+		ret = builtin_getopt(ctx, child, globbuf.gl_pathc, globbuf.gl_pathv);
+	else
+		ret = execute_binfmt(globbuf.gl_pathc, globbuf.gl_pathv);
+
+	globfree(&globbuf);
+
+	return ret;
 }
 
 static int run_list_real(struct p_context *ctx, struct pipe *pi)
@@ -911,41 +976,7 @@ static int free_pipe_list(struct pipe *head, int indent)
 	return rcode;
 }
 
-static int fake_glob(const char *src, int flags,
-		int (*errfunc) (const char *epath, int eerrno),
-		glob_t *pglob)
-{
-	int pathc;
-
-	if (!(flags & GLOB_APPEND)) {
-		globfree(pglob);
-		pglob->gl_pathv = NULL;
-		pglob->gl_pathc = 0;
-		pglob->gl_offs = 0;
-	}
-	pathc = ++pglob->gl_pathc;
-	pglob->gl_pathv = xrealloc(pglob->gl_pathv, (pathc + 1) * sizeof(*pglob->gl_pathv));
-	pglob->gl_pathv[pathc - 1] = xstrdup(src);
-	pglob->gl_pathv[pathc] = NULL;
-
-	return 0;
-}
-
-/* XXX broken if the last character is '\\', check that before calling */
-static int glob_needed(const char *s)
-{
-#ifdef CONFIG_GLOB
-	for (; *s; s++) {
-		if (*s == '\\')
-			s++;
-		if (strchr("*[?",*s))
-			return 1;
-	}
-#endif
-	return 0;
-}
-
-static int xglob(o_string *dest, int flags, glob_t *pglob)
+static int xglob(o_string *dest, int flags, glob_t *pglob, int glob_needed)
 {
 	int gr;
 
@@ -959,8 +990,8 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
 		} else {
 			return 0;
 		}
-	} else if (glob_needed(dest->data)) {
-		gr = glob(dest->data, flags, NULL, pglob);
+	} else if (glob_needed) {
+		gr = do_glob(dest->data, flags, NULL, pglob);
 		debug("glob returned %d\n",gr);
 	} else {
 		gr = fake_glob(dest->data, flags, NULL, pglob);
@@ -1188,7 +1219,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
 	if (child->argv)
 		flags |= GLOB_APPEND;
 
-	gr = xglob(dest, flags, glob_target);
+	gr = xglob(dest, flags, glob_target, ctx->w == RES_IN ? 1 : 0);
 	if (gr)
 		return 1;
 
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 12/13] hush: allow to run interactive shell in do_sh
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (10 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 11/13] hush: Fix globbing Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  2012-04-30 11:19 ` [PATCH 13/13] defaultenv: remove now unnecessary hush-hack Sascha Hauer
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

This allows to call 'sh' in scripts without arguments in which
case an interactive shell will be started.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/hush.c b/common/hush.c
index ab513af..d915f9e 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1814,7 +1814,7 @@ int run_shell(void)
 static int do_sh(int argc, char *argv[])
 {
 	if (argc < 2)
-		return COMMAND_ERROR_USAGE;
+		return run_shell();
 
 	return execute_script(argv[1], argc - 1, argv + 1);
 }
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 13/13] defaultenv: remove now unnecessary hush-hack
  2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
                   ` (11 preceding siblings ...)
  2012-04-30 11:19 ` [PATCH 12/13] hush: allow to run interactive shell in do_sh Sascha Hauer
@ 2012-04-30 11:19 ` Sascha Hauer
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2012-04-30 11:19 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 defaultenv/bin/hush_hack |    1 -
 defaultenv/bin/init      |    5 +----
 2 files changed, 1 insertion(+), 5 deletions(-)
 delete mode 100644 defaultenv/bin/hush_hack

diff --git a/defaultenv/bin/hush_hack b/defaultenv/bin/hush_hack
deleted file mode 100644
index 5fffa92..0000000
--- a/defaultenv/bin/hush_hack
+++ /dev/null
@@ -1 +0,0 @@
-nand -a /dev/nand0.*
diff --git a/defaultenv/bin/init b/defaultenv/bin/init
index 7452bb6..6e85a82 100644
--- a/defaultenv/bin/init
+++ b/defaultenv/bin/init
@@ -14,10 +14,7 @@ fi
 
 if [ -e /dev/nand0 -a -n "$nand_parts" ]; then
 	addpart /dev/nand0 $nand_parts
-
-	# Uh, oh, hush first expands wildcards and then starts executing
-	# commands. What a bug!
-	source /env/bin/hush_hack
+	nand -a /dev/nand0.*
 fi
 
 if [ -f /env/bin/init_board ]; then
-- 
1.7.10


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-04-30 11:19 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-30 11:19 hush fixes and cleanups Sascha Hauer
2012-04-30 11:19 ` [PATCH 01/13] hush: safe indention level by continueing a loop Sascha Hauer
2012-04-30 11:19 ` [PATCH 02/13] hush: safe an " Sascha Hauer
2012-04-30 11:19 ` [PATCH 03/13] hush: cleanup coding style Sascha Hauer
2012-04-30 11:19 ` [PATCH 04/13] hush: remove bogus 'else' Sascha Hauer
2012-04-30 11:19 ` [PATCH 05/13] hush: run_pipe_real must have num_progs == 1 Sascha Hauer
2012-04-30 11:19 ` [PATCH 06/13] hush: run_pipe_real: bail out early to safe an indention level Sascha Hauer
2012-04-30 11:19 ` [PATCH 07/13] hush: remove quotes at end of processing Sascha Hauer
2012-04-30 11:19 ` [PATCH 08/13] hush: simplify globhack Sascha Hauer
2012-04-30 11:19 ` [PATCH 09/13] hush: pass GLOB_NOCHECK to glob Sascha Hauer
2012-04-30 11:19 ` [PATCH 10/13] glob: activate GLOB_NOCHECK flag Sascha Hauer
2012-04-30 11:19 ` [PATCH 11/13] hush: Fix globbing Sascha Hauer
2012-04-30 11:19 ` [PATCH 12/13] hush: allow to run interactive shell in do_sh Sascha Hauer
2012-04-30 11:19 ` [PATCH 13/13] defaultenv: remove now unnecessary hush-hack Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox