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

Reply via email to