Check Ctrl-C status before executing each command in the pipeline so that the Ctrl-C can skip all subsequent commands. in the meantime, we need to clear the ctrlc status at the end of a pipeline. This should be the default behavior of most shell parsers.
Before the change: ``` => echo start; while true; do echo loop; sleep 1; done; echo int; if true; then echo if; fi; echo stop start loop loop <-- Input Ctrl-C int if stop => ``` After the change: ``` => echo start; while true; do echo loop; sleep 1; done; echo int; if true; then echo if; fi; echo stop start loop loop <-- Input Ctrl-C ^C => ``` Signed-off-by: Shiji Yang <[email protected]> --- v1 --> v2: - use puts() instead of printf() - only clear Ctrl-C status when one pipe reaches the end common/cli_hush.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/common/cli_hush.c b/common/cli_hush.c index 7bd6943d3ed..3f6adc01934 100644 --- a/common/cli_hush.c +++ b/common/cli_hush.c @@ -1792,16 +1792,15 @@ static int run_list_real(struct pipe *pi) } } for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) { - if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL || - pi->r_mode == RES_FOR) { #ifdef __U_BOOT__ - /* check Ctrl-C */ - ctrlc(); - if ((had_ctrlc())) { - return 1; - } + /* check Ctrl-C */ + ctrlc(); + if (had_ctrlc()) + return 1; #endif - flag_restore = 0; + if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL || + pi->r_mode == RES_FOR) { + flag_restore = 0; if (!rpipe) { flag_rep = 0; rpipe = pi; @@ -3207,6 +3206,11 @@ static int parse_stream_outer(struct in_str *inp, int flag) run_list(ctx.list_head); #else code = run_list(ctx.list_head); + /* clear Ctrl-C status when one pipe reaches the end */ + if (had_ctrlc() && !(flag & FLAG_REPARSING)) { + puts("^C\n"); + clear_ctrlc(); + } if (code == -2) { /* exit */ b_free(&temp); code = 0; -- 2.51.0

