From: Chet Ramey Date: Fri, 27 Sep 2024 16:00:46 +0000 (-0400) Subject: fix for set -e and compound commands inverting return status; tty fix for `fg' from... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=254081c09767738833cdf161b4bc3feb1a51690a;p=thirdparty%2Fbash.git fix for set -e and compound commands inverting return status; tty fix for `fg' from a key binding; posix mode `wait -n' can return notified jobs; off-by-one error in history word tokenization; new configure option to set bash_source_fullpath --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 678be422..6291e6ae 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -10228,3 +10228,57 @@ jobs.c - wait_for_single_pid: if wait finds a status for the pid argument in the bgp list, remove it from the bgp list if the shell is in posix mode + + 9/23 + ---- +execute_cmd.c + - execute_command_internal: if the COMMAND * passed in to execute has + the CMD_INVERT_RETURN flag set, make sure we propagate that to + simple commands, for commands, arith for commands, select commands, + case commands, while/until commands, if commands, group commands, + shell functions, pipelines, subshells, and connections so if set -e + is enabled in the body (or test for if/while/until) its effect is + ignored + - execute_in_subshell: if the subshell's return status is being inverted, + make sure to ignore set -e in the commands the subshell executes + - execute_pipeline: if the pipeline's return status is being inverted, + make sure to ignore the effects of set -e in all pipeline elements + - execute_connection: if the list's return status is being inverted + (tough to do because of precedence), make sure the list commands + ignore the effect of set -e + + 9/24 + ---- +jobs.c + - start_job: don't fetch the tty settings if we're being called from + a readline key binding (bind -x) or programmable completion + From a report by David Moberg + + 9/25 + ---- +jobs.c + - wait_for_any_job: if the jobs table is empty and there are no + eligible procsubs, and the shell is in posix mode, take a random + pid from the bgpids table, delete it, and return its status + (since we would be deleting that pid from bgpids anyway) + + 9/26 + ---- +lib/readline/histexpand.c + - history_tokenize_word: fix off-by-one error (incrementing i one too + many positions after the increment in the loop) preventing words + like `$((expr))' from being tokenized correctly + Report from Milana <94888u@riseup.net> + +config.h.in,configure.ac + - new option: bash-source-fullpath-default: set it to make the + bash_source_fullpath option enabled by default; sets + BASH_SOURCE_FULLPATH_DEFAULT + Based on a patch from konsolebox + +variables.c + - bash_source_fullpath: initialize to BASH_SOURCE_FULLPATH_DEFAULT, + set by configure + +doc/bashref.texi + - --enable-bash-source-default: document diff --git a/MANIFEST b/MANIFEST index ede4b45b..a6f2fddc 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1178,6 +1178,7 @@ tests/exec12.sub f tests/exec13.sub f tests/exec14.sub f tests/exec15.sub f +tests/exec16.sub f tests/exp.tests f tests/exp.right f tests/exp1.sub f diff --git a/MANIFEST.doc b/MANIFEST.doc index ab9507c4..d062fc61 100644 --- a/MANIFEST.doc +++ b/MANIFEST.doc @@ -5,11 +5,10 @@ doc d MANIFEST.doc f doc/article.ps f doc/rose94.ps f -doc/bash.ps f +doc/bash.ps f doc/bashbug.ps f doc/builtins.ps f doc/rbash.ps f -doc/bashref.ps f doc/bashref.dvi f doc/bash.0 f doc/bashbug.0 f @@ -18,8 +17,11 @@ doc/rbash.0 f doc/article.txt f doc/bash.html f doc/bashref.html f +doc/bash.info f +doc/bashref.info f doc/article.pdf f doc/bash.pdf f doc/bashref.pdf f doc/rose94.pdf f doc/aosa-bash.pdf f +doc/aosa-bash-full.pdf f diff --git a/config.h.in b/config.h.in index 97f9a39d..dbef3a74 100644 --- a/config.h.in +++ b/config.h.in @@ -178,6 +178,9 @@ /* Define to allow functions to be imported from the environment. */ #undef FUNCTION_IMPORT +/* Define to make the `bash_source_fullpath' option enabled by default. */ +#undef BASH_SOURCE_FULLPATH_DEFAULT + /* Define AFS if you are using Transarc's AFS. */ #undef AFS diff --git a/configure b/configure index 3d060a5b..9c41015a 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac for Bash 5.3, version 5.068. +# From configure.ac for Bash 5.3, version 5.069. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.72 for bash 5.3-beta. # @@ -852,6 +852,7 @@ enable_alt_array_implementation enable_arith_for_command enable_array_variables enable_bang_history +enable_bash_source_fullpath_default enable_brace_expansion enable_casemod_attributes enable_casemod_expansions @@ -1547,6 +1548,8 @@ Optional Features: --enable-array-variables include shell array variables --enable-bang-history turn on csh-style history substitution + --enable-bash-source-fullpath-default + enable the bash_source_fullpath option by default --enable-brace-expansion include brace expansion --enable-casemod-attributes @@ -3455,6 +3458,7 @@ opt_function_import=yes opt_dev_fd_stat_broken=no opt_alt_array_impl=no opt_translatable_strings=yes +opt_bash_source_fullpath=no ARRAY_O=array.o @@ -3480,6 +3484,7 @@ if test $opt_minimal_config = yes; then opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no opt_translatable_strings=no opt_globascii_default=yes + opt_bash_source_fullpath=no fi # Check whether --enable-alias was given. @@ -3512,6 +3517,12 @@ then : enableval=$enable_bang_history; opt_bang_history=$enableval fi +# Check whether --enable-bash-source-fullpath-default was given. +if test ${enable_bash_source_fullpath_default+y} +then : + enableval=$enable_bash_source_fullpath_default; opt_bash_source_fullpath_default=$enableval +fi + # Check whether --enable-brace-expansion was given. if test ${enable_brace_expansion+y} then : @@ -3877,6 +3888,13 @@ fi if test $opt_translatable_strings = yes; then printf "%s\n" "#define TRANSLATABLE_STRINGS 1" >>confdefs.h +fi +if test $opt_bash_source_fullpath_default = yes; then +printf "%s\n" "#define BASH_SOURCE_FULLPATH_DEFAULT 1" >>confdefs.h + +else +printf "%s\n" "#define BASH_SOURCE_FULLPATH_DEFAULT 0" >>confdefs.h + fi if test $opt_memscramble = yes; then @@ -9200,8 +9218,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ LIBS=$save_LIBS test $gl_pthread_api = yes && break done - echo "$as_me:9203: gl_pthread_api=$gl_pthread_api" >&5 - echo "$as_me:9204: LIBPTHREAD=$LIBPTHREAD" >&5 + echo "$as_me:9221: gl_pthread_api=$gl_pthread_api" >&5 + echo "$as_me:9222: LIBPTHREAD=$LIBPTHREAD" >&5 gl_pthread_in_glibc=no # On Linux with glibc >= 2.34, libc contains the fully functional @@ -9227,7 +9245,7 @@ rm -rf conftest* ;; esac - echo "$as_me:9230: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 + echo "$as_me:9248: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 # Test for libpthread by looking for pthread_kill. (Not pthread_self, # since it is defined as a macro on OSF/1.) @@ -9405,7 +9423,7 @@ fi fi fi - echo "$as_me:9408: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 + echo "$as_me:9426: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5 printf %s "checking whether POSIX threads API is available... " >&6; } @@ -9652,8 +9670,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ LIBS=$save_LIBS test $gl_pthread_api = yes && break done - echo "$as_me:9655: gl_pthread_api=$gl_pthread_api" >&5 - echo "$as_me:9656: LIBPTHREAD=$LIBPTHREAD" >&5 + echo "$as_me:9673: gl_pthread_api=$gl_pthread_api" >&5 + echo "$as_me:9674: LIBPTHREAD=$LIBPTHREAD" >&5 gl_pthread_in_glibc=no # On Linux with glibc >= 2.34, libc contains the fully functional @@ -9679,7 +9697,7 @@ rm -rf conftest* ;; esac - echo "$as_me:9682: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 + echo "$as_me:9700: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 # Test for libpthread by looking for pthread_kill. (Not pthread_self, # since it is defined as a macro on OSF/1.) @@ -9857,7 +9875,7 @@ fi fi fi - echo "$as_me:9860: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 + echo "$as_me:9878: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5 printf %s "checking whether POSIX threads API is available... " >&6; } diff --git a/configure.ac b/configure.ac index 88fc47f6..d29c8861 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script. # You should have received a copy of the GNU General Public License # along with this program. If not, see . -AC_REVISION([for Bash 5.3, version 5.068])dnl +AC_REVISION([for Bash 5.3, version 5.069])dnl define(bashvers, 5.3) define(relstatus, beta) @@ -186,6 +186,7 @@ opt_function_import=yes opt_dev_fd_stat_broken=no opt_alt_array_impl=no opt_translatable_strings=yes +opt_bash_source_fullpath=no dnl modified by alternate array implementation option ARRAY_O=array.o @@ -211,6 +212,7 @@ if test $opt_minimal_config = yes; then opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no opt_translatable_strings=no opt_globascii_default=yes + opt_bash_source_fullpath=no fi AC_ARG_ENABLE(alias, AS_HELP_STRING([--enable-alias], [enable shell aliases]), opt_alias=$enableval) @@ -218,6 +220,7 @@ AC_ARG_ENABLE(alt-array-implementation, AS_HELP_STRING([--enable-alt-array-imple AC_ARG_ENABLE(arith-for-command, AS_HELP_STRING([--enable-arith-for-command], [enable arithmetic for command]), opt_arith_for_command=$enableval) AC_ARG_ENABLE(array-variables, AS_HELP_STRING([--enable-array-variables], [include shell array variables]), opt_array_variables=$enableval) AC_ARG_ENABLE(bang-history, AS_HELP_STRING([--enable-bang-history], [turn on csh-style history substitution]), opt_bang_history=$enableval) +AC_ARG_ENABLE(bash-source-fullpath-default, AS_HELP_STRING([--enable-bash-source-fullpath-default], [enable the bash_source_fullpath option by default]), opt_bash_source_fullpath_default=$enableval) AC_ARG_ENABLE(brace-expansion, AS_HELP_STRING([--enable-brace-expansion], [include brace expansion]), opt_brace_expansion=$enableval) AC_ARG_ENABLE(casemod-attributes, AS_HELP_STRING([--enable-casemod-attributes], [include case-modifying variable attributes]), opt_casemod_attrs=$enableval) AC_ARG_ENABLE(casemod-expansions, AS_HELP_STRING([--enable-casemod-expansions], [include case-modifying word expansions]), opt_casemod_expansions=$enableval) @@ -371,6 +374,11 @@ fi if test $opt_translatable_strings = yes; then AC_DEFINE(TRANSLATABLE_STRINGS) fi +if test $opt_bash_source_fullpath_default = yes; then +AC_DEFINE(BASH_SOURCE_FULLPATH_DEFAULT, 1) +else +AC_DEFINE(BASH_SOURCE_FULLPATH_DEFAULT, 0) +fi if test $opt_memscramble = yes; then AC_DEFINE(MEMSCRAMBLE) diff --git a/doc/bash.1 b/doc/bash.1 index 244094a2..f7eedcbb 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -6565,6 +6565,9 @@ may change if the locale is changed. If set to \fBOn\fP, readline uses an internal \fImore\fP-like pager to display a screenful of possible completions at a time. .TP +.B prefer\-visible\-bell +See \fBbell\-style\fP. +.TP .B print\-completions\-horizontally (Off) If set to \fBOn\fP, readline will display completions with matches sorted horizontally in alphabetical order, rather than down the screen. diff --git a/doc/bashref.texi b/doc/bashref.texi index 684b217e..342d706d 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -9907,6 +9907,12 @@ Include support for one-dimensional array shell variables Include support for @code{csh}-like history substitution (@pxref{History Interaction}). +@item --enable-bash-source-fullpath-default +Set the default value of the @code{bash_source_fullpath} shell option described +above under @ref{The Shopt Builtin} to be enabled. +This controls how filenames are assigned to the @code{BASH_SOURCE} +array variable. + @item --enable-brace-expansion Include @code{csh}-like brace expansion ( @code{b@{a,b@}c} @expansion{} @code{bac bbc} ). diff --git a/execute_cmd.c b/execute_cmd.c index 6402f894..758fbf5e 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -905,7 +905,7 @@ execute_command_internal (COMMAND *command, int asynchronous, int pipe_in, int p #endif was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; - if (ignore_return && command->value.Simple) + if ((ignore_return || invert) && command->value.Simple) command->value.Simple->flags |= CMD_IGNORE_RETURN; if (command->flags & CMD_STDIN_REDIR) command->value.Simple->flags |= CMD_STDIN_REDIR; @@ -1012,14 +1012,14 @@ execute_command_internal (COMMAND *command, int asynchronous, int pipe_in, int p break; case cm_for: - if (ignore_return) + if (ignore_return || invert) command->value.For->flags |= CMD_IGNORE_RETURN; exec_result = execute_for_command (command->value.For); break; #if defined (ARITH_FOR_COMMAND) case cm_arith_for: - if (ignore_return) + if (ignore_return || invert) command->value.ArithFor->flags |= CMD_IGNORE_RETURN; exec_result = execute_arith_for_command (command->value.ArithFor); break; @@ -1027,32 +1027,32 @@ execute_command_internal (COMMAND *command, int asynchronous, int pipe_in, int p #if defined (SELECT_COMMAND) case cm_select: - if (ignore_return) + if (ignore_return || invert) command->value.Select->flags |= CMD_IGNORE_RETURN; exec_result = execute_select_command (command->value.Select); break; #endif case cm_case: - if (ignore_return) + if (ignore_return || invert) command->value.Case->flags |= CMD_IGNORE_RETURN; exec_result = execute_case_command (command->value.Case); break; case cm_while: - if (ignore_return) + if (ignore_return || invert) command->value.While->flags |= CMD_IGNORE_RETURN; exec_result = execute_while_command (command->value.While); break; case cm_until: - if (ignore_return) + if (ignore_return || invert) command->value.While->flags |= CMD_IGNORE_RETURN; exec_result = execute_until_command (command->value.While); break; case cm_if: - if (ignore_return) + if (ignore_return || invert) command->value.If->flags |= CMD_IGNORE_RETURN; exec_result = execute_if_command (command->value.If); break; @@ -1092,7 +1092,11 @@ execute_command_internal (COMMAND *command, int asynchronous, int pipe_in, int p } else { - if (ignore_return && command->value.Group->command) + /* If we're already ignoring the return value of this group command, + or if the return value is being inverted, make sure to ignore + set -e for the duration of the command, even if the group + command enables it. */ + if ((ignore_return || invert) && command->value.Group->command) command->value.Group->command->flags |= CMD_IGNORE_RETURN; exec_result = execute_command_internal (command->value.Group->command, @@ -1586,7 +1590,7 @@ execute_in_subshell (COMMAND *command, int asynchronous, int pipe_in, int pipe_o /* If a command is asynchronous in a subshell (like ( foo ) & or the special case of an asynchronous GROUP command where the - subshell bit is turned on down in case cm_group: below), + subshell bit is turned on down in case cm_group: above), turn off `asynchronous', so that two subshells aren't spawned. XXX - asynchronous used to be set to 0 in this block, but that means that setup_async_signals was never run. Now it's set to @@ -1774,6 +1778,10 @@ execute_in_subshell (COMMAND *command, int asynchronous, int pipe_in, int pipe_o /* Make sure the subshell inherits any CMD_IGNORE_RETURN flag. */ if ((command->flags & CMD_IGNORE_RETURN) && tcom != command) tcom->flags |= CMD_IGNORE_RETURN; + /* If the subshell's return value is being inverted, ignore set -e even + if the subshell enables it. */ + if (invert) + tcom->flags |= CMD_IGNORE_RETURN; /* If this is a simple command, tell execute_disk_command that it might be able to get away without forking and simply exec. @@ -2603,7 +2611,7 @@ uw_lastpipe_cleanup (void *s) static int execute_pipeline (COMMAND *command, int asynchronous, int pipe_in, int pipe_out, struct fd_bitmap *fds_to_close) { - int prev, fildes[2], new_bitmap_size, dummyfd, ignore_return, exec_result; + int prev, fildes[2], new_bitmap_size, dummyfd, ignore_return, invert, exec_result; int lstdin, lastpipe_flag, lastpipe_jid, old_frozen, stdin_valid; COMMAND *cmd; struct fd_bitmap *fd_bitmap; @@ -2615,6 +2623,7 @@ execute_pipeline (COMMAND *command, int asynchronous, int pipe_in, int pipe_out, #endif /* JOB_CONTROL */ ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; + invert = (command->flags & CMD_INVERT_RETURN) != 0; stdin_valid = sh_validfd (0); @@ -2682,7 +2691,7 @@ execute_pipeline (COMMAND *command, int asynchronous, int pipe_in, int pipe_out, add_unwind_protect (uw_restore_signal_mask, &oset); #endif /* JOB_CONTROL */ - if (ignore_return && cmd->value.Connection->first) + if ((ignore_return || invert) && cmd->value.Connection->first) cmd->value.Connection->first->flags |= CMD_IGNORE_RETURN; execute_command_internal (cmd->value.Connection->first, asynchronous, prev, fildes[1], fd_bitmap); @@ -2702,7 +2711,7 @@ execute_pipeline (COMMAND *command, int asynchronous, int pipe_in, int pipe_out, lastpid = last_made_pid; /* Now execute the rightmost command in the pipeline. */ - if (ignore_return && cmd) + if ((ignore_return || invert) && cmd) cmd->flags |= CMD_IGNORE_RETURN; lastpipe_flag = 0; @@ -2798,6 +2807,7 @@ execute_connection (COMMAND *command, int asynchronous, int pipe_in, int pipe_ou volatile int save_line_number; ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; + invert = (command->flags & CMD_INVERT_RETURN) != 0; switch (command->value.Connection->connector) { @@ -2842,7 +2852,7 @@ execute_connection (COMMAND *command, int asynchronous, int pipe_in, int pipe_ou /* Just call execute command on both sides. */ case ';': case '\n': /* special case, happens in command substitutions */ - if (ignore_return) + if (ignore_return || invert) { if (command->value.Connection->first) command->value.Connection->first->flags |= CMD_IGNORE_RETURN; @@ -2874,9 +2884,6 @@ execute_connection (COMMAND *command, int asynchronous, int pipe_in, int pipe_ou case '|': was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; - invert = (command->flags & CMD_INVERT_RETURN) != 0; - ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; - SET_LINE_NUMBER (line_number); /* XXX - save value? */ exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close); diff --git a/jobs.c b/jobs.c index b247fd43..b6f0fd58 100644 --- a/jobs.c +++ b/jobs.c @@ -1000,7 +1000,7 @@ save_proc_status (pid_t pid, int status) sigset_t set, oset; BLOCK_CHILD (set, oset); - bgp_add (pid, status); + bgp_add (pid, process_exit_status (status)); UNBLOCK_CHILD (oset); } @@ -3444,9 +3444,11 @@ wait_for_job (int job, int flags, struct procstat *ps) /* Wait for any background job started by this shell to finish, including process substitutions. Very similar to wait_for_background_pids(). Returns the exit status of - the next exiting job, -1 if there are no background jobs. The caller - is responsible for translating -1 into the right return value. RPID, - if non-null, gets the pid of the job's process leader. */ + the next exiting job, -1 if there are no background jobs. If we are in + posix mode, we can take a pid from bgpids since we will delete it. + + The caller is responsible for translating -1 into the right return value. + PS, if non-null, gets the pid and status of the job's process leader. */ int wait_for_any_job (int flags, struct procstat *ps) { @@ -3575,8 +3577,26 @@ return_procsub: if (i == js.j_jobslots && p == NULL) { + /* Ok, the job table is empty. If we're in posix mode, we can look + in the bgpids table because we will remove the pid we find and + this won't change existing semantics. Otherwise, we return + failure as before. */ + struct pidstat *t; + + r = -1; + if (posixly_correct && (t = bgp_findone ())) + { + pid = t->pid; + r = t->status; + if (ps) + { + ps->pid = pid; + ps->status = r; + } + bgp_delete (pid); + } UNBLOCK_CHILD (oset); - return -1; + return r; } UNBLOCK_CHILD (oset); @@ -3886,7 +3906,12 @@ start_job (int job, int foreground) /* Save the tty settings before we start the job in the foreground. */ if (foreground) { - get_tty_state (); +#if defined (READLINE) + /* Don't fetch the terminal attributes if we're doing this from a key + binding or programmable completion. */ + if (RL_ISSTATE(RL_STATE_COMPLETING|RL_STATE_DISPATCHING|RL_STATE_TERMPREPPED) == 0) +#endif + get_tty_state (); save_stty = shell_tty_info; jobs[job]->flags &= ~J_ASYNC; /* no longer async */ /* Give the terminal to this job. */ diff --git a/lib/readline/doc/readline.3 b/lib/readline/doc/readline.3 index 3dbc8596..b31fa313 100644 --- a/lib/readline/doc/readline.3 +++ b/lib/readline/doc/readline.3 @@ -704,6 +704,9 @@ may change if the locale is changed. If set to \fBOn\fP, readline uses an internal \fImore\fP-like pager to display a screenful of possible completions at a time. .TP +.B prefer\-visible\-bell +See \fBbell\-style\fP. +.TP .B print\-completions\-horizontally (Off) If set to \fBOn\fP, readline will display completions with matches sorted horizontally in alphabetical order, rather than down the screen. diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi index 0449452e..c4ba476d 100644 --- a/lib/readline/doc/rluser.texi +++ b/lib/readline/doc/rluser.texi @@ -787,6 +787,9 @@ If set to @samp{on}, Readline uses an internal @code{more}-like pager to display a screenful of possible completions at a time. This variable is @samp{on} by default. +@item prefer-visible-bell +See @code{bell-style}. + @item print-completions-horizontally If set to @samp{on}, Readline will display completions with matches sorted horizontally in alphabetical order, rather than down the screen. diff --git a/lib/readline/histexpand.c b/lib/readline/histexpand.c index f67acd73..068feccd 100644 --- a/lib/readline/histexpand.c +++ b/lib/readline/histexpand.c @@ -1598,8 +1598,8 @@ get_word: /* Command and process substitution; shell extended globbing patterns */ if (nestdelim == 0 && delimiter == 0 && member (string[i], "<>$!@?+*") && string[i+1] == '(') /*)*/ { - i += 2; - if (string[i] == 0) + i++; /* string[i] == '(' */ /*)*/ + if (string[i+1] == 0) break; /* could just return i here */ delimopen = '('; delimiter = ')'; diff --git a/po/POTFILES.in b/po/POTFILES.in index a900e6c1..4b794f57 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,5 +1,5 @@ # List of source files containing translatable strings. -# Copyright (C) 2004 Free Software Foundation, Inc. +# Copyright (C) 2004-2024 Free Software Foundation, Inc. arrayfunc.c bashhist.c @@ -15,6 +15,7 @@ builtins/complete.def builtins/declare.def builtins/enable.def builtins/evalfile.c +builtins/evalstring.c builtins/exec.def builtins/exit.def builtins/fc.def @@ -23,7 +24,6 @@ builtins/getopt.c builtins/hash.def builtins/help.def builtins/history.def -builtins/inlib.def builtins/jobs.def builtins/kill.def builtins/let.def @@ -39,6 +39,7 @@ builtins/shift.def builtins/shopt.def builtins/source.def builtins/suspend.def +builtins/test.def builtins/type.def builtins/ulimit.def builtins/umask.def @@ -49,11 +50,8 @@ expr.c general.c input.c jobs.c -lib/intl/os2compat.c lib/malloc/malloc.c -lib/malloc/stats.c lib/malloc/table.c -lib/malloc/watch.c lib/sh/fmtulong.c lib/sh/netopen.c locale.c @@ -61,6 +59,7 @@ mailcheck.c make_cmd.c nojobs.c parse.y +pathexp.c pcomplete.c pcomplib.c print_cmd.c @@ -71,11 +70,14 @@ siglist.c subst.c test.c trap.c +unwind_prot.c variables.c version.c #version2.c xmalloc.c +lib/intl/plural.c + # Apparently gettext's defaults cannot handle files that exist outside of the # source directory, like in the build directory #../builtins/builtins.c diff --git a/tests/exec.right b/tests/exec.right index dd191330..e65d8cbf 100644 --- a/tests/exec.right +++ b/tests/exec.right @@ -218,3 +218,31 @@ test sub3 1 done 42 +test invert +reached subshell +reached group +reached async group +reached timed group +reached simple +reached if test +reached if body +reached while test +reached while body +reached until test +reached until body +reached func +reached for +reached arith for +1) a +2) b +3) c +#? reached select +reached case +reached arith +reached cond +reached coproc body +reached pipeline element invert +reached AND-AND body +reached OR-OR body +reached AND-AND group +reached OR-OR group diff --git a/tests/exec16.sub b/tests/exec16.sub new file mode 100644 index 00000000..e9d80304 --- /dev/null +++ b/tests/exec16.sub @@ -0,0 +1,126 @@ +# test ignoring effects of set -e on commands whose return status is being +# inverted + +echo test invert + +! ( set -e; false; echo reached subshell; ) +set +e + +! { set -e; false; echo reached group; } +set +e + +! { set -e ; false ; echo reached async group; } & +set +e + +set -e +exec 3>&2 +exec 2>/dev/null +! time { set -e ; false ; echo reached timed group; } +exec 2>&3 +set +e + +set -e +! false +echo reached simple +set +e + +! if set -e; false ; echo reached if test; true; then + set -e + false + echo reached if body +fi +set +e + +! while set -e ; false; echo reached while test; true; do + set -e + false + echo reached while body + break +done +set +e +! until set -e ; false; echo reached until test; false; do + set -e + false + echo reached until body + break +done +set +e + +func() +{ + set -e; false; echo reached func; +} +! func +set +e + +! for f in 1 2 3; do + set -e + false + echo reached for + break +done +set +e + +! for (( f=0; f < 3; f++ )); do + set -e + false + echo reached arith for + break +done +set +e + +! select f in a b c +do + set -e + false + echo reached select + break +done <<<"a" +set +e + +! case 1 in +1) set -e + false + echo reached case ;; +*) echo bad case match;; +esac +set +e + +set -e +! (( 0 )) +echo reached arith +set +e + +set -e +! [[ -n '' ]] +echo reached cond +set +e + +! coproc C { set -e; false; echo reached coproc body; sleep 0.5; exit 0; } +read -u ${C[0]} +echo $REPLY +set +e + +! echo pipeline | { set -e ; false; echo reached pipeline element invert; } | cat - +echo pipeline | { set -e ; false; echo reached pipeline element non-invert; } | cat - +set +e + +! { true && { set -e ; false; echo reached AND-AND body; }; } +set +e +! { false || { set -e ; false; echo reached OR-OR body; }; } +set +e + +true && ! { set -e ; false ; echo reached AND-AND group; } +set +e +false || ! { set -e ; false ; echo reached OR-OR group; } +set +e + +# precedence here + +! false && { set -e ; false ; echo reached inverted AND-AND group; } +set +e +! true || { set -e ; false ; echo reached inverted OR-OR group; } +set +e + +# NOTREACHED +echo done diff --git a/tests/execscript b/tests/execscript index 1e2117e6..6dad13c9 100644 --- a/tests/execscript +++ b/tests/execscript @@ -201,3 +201,6 @@ ${THIS_SH} ./exec14.sub # problems with fork optimization in bash-5.2 ${THIS_SH} ./exec15.sub + +# problems with set -e and inverting commands' return status +${THIS_SH} ./exec16.sub diff --git a/tests/histexp.right b/tests/histexp.right index d9b8fea8..cc8cb04d 100644 --- a/tests/histexp.right +++ b/tests/histexp.right @@ -135,6 +135,9 @@ one two three four echo two ; echo four one two three four echo four ; echo two +3 +echo $((1+2)) +3 ! ! ! diff --git a/tests/histexp.tests b/tests/histexp.tests index 91a36f23..18a02816 100644 --- a/tests/histexp.tests +++ b/tests/histexp.tests @@ -149,6 +149,10 @@ echo !:2:p ; echo !$ echo one two three four echo !$ ; echo !:2:p +# problem through bash-5.2 with history word tokenization +echo $((1+2)) +echo !!:1 + ${THIS_SH} ./histexp1.sub ${THIS_SH} ./histexp2.sub ${THIS_SH} ./histexp3.sub diff --git a/variables.c b/variables.c index 6d717757..3c9e2907 100644 --- a/variables.c +++ b/variables.c @@ -171,7 +171,7 @@ int array_needs_making = 1; int shell_level = 0; /* If non-zero, each element of BASH_SOURCE contains a full pathnames */ -int bash_source_fullpath = 0; +int bash_source_fullpath = BASH_SOURCE_FULLPATH_DEFAULT; /* An array which is passed to commands as their environment. It is manufactured from the union of the initial environment and the