hush: fix a bit different instance of "No EOL" bug,
add testsuite for that. Expand another testsuite.
diff --git a/shell/hush.c b/shell/hush.c
index 61c03f7..aab6ff3 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2836,14 +2836,13 @@
static void initialize_context(struct p_context *ctx)
{
- ctx->pipe = NULL;
- ctx->pending_redirect = NULL;
ctx->child = NULL;
- ctx->list_head = new_pipe();
- ctx->pipe = ctx->list_head;
+ ctx->pipe = ctx->list_head = new_pipe();
+ ctx->pending_redirect = NULL;
ctx->res_w = RES_NONE;
- ctx->stack = NULL;
+ //only ctx->parse_type is not touched... is this intentional?
ctx->old_flag = 0;
+ ctx->stack = NULL;
done_command(ctx); /* creates the memory for working child */
}
@@ -2886,44 +2885,44 @@
const struct reserved_combo *r;
for (r = reserved_list; r < reserved_list + NRES; r++) {
- if (strcmp(dest->data, r->literal) == 0) {
- debug_printf("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_printf("push stack\n");
+ if (strcmp(dest->data, r->literal) != 0)
+ continue;
+ debug_printf("found reserved word %s, code %d\n", r->literal, r->code);
+ if (r->flag & FLAG_START) {
+ struct p_context *new;
+ debug_printf("push stack\n");
#if ENABLE_HUSH_LOOPS
- if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
- syntax();
- free(new);
- ctx->res_w = RES_SNTX;
- b_reset(dest);
- return 1;
- }
-#endif
- *new = *ctx; /* physical copy */
- initialize_context(ctx);
- ctx->stack = new;
- } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
+ if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
syntax();
ctx->res_w = RES_SNTX;
b_reset(dest);
return 1;
}
- ctx->res_w = r->code;
- ctx->old_flag = r->flag;
- if (ctx->old_flag & FLAG_END) {
- struct p_context *old;
- debug_printf("pop stack\n");
- done_pipe(ctx, PIPE_SEQ);
- old = ctx->stack;
- old->child->group = ctx->list_head;
- old->child->subshell = 0;
- *ctx = *old; /* physical copy */
- free(old);
- }
+#endif
+ new = xmalloc(sizeof(*new));
+ *new = *ctx; /* physical copy */
+ initialize_context(ctx);
+ ctx->stack = new;
+ } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
+ syntax();
+ ctx->res_w = RES_SNTX;
b_reset(dest);
return 1;
}
+ ctx->res_w = r->code;
+ ctx->old_flag = r->flag;
+ if (ctx->old_flag & FLAG_END) {
+ struct p_context *old;
+ debug_printf("pop stack\n");
+ done_pipe(ctx, PIPE_SEQ);
+ old = ctx->stack;
+ old->child->group = ctx->list_head;
+ old->child->subshell = 0;
+ *ctx = *old; /* physical copy */
+ free(old);
+ }
+ b_reset(dest);
+ return 1;
}
return 0;
}
@@ -3155,7 +3154,8 @@
/* recursion to generate command */
retcode = parse_stream(&result, &inner, input, subst_end);
- if (retcode != 0) return retcode; /* syntax error or EOF */
+ if (retcode != 0)
+ return retcode; /* syntax error or EOF */
done_word(&result, &inner);
done_pipe(&inner, PIPE_SEQ);
b_free(&result);
@@ -3357,9 +3357,15 @@
debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger);
- while ((ch = b_getch(input)) != EOF) {
- m = charmap[ch];
- next = (ch == '\n') ? '\0' : b_peek(input);
+ while (1) {
+ ch = b_getch(input);
+ m = CHAR_IFS;
+ next = '\0';
+ if (ch != EOF) {
+ m = charmap[ch];
+ if (ch != '\n')
+ next = b_peek(input);
+ }
debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n",
ch, ch, m, dest->quote);
if (m == CHAR_ORDINARY
@@ -3373,6 +3379,8 @@
debug_printf_parse("parse_stream return 1: done_word!=0\n");
return 1;
}
+ if (ch == EOF)
+ break;
/* If we aren't performing a substitution, treat
* a newline as a command separator.
* [why we don't handle it exactly like ';'? --vda] */