- revert changes to COMMAND and SIMPLE_COM from 7/16
From a report by Jessica Clarke <jrtc27@jrtc27.com>
+parse.y
+ - pipeline: in BAR_AND form of the pipeline production, use a
+ REDIRECT ** to manipulate the redirection list instead of trying
+ to cast a COMAND * to a SIMPLE_COM *
+ From a report by Jessica Clarke <jrtc27@jrtc27.com>
+
expr.c
- expassign,expshift: avoid C23 undefined behavior when performing
left and right arithmetic shifts
From https://savannah.gnu.org/patch/?10532
bkallus <benjamin.p.kallus.gr@dartmouth.edu>
+
+ 7/28
+ ----
+subst.c
+ - expand_word_internal: if we see a `$' and call param_expand, pass a
+ local copy of expanded_something and OR it into expanded_something,
+ so this function can set it to 0 if we get a trailing $ or a $!
+ when there are no background pids.
+ From ahmedwaldsaaid@gmail.com via https://savannah.gnu.org/bugs/index.php?67358
+ Fix suggested by Oğuz <oguzismailuysal@gmail.com>
+
+ 8/1
+ ---
+lib/sh/getcwd.c
+ - getcwd: set errno to 0 before calling readdir to avoid a stale
+ value if readdir() returns NULL and distinguish errors from the
+ end of the directory. If readdir() returns NULL without changing
+ errno, set it to ENOENT.
+ From a report by Richard Weinberger <richard@sigma-star.at>
+
+aclocal.m4
+ - BASH_CHECK_LIB_TERMCAP: add libtinfow to the library list to search
+ From a report by Дилян Палаузов <dilyan.palauzov@aegee.org>
+
+execute_cmd.c
+ - execute_subshell_builtin_or_function: fix to propagate exit statuses
+ of builtins run in subshells back to the calling shell
+ From https://savannah.gnu.org/support/?109840
[AC_CHECK_FUNC(tgetent, bash_cv_termcap_lib=libc,
[AC_CHECK_LIB(termcap, tgetent, bash_cv_termcap_lib=libtermcap,
[AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
+ [AC_CHECK_LIB(tinfow, tgetent, bash_cv_termcap_lib=libtinfow,
[AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
- [AC_CHECK_LIB(ncursesw, tgetent, bash_cv_termcap_lib=libncursesw,
- [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
- bash_cv_termcap_lib=gnutermcap)])])])])])])
+ [AC_CHECK_LIB(ncursesw, tgetent, bash_cv_termcap_lib=libncursesw,
+ [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
+ bash_cv_termcap_lib=gnutermcap)])])])])])])])
if test "X$_bash_needmsg" = "Xyes"; then
AC_MSG_CHECKING(which library has the termcap functions)
fi
elif test $bash_cv_termcap_lib = libtinfo; then
TERMCAP_LIB=-ltinfo
TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libtinfow; then
+TERMCAP_LIB=-ltinfow
+TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libncursesw; then
TERMCAP_LIB=-lncursesw
TERMCAP_DEP=
Change the shell working directory.
Change the current directory to DIR. The default DIR is the value of the
-HOME shell variable. If DIR is "-", it is converted to $OLDPWD.
+HOME shell variable. If DIR is "-", it is converted to $OLDPWD. If DIR is
+the empty string, cd returns an error.
The variable CDPATH defines the search path for the directory containing
DIR. Alternative directory names in CDPATH are separated by a colon (:).
-A null directory name is the same as the current directory. If DIR begins
-with a slash (/), then CDPATH is not used.
+A null directory name in CDPATH is the same as the current directory.
+If DIR begins with a slash (/), then CDPATH is not used.
If the directory is not found, and the shell option `cdable_vars' is set,
the word is assumed to be a variable name. If that variable has a value,
if test "x$ac_cv_lib_tinfo_tgetent" = xyes
then :
bash_cv_termcap_lib=libtinfo
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -ltinfow" >&5
+printf %s "checking for tgetent in -ltinfow... " >&6; }
+if test ${ac_cv_lib_tinfow_tgetent+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltinfow $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tgetent (void);
+int
+main (void)
+{
+return tgetent ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_tinfow_tgetent=yes
+else case e in #(
+ e) ac_cv_lib_tinfow_tgetent=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tinfow_tgetent" >&5
+printf "%s\n" "$ac_cv_lib_tinfow_tgetent" >&6; }
+if test "x$ac_cv_lib_tinfow_tgetent" = xyes
+then :
+ bash_cv_termcap_lib=libtinfow
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lcurses" >&5
printf %s "checking for tgetent in -lcurses... " >&6; }
fi
;;
esac
+fi
+ ;;
+esac
fi
if test "X$_bash_needmsg" = "Xyes"; then
elif test $bash_cv_termcap_lib = libtinfo; then
TERMCAP_LIB=-ltinfo
TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libtinfow; then
+TERMCAP_LIB=-ltinfow
+TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libncursesw; then
TERMCAP_LIB=-lncursesw
TERMCAP_DEP=
LIBS=$save_LIBS
test $gl_pthread_api = yes && break
done
- echo "$as_me:9360: gl_pthread_api=$gl_pthread_api" >&5
- echo "$as_me:9361: LIBPTHREAD=$LIBPTHREAD" >&5
+ echo "$as_me:9413: gl_pthread_api=$gl_pthread_api" >&5
+ echo "$as_me:9414: LIBPTHREAD=$LIBPTHREAD" >&5
gl_pthread_in_glibc=no
# On Linux with glibc >= 2.34, libc contains the fully functional
;;
esac
- echo "$as_me:9387: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
+ echo "$as_me:9440: 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.)
fi
fi
- echo "$as_me:9565: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
+ echo "$as_me:9618: 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; }
LIBS=$save_LIBS
test $gl_pthread_api = yes && break
done
- echo "$as_me:9812: gl_pthread_api=$gl_pthread_api" >&5
- echo "$as_me:9813: LIBPTHREAD=$LIBPTHREAD" >&5
+ echo "$as_me:9865: gl_pthread_api=$gl_pthread_api" >&5
+ echo "$as_me:9866: LIBPTHREAD=$LIBPTHREAD" >&5
gl_pthread_in_glibc=no
# On Linux with glibc >= 2.34, libc contains the fully functional
;;
esac
- echo "$as_me:9839: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
+ echo "$as_me:9892: 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.)
fi
fi
- echo "$as_me:10017: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
+ echo "$as_me:10070: 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; }
if test "x$ac_cv_lib_tinfo_tgetent" = xyes
then :
bash_cv_termcap_lib=libtinfo
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -ltinfow" >&5
+printf %s "checking for tgetent in -ltinfow... " >&6; }
+if test ${ac_cv_lib_tinfow_tgetent+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltinfow $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tgetent (void);
+int
+main (void)
+{
+return tgetent ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_tinfow_tgetent=yes
+else case e in #(
+ e) ac_cv_lib_tinfow_tgetent=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tinfow_tgetent" >&5
+printf "%s\n" "$ac_cv_lib_tinfow_tgetent" >&6; }
+if test "x$ac_cv_lib_tinfow_tgetent" = xyes
+then :
+ bash_cv_termcap_lib=libtinfow
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lcurses" >&5
printf %s "checking for tgetent in -lcurses... " >&6; }
fi
;;
esac
+fi
+ ;;
+esac
fi
if test "X$_bash_needmsg" = "Xyes"; then
elif test $bash_cv_termcap_lib = libtinfo; then
TERMCAP_LIB=-ltinfo
TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libtinfow; then
+TERMCAP_LIB=-ltinfow
+TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libncursesw; then
TERMCAP_LIB=-lncursesw
TERMCAP_DEP=
.\" Case Western Reserve University
.\" chet.ramey@case.edu
.\"
-.\" Last Change: Tue Jul 15 10:19:08 EDT 2025
+.\" Last Change: Wed Jul 30 14:47:58 EDT 2025
.\"
.\" For bash_builtins, strip all but "SHELL BUILTIN COMMANDS" section
.\" For rbash, strip all but "RESTRICTED SHELL" section
.ds zY \" empty
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
-.TH BASH 1 "2025 July 15" "GNU Bash 5.3"
+.TH BASH 1 "2025 July 30" "GNU Bash 5.3"
.\"
.ie \n(.g \{\
.ds ' \(aq
.SM
.B HOME
shell variable is used as \fIdir\fP.
+If \fIdir\fP is the empty string, \fBcd\fP treats it as an error.
The variable
.SM
.B CDPATH
Change the current working directory to @var{directory}.
If @var{directory} is not supplied, the value of the @env{HOME}
shell variable is used as @var{directory}.
+If @var{directory} is the empty string, @code{cd} treats it as an error.
If the shell variable
@env{CDPATH} exists,
and @var{directory} does not begin with a slash,
Copyright (C) 1988-2025 Free Software Foundation, Inc.
@end ignore
-@set LASTCHANGE Sun May 18 13:42:18 EDT 2025
+@set LASTCHANGE Wed Jul 30 14:47:36 EDT 2025
@set EDITION 5.3
@set VERSION 5.3
-@set UPDATED 18 May 2025
-@set UPDATED-MONTH May 2025
+@set UPDATED 30 July 2025
+@set UPDATED-MONTH July 2025
if (result == EXITPROG || result == EXITBLTIN)
subshell_exit (last_command_exit_value);
-#if 0 /* TAG:bash-5.4 https://savannah.gnu.org/support/?109840 6/5/2025 */
else if (result == ERREXIT)
subshell_exit (last_command_exit_value ? last_command_exit_value : EXECUTION_FAILURE);
-#endif
else if (result)
subshell_exit (EXECUTION_FAILURE);
else if (funcvalue)
dirstream = opendir (dotp);
if (dirstream == NULL)
goto lose;
- while ((d = readdir (dirstream)) != NULL)
+ for (;;)
{
+ errno = 0;
+ d = readdir (dirstream);
+
+ if (d == NULL)
+ {
+ if (errno == 0)
+ errno = ENOENT;
+ break;
+ }
+
if (d->d_name[0] == '.' &&
(d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
memcpy (&name[dotlist + dotsize - dotp + 1],
d->d_name, namlen + 1);
if (lstat (name, &st) < 0)
- {
-#if 0
- int save = errno;
- (void) closedir (dirstream);
- errno = save;
- goto lose;
-#else
- saved_errno = errno;
-#endif
- }
+ saved_errno = errno;
if (st.st_dev == thisdev && st.st_ino == thisino)
break;
}
}
if (d == NULL)
{
-#if 0
- int save = errno;
-#else
int save = errno ? errno : saved_errno;
-#endif
(void) closedir (dirstream);
errno = save;
goto lose;
}
case '$':
- if (expanded_something)
- *expanded_something = 1;
local_expanded = 1;
temp_has_dollar_at = 0;
if (word->flags & W_COMPLETE)
pflags |= PF_COMPLETE;
- tword = param_expand (string, &sindex, quoted, expanded_something,
+ tword = param_expand (string, &sindex, quoted, &local_expanded,
&temp_has_dollar_at, "ed_dollar_at,
&had_quoted_null, pflags);
has_dollar_at += temp_has_dollar_at;
split_on_spaces += (tword->flags & W_SPLITSPACE);
+ if (expanded_something)
+ *expanded_something |= local_expanded;
+
if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
{
free (string);
if (expanded_something)
*expanded_something = 1;
- local_expanded = 1;
if (word->flags & W_NOCOMSUB)
/* sindex + 1 because string[sindex] == '`' */
*contains_dollar_at = 1;
if (expanded_something)
*expanded_something = 1;
- local_expanded = 1;
}
}
else