hush: preparatory patch for removing extra empty pipes generation
in parse stage. No real code change here.
This commit is contained in:
parent
734e5ebc93
commit
a6c467f6d1
152
shell/hush.c
152
shell/hush.c
@ -125,7 +125,7 @@ static const char *indenter(int i)
|
|||||||
#define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
|
#define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SPECIAL_VAR_SYMBOL 03
|
#define SPECIAL_VAR_SYMBOL 3
|
||||||
#define FLAG_EXIT_FROM_LOOP 1
|
#define FLAG_EXIT_FROM_LOOP 1
|
||||||
#define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */
|
#define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */
|
||||||
#define FLAG_REPARSING (1 << 2) /* >= 2nd pass */
|
#define FLAG_REPARSING (1 << 2) /* >= 2nd pass */
|
||||||
@ -199,10 +199,10 @@ struct p_context {
|
|||||||
struct pipe *list_head;
|
struct pipe *list_head;
|
||||||
struct pipe *pipe;
|
struct pipe *pipe;
|
||||||
struct redir_struct *pending_redirect;
|
struct redir_struct *pending_redirect;
|
||||||
reserved_style w;
|
reserved_style res_w;
|
||||||
int old_flag; /* for figuring out valid reserved words */
|
int old_flag; /* for figuring out valid reserved words */
|
||||||
struct p_context *stack;
|
struct p_context *stack;
|
||||||
int type; /* define type of parser : ";$" common or special symbol */
|
int parse_type; /* define type of parser : ";$" common or special symbol */
|
||||||
/* How about quoting status? */
|
/* How about quoting status? */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -410,8 +410,8 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
|
|||||||
static int parse_string(o_string *dest, struct p_context *ctx, const char *src);
|
static int parse_string(o_string *dest, struct p_context *ctx, const char *src);
|
||||||
static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, const char *end_trigger);
|
static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, const char *end_trigger);
|
||||||
/* setup: */
|
/* setup: */
|
||||||
static int parse_stream_outer(struct in_str *inp, int flag);
|
static int parse_stream_outer(struct in_str *inp, int parse_flag);
|
||||||
static int parse_string_outer(const char *s, int flag);
|
static int parse_string_outer(const char *s, int parse_flag);
|
||||||
static int parse_file_outer(FILE *f);
|
static int parse_file_outer(FILE *f);
|
||||||
/* job management: */
|
/* job management: */
|
||||||
static int checkjobs(struct pipe* fg_pipe);
|
static int checkjobs(struct pipe* fg_pipe);
|
||||||
@ -1854,23 +1854,24 @@ static void debug_print_tree(struct pipe *pi, int lvl)
|
|||||||
};
|
};
|
||||||
|
|
||||||
int pin, prn;
|
int pin, prn;
|
||||||
char **argv;
|
|
||||||
pin = 0;
|
pin = 0;
|
||||||
while (pi) {
|
while (pi) {
|
||||||
fprintf(stderr, "%*spipe %d r_mode=%s followup=%d %s\n", lvl*2, "",
|
fprintf(stderr, "%*spipe %d r_mode=%s followup=%d %s\n", lvl*2, "",
|
||||||
pin, RES[pi->r_mode], pi->followup, PIPE[pi->followup]);
|
pin, RES[pi->r_mode], pi->followup, PIPE[pi->followup]);
|
||||||
prn = 0;
|
prn = 0;
|
||||||
while (prn < pi->num_progs) {
|
while (prn < pi->num_progs) {
|
||||||
|
struct child_prog *child = &pi->progs[prn];
|
||||||
|
char **argv = child->argv;
|
||||||
|
|
||||||
fprintf(stderr, "%*s prog %d", lvl*2, "", prn);
|
fprintf(stderr, "%*s prog %d", lvl*2, "", prn);
|
||||||
if (pi->progs[prn].group) {
|
if (child->group) {
|
||||||
fprintf(stderr, " group %s: (argv=%p)\n",
|
fprintf(stderr, " group %s: (argv=%p)\n",
|
||||||
(pi->subshell ? "()" : "{}"),
|
(child->subshell ? "()" : "{}"),
|
||||||
pi->progs[prn].argv);
|
argv);
|
||||||
debug_print_tree(pi->progs[prn].group, lvl+1);
|
debug_print_tree(child->group, lvl+1);
|
||||||
prn++;
|
prn++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
argv = pi->progs[prn].argv;
|
|
||||||
if (argv) while (*argv) {
|
if (argv) while (*argv) {
|
||||||
fprintf(stderr, " '%s'", *argv);
|
fprintf(stderr, " '%s'", *argv);
|
||||||
argv++;
|
argv++;
|
||||||
@ -1901,7 +1902,7 @@ static int run_list_real(struct pipe *pi)
|
|||||||
int flag_rep = 0;
|
int flag_rep = 0;
|
||||||
int save_num_progs;
|
int save_num_progs;
|
||||||
int flag_skip = 1;
|
int flag_skip = 1;
|
||||||
int rcode = 0; /* probaly for gcc only */
|
int rcode = 0; /* probably for gcc only */
|
||||||
int flag_restore = 0;
|
int flag_restore = 0;
|
||||||
int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */
|
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;
|
||||||
@ -1968,17 +1969,15 @@ static int run_list_real(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) {
|
for (; pi; pi = flag_restore ? rpipe : pi->next) {
|
||||||
if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL
|
rmode = pi->r_mode;
|
||||||
|| pi->r_mode == RES_FOR
|
if (rmode == RES_WHILE || rmode == RES_UNTIL || rmode == RES_FOR) {
|
||||||
) {
|
|
||||||
flag_restore = 0;
|
flag_restore = 0;
|
||||||
if (!rpipe) {
|
if (!rpipe) {
|
||||||
flag_rep = 0;
|
flag_rep = 0;
|
||||||
rpipe = pi;
|
rpipe = pi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rmode = pi->r_mode;
|
|
||||||
debug_printf_exec(": rmode=%d if_code=%d next_if_code=%d skip_more=%d\n",
|
debug_printf_exec(": rmode=%d if_code=%d next_if_code=%d skip_more=%d\n",
|
||||||
rmode, if_code, next_if_code, skip_more_in_this_rmode);
|
rmode, if_code, next_if_code, skip_more_in_this_rmode);
|
||||||
if (rmode == skip_more_in_this_rmode && flag_skip) {
|
if (rmode == skip_more_in_this_rmode && flag_skip) {
|
||||||
@ -2535,7 +2534,7 @@ static void initialize_context(struct p_context *ctx)
|
|||||||
ctx->child = NULL;
|
ctx->child = NULL;
|
||||||
ctx->list_head = new_pipe();
|
ctx->list_head = new_pipe();
|
||||||
ctx->pipe = ctx->list_head;
|
ctx->pipe = ctx->list_head;
|
||||||
ctx->w = RES_NONE;
|
ctx->res_w = RES_NONE;
|
||||||
ctx->stack = NULL;
|
ctx->stack = NULL;
|
||||||
ctx->old_flag = 0;
|
ctx->old_flag = 0;
|
||||||
done_command(ctx); /* creates the memory for working child */
|
done_command(ctx); /* creates the memory for working child */
|
||||||
@ -2580,23 +2579,23 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
|
|||||||
if (r->flag & FLAG_START) {
|
if (r->flag & FLAG_START) {
|
||||||
struct p_context *new = xmalloc(sizeof(struct p_context));
|
struct p_context *new = xmalloc(sizeof(struct p_context));
|
||||||
debug_printf("push stack\n");
|
debug_printf("push stack\n");
|
||||||
if (ctx->w == RES_IN || ctx->w == RES_FOR) {
|
if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
|
||||||
syntax();
|
syntax();
|
||||||
free(new);
|
free(new);
|
||||||
ctx->w = RES_SNTX;
|
ctx->res_w = RES_SNTX;
|
||||||
b_reset(dest);
|
b_reset(dest);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
*new = *ctx; /* physical copy */
|
*new = *ctx; /* physical copy */
|
||||||
initialize_context(ctx);
|
initialize_context(ctx);
|
||||||
ctx->stack = new;
|
ctx->stack = new;
|
||||||
} else if (ctx->w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
|
} else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
|
||||||
syntax();
|
syntax();
|
||||||
ctx->w = RES_SNTX;
|
ctx->res_w = RES_SNTX;
|
||||||
b_reset(dest);
|
b_reset(dest);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ctx->w = r->code;
|
ctx->res_w = r->code;
|
||||||
ctx->old_flag = r->flag;
|
ctx->old_flag = r->flag;
|
||||||
if (ctx->old_flag & FLAG_END) {
|
if (ctx->old_flag & FLAG_END) {
|
||||||
struct p_context *old;
|
struct p_context *old;
|
||||||
@ -2623,7 +2622,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
|
|||||||
glob_t *glob_target;
|
glob_t *glob_target;
|
||||||
int gr, flags = 0;
|
int gr, flags = 0;
|
||||||
|
|
||||||
debug_printf_parse("done_word: '%s' %p\n", dest->data, child);
|
debug_printf_parse("done_word entered: '%s' %p\n", dest->data, child);
|
||||||
if (dest->length == 0 && !dest->nonnull) {
|
if (dest->length == 0 && !dest->nonnull) {
|
||||||
debug_printf_parse("done_word return 0: true null, ignored\n");
|
debug_printf_parse("done_word return 0: true null, ignored\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -2636,15 +2635,16 @@ static int done_word(o_string *dest, struct p_context *ctx)
|
|||||||
debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n");
|
debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) {
|
if (!child->argv && (ctx->parse_type & FLAG_PARSE_SEMICOLON)) {
|
||||||
debug_printf_parse(": checking %s for reserved-ness\n", dest->data);
|
debug_printf_parse(": checking '%s' for reserved-ness\n", dest->data);
|
||||||
if (reserved_word(dest, ctx)) {
|
if (reserved_word(dest, ctx)) {
|
||||||
debug_printf_parse("done_word return %d\n", (ctx->w == RES_SNTX));
|
debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX));
|
||||||
return (ctx->w == RES_SNTX);
|
return (ctx->res_w == RES_SNTX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glob_target = &child->glob_result;
|
glob_target = &child->glob_result;
|
||||||
if (child->argv) flags |= GLOB_APPEND;
|
if (child->argv)
|
||||||
|
flags |= GLOB_APPEND;
|
||||||
}
|
}
|
||||||
gr = xglob(dest, flags, glob_target);
|
gr = xglob(dest, flags, glob_target);
|
||||||
if (gr != 0) {
|
if (gr != 0) {
|
||||||
@ -2663,7 +2663,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
|
|||||||
} else {
|
} else {
|
||||||
child->argv = glob_target->gl_pathv;
|
child->argv = glob_target->gl_pathv;
|
||||||
}
|
}
|
||||||
if (ctx->w == RES_FOR) {
|
if (ctx->res_w == RES_FOR) {
|
||||||
done_word(dest, ctx);
|
done_word(dest, ctx);
|
||||||
done_pipe(ctx, PIPE_SEQ);
|
done_pipe(ctx, PIPE_SEQ);
|
||||||
}
|
}
|
||||||
@ -2676,56 +2676,63 @@ static int done_word(o_string *dest, struct p_context *ctx)
|
|||||||
static int done_command(struct p_context *ctx)
|
static int done_command(struct p_context *ctx)
|
||||||
{
|
{
|
||||||
/* The child is really already in the pipe structure, so
|
/* The child is really already in the pipe structure, so
|
||||||
* advance the pipe counter and make a new, null child.
|
* advance the pipe counter and make a new, null child. */
|
||||||
* 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 pipe *pi = ctx->pipe;
|
||||||
struct child_prog *prog = ctx->child;
|
struct child_prog *child = ctx->child;
|
||||||
|
|
||||||
if (prog && prog->group == NULL
|
if (child) {
|
||||||
&& prog->argv == NULL
|
if (child->group == NULL
|
||||||
&& prog->redirects == NULL
|
&& child->argv == NULL
|
||||||
|
&& child->redirects == NULL
|
||||||
) {
|
) {
|
||||||
debug_printf("done_command: skipping null command\n");
|
debug_printf_parse("done_command: skipping null command\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (prog) {
|
|
||||||
pi->num_progs++;
|
pi->num_progs++;
|
||||||
debug_printf("done_command: num_progs incremented to %d\n", pi->num_progs);
|
debug_printf_parse("done_command: ++num_progs=%d\n", pi->num_progs);
|
||||||
} else {
|
} else {
|
||||||
debug_printf("done_command: initializing\n");
|
debug_printf_parse("done_command: initializing, num_progs=%d\n", pi->num_progs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only real trickiness here is that the uncommitted
|
||||||
|
* child structure is not counted in pi->num_progs. */
|
||||||
pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));
|
pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));
|
||||||
|
child = &pi->progs[pi->num_progs];
|
||||||
|
|
||||||
prog = pi->progs + pi->num_progs;
|
memset(child, 0, sizeof(*child));
|
||||||
memset(prog, 0, sizeof(*prog));
|
/*child->redirects = NULL;*/
|
||||||
/*prog->redirects = NULL;*/
|
/*child->argv = NULL;*/
|
||||||
/*prog->argv = NULL; */
|
/*child->is_stopped = 0;*/
|
||||||
/*prog->is_stopped = 0;*/
|
/*child->group = NULL;*/
|
||||||
/*prog->group = NULL;*/
|
/*child->glob_result.gl_pathv = NULL;*/
|
||||||
/*prog->glob_result.gl_pathv = NULL;*/
|
child->family = pi;
|
||||||
prog->family = pi;
|
/*child->sp = 0;*/
|
||||||
/*prog->sp = 0;*/
|
child->type = ctx->parse_type;
|
||||||
ctx->child = prog;
|
|
||||||
prog->type = ctx->type;
|
|
||||||
|
|
||||||
|
ctx->child = child;
|
||||||
/* but ctx->pipe and ctx->list_head remain unchanged */
|
/* but ctx->pipe and ctx->list_head remain unchanged */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int done_pipe(struct p_context *ctx, pipe_style type)
|
static int done_pipe(struct p_context *ctx, pipe_style type)
|
||||||
{
|
{
|
||||||
struct pipe *new_p;
|
struct pipe *new_p;
|
||||||
|
|
||||||
|
debug_printf_parse("done_pipe entered, followup %d\n", type);
|
||||||
done_command(ctx); /* implicit closure of previous command */
|
done_command(ctx); /* implicit closure of previous command */
|
||||||
debug_printf_parse("done_pipe, type %d\n", type);
|
|
||||||
ctx->pipe->followup = type;
|
ctx->pipe->followup = type;
|
||||||
ctx->pipe->r_mode = ctx->w;
|
ctx->pipe->r_mode = ctx->res_w;
|
||||||
new_p = new_pipe();
|
new_p = new_pipe();
|
||||||
ctx->pipe->next = new_p;
|
ctx->pipe->next = new_p;
|
||||||
ctx->pipe = new_p;
|
ctx->pipe = new_p;
|
||||||
ctx->child = NULL;
|
ctx->child = NULL;
|
||||||
|
// TODO: even just <enter> on command line basically generates
|
||||||
|
// tree of three NOPs (!).
|
||||||
|
// Can we detect that previous done_command have seen "skipping null command"
|
||||||
|
// condition and NOT create new pipe here?
|
||||||
done_command(ctx); /* set up new pipe to accept commands */
|
done_command(ctx); /* set up new pipe to accept commands */
|
||||||
|
debug_printf_parse("done_pipe return 0\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3055,7 +3062,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
|
|||||||
}
|
}
|
||||||
if (m == MAP_IFS_IF_UNQUOTED) {
|
if (m == MAP_IFS_IF_UNQUOTED) {
|
||||||
if (done_word(dest, ctx)) {
|
if (done_word(dest, ctx)) {
|
||||||
debug_printf_parse("parse_stream return 1\n");
|
debug_printf_parse("parse_stream return 1: done_word!=0\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* If we aren't performing a substitution, treat
|
/* If we aren't performing a substitution, treat
|
||||||
@ -3066,9 +3073,9 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((end_trigger && strchr(end_trigger, ch))
|
if ((end_trigger && strchr(end_trigger, ch))
|
||||||
&& !dest->quote && ctx->w == RES_NONE
|
&& !dest->quote && ctx->res_w == RES_NONE
|
||||||
) {
|
) {
|
||||||
debug_printf_parse("parse_stream return 0\n");
|
debug_printf_parse("parse_stream return 0: end_trigger char found\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (m == MAP_IFS_IF_UNQUOTED)
|
if (m == MAP_IFS_IF_UNQUOTED)
|
||||||
@ -3089,7 +3096,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
|
|||||||
case '\\':
|
case '\\':
|
||||||
if (next == EOF) {
|
if (next == EOF) {
|
||||||
syntax();
|
syntax();
|
||||||
debug_printf_parse("parse_stream return 1\n");
|
debug_printf_parse("parse_stream return 1: \\<eof>\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
b_addqchr(dest, '\\', dest->quote);
|
b_addqchr(dest, '\\', dest->quote);
|
||||||
@ -3111,7 +3118,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
|
|||||||
}
|
}
|
||||||
if (ch == EOF) {
|
if (ch == EOF) {
|
||||||
syntax();
|
syntax();
|
||||||
debug_printf_parse("parse_stream return 1\n");
|
debug_printf_parse("parse_stream return 1: unterminated '\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -3204,7 +3211,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
|
|||||||
* that is, we were really supposed to get end_trigger, and never got
|
* 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,
|
* 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. */
|
* so that parse_stream_outer can distinguish the EOF and exit smoothly. */
|
||||||
debug_printf_parse("parse_stream return -%d\n", end_trigger != NULL);
|
debug_printf_parse("parse_stream return %d\n", -(end_trigger != NULL));
|
||||||
if (end_trigger)
|
if (end_trigger)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -3220,7 +3227,8 @@ static void update_ifs_map(void)
|
|||||||
{
|
{
|
||||||
/* char *ifs and char map[256] are both globals. */
|
/* char *ifs and char map[256] are both globals. */
|
||||||
ifs = getenv("IFS");
|
ifs = getenv("IFS");
|
||||||
if (ifs == NULL) ifs = " \t\n";
|
if (ifs == NULL)
|
||||||
|
ifs = " \t\n";
|
||||||
/* Precompute a list of 'flow through' behavior so it can be treated
|
/* Precompute a list of 'flow through' behavior so it can be treated
|
||||||
* quickly up front. Computation is necessary because of IFS.
|
* quickly up front. Computation is necessary because of IFS.
|
||||||
* Special case handling of IFS == " \t\n" is not implemented.
|
* Special case handling of IFS == " \t\n" is not implemented.
|
||||||
@ -3235,24 +3243,26 @@ static void update_ifs_map(void)
|
|||||||
|
|
||||||
/* most recursion does not come through here, the exception is
|
/* most recursion does not come through here, the exception is
|
||||||
* from builtin_source() */
|
* from builtin_source() */
|
||||||
static int parse_stream_outer(struct in_str *inp, int flag)
|
static int parse_stream_outer(struct in_str *inp, int parse_flag)
|
||||||
{
|
{
|
||||||
// FIXME: '{ true | exit 3; echo $? }' is parsed as a whole,
|
// FIXME: '{ true | exit 3; echo $? }' is parsed as a whole,
|
||||||
// as a result $? is replaced by 0, not 3!
|
// as a result $? is replaced by 0, not 3!
|
||||||
// Need to stop & execute stuff at ';', not parse till EOL!
|
|
||||||
|
|
||||||
struct p_context ctx;
|
struct p_context ctx;
|
||||||
o_string temp = NULL_O_STRING;
|
o_string temp = NULL_O_STRING;
|
||||||
int rcode;
|
int rcode;
|
||||||
do {
|
do {
|
||||||
ctx.type = flag;
|
ctx.parse_type = parse_flag;
|
||||||
initialize_context(&ctx);
|
initialize_context(&ctx);
|
||||||
update_ifs_map();
|
update_ifs_map();
|
||||||
if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING))
|
if (!(parse_flag & FLAG_PARSE_SEMICOLON) || (parse_flag & FLAG_REPARSING))
|
||||||
mapset(";$&|", MAP_ORDINARY);
|
mapset(";$&|", MAP_ORDINARY);
|
||||||
#if ENABLE_HUSH_INTERACTIVE
|
#if ENABLE_HUSH_INTERACTIVE
|
||||||
inp->promptmode = 1;
|
inp->promptmode = 1;
|
||||||
#endif
|
#endif
|
||||||
|
/* We will stop & execute after each ';' or '\n'.
|
||||||
|
* Example: "sleep 9999; echo TEST" + ctrl-C:
|
||||||
|
* TEST should be printed */
|
||||||
rcode = parse_stream(&temp, &ctx, inp, ";\n");
|
rcode = parse_stream(&temp, &ctx, inp, ";\n");
|
||||||
if (rcode != 1 && ctx.old_flag != 0) {
|
if (rcode != 1 && ctx.old_flag != 0) {
|
||||||
syntax();
|
syntax();
|
||||||
@ -3274,15 +3284,15 @@ static int parse_stream_outer(struct in_str *inp, int flag)
|
|||||||
free_pipe_list(ctx.list_head, 0);
|
free_pipe_list(ctx.list_head, 0);
|
||||||
}
|
}
|
||||||
b_free(&temp);
|
b_free(&temp);
|
||||||
} while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */
|
} while (rcode != -1 && !(parse_flag & FLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_string_outer(const char *s, int flag)
|
static int parse_string_outer(const char *s, int parse_flag)
|
||||||
{
|
{
|
||||||
struct in_str input;
|
struct in_str input;
|
||||||
setup_string_in_str(&input, s);
|
setup_string_in_str(&input, s);
|
||||||
return parse_stream_outer(&input, flag);
|
return parse_stream_outer(&input, parse_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_file_outer(FILE *f)
|
static int parse_file_outer(FILE *f)
|
||||||
@ -3303,7 +3313,7 @@ static void setup_job_control(void)
|
|||||||
pid_t shell_pgrp;
|
pid_t shell_pgrp;
|
||||||
|
|
||||||
saved_task_pgrp = shell_pgrp = getpgrp();
|
saved_task_pgrp = shell_pgrp = getpgrp();
|
||||||
debug_printf("saved_task_pgrp=%d\n", saved_task_pgrp);
|
debug_printf_jobs("saved_task_pgrp=%d\n", saved_task_pgrp);
|
||||||
fcntl(interactive_fd, F_SETFD, FD_CLOEXEC);
|
fcntl(interactive_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
/* If we were ran as 'hush &',
|
/* If we were ran as 'hush &',
|
||||||
@ -3319,7 +3329,7 @@ static void setup_job_control(void)
|
|||||||
set_misc_sighandler(SIG_IGN);
|
set_misc_sighandler(SIG_IGN);
|
||||||
//huh? signal(SIGCHLD, SIG_IGN);
|
//huh? signal(SIGCHLD, SIG_IGN);
|
||||||
|
|
||||||
/* We _must_ restore tty pgrp fatal signals */
|
/* We _must_ restore tty pgrp on fatal signals */
|
||||||
set_fatal_sighandler(sigexit);
|
set_fatal_sighandler(sigexit);
|
||||||
|
|
||||||
/* Put ourselves in our own process group. */
|
/* Put ourselves in our own process group. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user