Hi, Below is the patch for the new 'errfail' option.
Please note that this is MINIMAL implementation. It will cover the cases below. Possible to think about this as replacing every ';' (or new line line that terminate statements) with '&&' - forcing execution to break. . Patch is minimal (less than 15 lines of code changes), and is low-risk - all changes are conditional on the (global) flag setting. No complex logic, No write of functions. Feedback/comments are welcomed. set -o errfail function foo { echo A ; false ; echo B ; } function bar { echo C ; foo ; echo D ; } # Will print A, return non-zero status foo # Return from function on first error # Will print A, CATCH foo || { echo CATCH ; } # Failures will propagate through function calls, unless explicitly "caught" # Print C A CATCH bar || echo CATCH # Fancier: "throw" function throw { echo "${0##*/}: $@" >& 2 ; false ; } function foo { if [ ! -f required-file.txt ] ; then throw "Missing required file" fi echo "YES" } Small Letters: * The errfail does NOT cover "top-level" errors. Only "connected" statements. Either create a 'main' function, or create a top level block: On Tue, Jul 5, 2022 at 12:00 AM Lawrence Velázquez <v...@larryv.me> wrote: > On Mon, Jul 4, 2022, at 3:55 PM, Yair Lenga wrote: > > I'm sorry - I misunderstood your original comments. I'll prepare the > > patched version (at least, I would like to add comments before > > publishing...) , and share it. > > Where/how can I post it ? > > Send it to this list as an attachment [1] with a .txt suffix [2]. > > [1] Gmail will mangle the patch if you send it inline. > [2] Alleviates issues with clients on the receiving end. > > > I did not see anyone else dropping source > > code/patches into the group ? > > Code contributions are not as common as you might think, given > bash's prominence. > > -- > vq >
diff -ru orig/bash-master/builtins/set.def new/bash-master/builtins/set.def --- orig/bash-master/builtins/set.def 2022-01-05 00:03:45.000000000 +0200 +++ new/bash-master/builtins/set.def 2022-07-05 11:54:31.545828400 +0300 @@ -76,6 +76,8 @@ emacs use an emacs-style line editing interface #endif /* READLINE */ errexit same as -e + errfail execution of command lists will stop whenever + a single command return non-zero status errtrace same as -E functrace same as -T hashall same as -h @@ -196,6 +198,7 @@ { "emacs", '\0', (int *)NULL, set_edit_mode, get_edit_mode }, #endif { "errexit", 'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, + { "errfail", '\0', &errfail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, { "errtrace", 'E', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, { "functrace", 'T', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, { "hashall", 'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, @@ -655,6 +658,7 @@ { pipefail_opt = 0; ignoreeof = 0; +/* errfail_opt = 0 ; errfail IS inherit by sub-shells */ #if defined (STRICT_POSIX) posixly_correct = 1; diff -ru orig/bash-master/execute_cmd.c new/bash-master/execute_cmd.c --- orig/bash-master/execute_cmd.c 2022-01-05 00:03:45.000000000 +0200 +++ new/bash-master/execute_cmd.c 2022-07-05 13:03:18.379533800 +0300 @@ -2706,7 +2706,7 @@ QUIT; #if 1 - execute_command (command->value.Connection->first); + exec_result = execute_command (command->value.Connection->first); #else execute_command_internal (command->value.Connection->first, asynchronous, pipe_in, pipe_out, @@ -2714,10 +2714,15 @@ #endif QUIT; - optimize_fork (command); /* XXX */ - exec_result = execute_command_internal (command->value.Connection->second, + + /* With errfail, the ';' is similar to '&&' */ + /* Execute the second part, only if first part was OK */ + if ( !errfail_opt || exec_result == EXECUTION_SUCCESS ) { + optimize_fork (command); /* XXX */ + exec_result = execute_command_internal (command->value.Connection->second, asynchronous, pipe_in, pipe_out, fds_to_close); + } ; executing_list--; break; diff -ru orig/bash-master/flags.c new/bash-master/flags.c --- orig/bash-master/flags.c 2022-01-05 00:03:45.000000000 +0200 +++ new/bash-master/flags.c 2022-07-05 13:42:12.287799400 +0300 @@ -156,6 +156,12 @@ with a 0 status, the status of the pipeline is 0. */ int pipefail_opt = 0; +/* Non-zero means that when executing connected commands (';' or new lines) + the sequence will be stopped when any individual commands return a non-zero + status. Similar to '&&'. Used for improved error handling */ + +int errfail_opt = 0; + /* **************************************************************** */ /* */ /* The Flags ALIST. */ diff -ru orig/bash-master/flags.h new/bash-master/flags.h --- orig/bash-master/flags.h 2022-01-05 00:03:45.000000000 +0200 +++ new/bash-master/flags.h 2022-07-05 11:25:14.515741700 +0300 @@ -48,7 +48,7 @@ echo_command_at_execute, noclobber, hashing_enabled, forced_interactive, privileged_mode, jobs_m_flag, asynchronous_notification, interactive_comments, no_symbolic_links, - function_trace_mode, error_trace_mode, pipefail_opt; + function_trace_mode, error_trace_mode, pipefail_opt, errfail_opt; /* -c, -s invocation options -- not really flags, but they show up in $- */ extern int want_pending_command, read_from_stdin;