From b6bbf18e93b7a8543f10c4bfcf2394c623c29d23 Mon Sep 17 00:00:00 2001
From: Hugues Morisset <morisset.hugues@gmail.com>
Date: Mon, 29 Aug 2022 11:21:42 +0200
Subject: [PATCH] Choose connector for new lines instead of ;

Add BASH_CMD_CONNECTOR special variable which set the
command connectors for new lines.

This allow users to write scripts that will fail at the first
unhandled error using BASH_CMD_CONNECTOR='&&' without
the fuss of adding it on each lines and makes reading easier.

Another use case is having a list of command executed in //
with BASH_CMD_CONNECTOR='&'

Also a function that would fallback to the first working command

config_fallback() { local BASH_CMD_CONNECTOR='||'; {
        [[ -f /config ]] && echo /config
        [[ -f /home/u/config ]] && echo /home/u/config
        [[ -f /deprecated ]] && echo /deprecated
        echo "Couldn't find config"
} }
---
 config-top.h  |  3 +++
 execute_cmd.c | 17 +++++++++++++++++
 parse.y       |  4 ++--
 print_cmd.c   |  3 +++
 variables.c   |  3 +++
 5 files changed, 28 insertions(+), 2 deletions(-)

diff --git config-top.h config-top.h
index 735f75e3..c284eb33 100644
--- config-top.h
+++ config-top.h
@@ -193,3 +193,6 @@
 /* Undefine or define to 0 if you don't want to allow associative array
    assignment using a compound list of key-value pairs. */
 #define ASSOC_KVPAIR_ASSIGNMENT 1
+
+/* Define to the default connector replacing newlines in command list */
+#define DEFAULT_CONNECTOR ";"
diff --git execute_cmd.c execute_cmd.c
index 425679a2..17ee93ff 100644
--- execute_cmd.c
+++ execute_cmd.c
@@ -2798,6 +2798,23 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
       executing_list--;
       break;
 
+    case END_OF_LINE:
+        if (command->value.Connection->connector == END_OF_LINE) {
+            const char* def_conn_str = get_string_value ("BASH_CMD_CONNECTOR");
+            command->value.Connection->connector = DEFAULT_CONNECTOR;
+            if (def_conn_str) {
+              if (!strcmp("&&", def_conn_str)) {
+                command->value.Connection->connector = AND_AND;
+              } else if (!strcmp("||", def_conn_str)) {
+                command->value.Connection->connector = OR_OR;
+              } else if (def_conn_str[0] && strchr("&|;", def_conn_str[0])) {
+                command->value.Connection->connector = def_conn_str[0];
+              }
+            }
+        }
+	    exec_result = execute_connection(command, asynchronous, pipe_in, pipe_out, fds_to_close);
+      break;
+
     default:
       command_error ("execute_connection", CMDERR_BADCONN, command->value.Connection->connector, 0);
       jump_to_top_level (DISCARD);
diff --git parse.y parse.y
index f4168c7c..77c4feae 100644
--- parse.y
+++ parse.y
@@ -351,7 +351,7 @@ static FILE *yyerrstream;
 %token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND LESS_LESS_LESS
 %token GREATER_AND SEMI_SEMI SEMI_AND SEMI_SEMI_AND
 %token LESS_LESS_MINUS AND_GREATER AND_GREATER_GREATER LESS_GREATER
-%token GREATER_BAR BAR_AND
+%token GREATER_BAR BAR_AND END_OF_LINE
 
 /* The types that the various syntactical units return. */
 
@@ -1135,7 +1135,7 @@ list1:		list1 AND_AND newline_list list1
 	|	list1 ';' newline_list list1
 			{ $$ = command_connect ($1, $4, ';'); }
 	|	list1 '\n' newline_list list1
-			{ $$ = command_connect ($1, $4, ';'); }
+			{ $$ = command_connect ($1, $4, END_OF_LINE); }
 	|	pipeline_command
 			{ $$ = $1; }
 	;
diff --git print_cmd.c print_cmd.c
index 3c8c2d8f..ea9694de 100644
--- print_cmd.c
+++ print_cmd.c
@@ -298,6 +298,9 @@ make_command_string_internal (command)
 		}
 	      break;
 
+        case END_OF_LINE:
+            cprintf ("\n");
+          break;
 	    default:
 	      cprintf (_("print_command: bad connector `%d'"),
 		       command->value.Connection->connector);
diff --git variables.c variables.c
index 73f157fb..2d5006d9 100644
--- variables.c
+++ variables.c
@@ -673,6 +673,9 @@ initialize_shell_variables (env, privmode)
   /* Allow FUNCNEST to be inherited from the environment. */
   sv_funcnest ("FUNCNEST");
 
+    /* Make a variable called BASH_VERSION which contains the version info. */
+  bind_variable ("BASH_CMD_CONNECTOR", DEFAULT_CONNECTOR, 0);
+
   /* Initialize the dynamic variables, and seed their values. */
   initialize_dynamic_variables ();
 }
-- 
2.37.2

