From 0b1533fe53ac52c20f64423f1311b600d88d87ce Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Wed, 3 Dec 2025 01:33:21 -0700 Subject: [PATCH 01/37] configure: change package name to scallop and define full version So the header subdir used for the `install-headers` target is scallop otherwise it would overlap with the regular bash package when plugin support is enabled (which installs the headers). Also, this changes $PACKAGE_VERSION to the X.Y.Z.DATE format used by scallop. --- configure | 64 +++++++++++++++++++++++++--------------------------- configure.ac | 6 +++-- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/configure b/configure index a28a3fcf..655d894b 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #! /bin/sh # From configure.ac for Bash 5.3, version 5.080. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for bash 5.3-release. +# Generated by GNU Autoconf 2.72 for scallop 5.3.12.20260606. # # Report bugs to . # @@ -603,10 +603,10 @@ MFLAGS= MAKEFLAGS= # Identity of this package. -PACKAGE_NAME='bash' -PACKAGE_TARNAME='bash' -PACKAGE_VERSION='5.3-release' -PACKAGE_STRING='bash 5.3-release' +PACKAGE_NAME='scallop' +PACKAGE_TARNAME='scallop' +PACKAGE_VERSION='5.3.12.20260606' +PACKAGE_STRING='scallop 5.3.12.20260606' PACKAGE_BUGREPORT='bug-bash@gnu.org' PACKAGE_URL='' @@ -1468,7 +1468,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures bash 5.3-release to adapt to many kinds of systems. +'configure' configures scallop 5.3.12.20260606 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1517,7 +1517,7 @@ Fine tuning of the installation directories: --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/bash] + --docdir=DIR documentation root [DATAROOTDIR/doc/scallop] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] @@ -1534,7 +1534,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bash 5.3-release:";; + short | recursive ) echo "Configuration of scallop 5.3.12.20260606:";; esac cat <<\_ACEOF @@ -1742,7 +1742,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bash configure 5.3-release +scallop configure 5.3.12.20260606 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. @@ -2420,7 +2420,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bash $as_me 5.3-release, which was +It was created by scallop $as_me 5.3.12.20260606, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -3952,7 +3952,7 @@ if test -z "$CFLAGS"; then fi echo "" -echo "Beginning configuration for bash-$BASHVERS-$RELSTATUS for ${host_cpu}-${host_vendor}-${host_os}" +echo "Beginning configuration for $PACKAGE_NAME-$PACKAGE_VERSION for ${host_cpu}-${host_vendor}-${host_os}" echo "" @@ -5175,18 +5175,18 @@ then : fi if test "$enable_largefile,$enable_year2038" != no,no then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable large file support" >&5 -printf %s "checking for $CC option to enable large file support... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CPPFLAGS option for large files" >&5 +printf %s "checking for $CPPFLAGS option for large files... " >&6; } if test ${ac_cv_sys_largefile_opts+y} then : printf %s "(cached) " >&6 else case e in #( - e) ac_save_CC="$CC" + e) ac_save_CPPFLAGS=$CPPFLAGS ac_opt_found=no - for ac_opt in "none needed" "-D_FILE_OFFSET_BITS=64" "-D_LARGE_FILES=1" "-n32"; do + for ac_opt in "none needed" "-D_FILE_OFFSET_BITS=64" "-D_LARGE_FILES=1"; do if test x"$ac_opt" != x"none needed" then : - CC="$ac_save_CC $ac_opt" + CPPFLAGS="$ac_save_CPPFLAGS $ac_opt" fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -5215,12 +5215,12 @@ then : if test x"$ac_opt" = x"none needed" then : # GNU/Linux s390x and alpha need _FILE_OFFSET_BITS=64 for wide ino_t. - CC="$CC -DFTYPE=ino_t" + CPPFLAGS="$CPPFLAGS -DFTYPE=ino_t" if ac_fn_c_try_compile "$LINENO" then : else case e in #( - e) CC="$CC -D_FILE_OFFSET_BITS=64" + e) CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" if ac_fn_c_try_compile "$LINENO" then : ac_opt='-D_FILE_OFFSET_BITS=64' @@ -5236,7 +5236,7 @@ fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext test $ac_opt_found = no || break done - CC="$ac_save_CC" + CPPFLAGS=$ac_save_CPPFLAGS test $ac_opt_found = yes || ac_cv_sys_largefile_opts="support not detected" ;; esac @@ -5260,16 +5260,14 @@ printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h printf "%s\n" "#define _LARGE_FILES 1" >>confdefs.h ;; #( - "-n32") : - CC="$CC -n32" ;; #( *) : as_fn_error $? "internal error: bad value for \$ac_cv_sys_largefile_opts" "$LINENO" 5 ;; esac if test "$enable_year2038" != no then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option for timestamps after 2038" >&5 -printf %s "checking for $CC option for timestamps after 2038... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CPPFLAGS option for timestamps after 2038" >&5 +printf %s "checking for $CPPFLAGS option for timestamps after 2038... " >&6; } if test ${ac_cv_sys_year2038_opts+y} then : printf %s "(cached) " >&6 @@ -9357,8 +9355,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ 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:9358: gl_pthread_api=$gl_pthread_api" >&5 + echo "$as_me:9359: LIBPTHREAD=$LIBPTHREAD" >&5 gl_pthread_in_glibc=no # On Linux with glibc >= 2.34, libc contains the fully functional @@ -9384,7 +9382,7 @@ rm -rf conftest* ;; esac - echo "$as_me:9387: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 + echo "$as_me:9385: 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.) @@ -9562,7 +9560,7 @@ fi fi fi - echo "$as_me:9565: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 + echo "$as_me:9563: 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; } @@ -9809,8 +9807,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ 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:9810: gl_pthread_api=$gl_pthread_api" >&5 + echo "$as_me:9811: LIBPTHREAD=$LIBPTHREAD" >&5 gl_pthread_in_glibc=no # On Linux with glibc >= 2.34, libc contains the fully functional @@ -9836,7 +9834,7 @@ rm -rf conftest* ;; esac - echo "$as_me:9839: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 + echo "$as_me:9837: 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.) @@ -10014,7 +10012,7 @@ fi fi fi - echo "$as_me:10017: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 + echo "$as_me:10015: 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; } @@ -23814,7 +23812,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by bash $as_me 5.3-release, which was +This file was extended by scallop $as_me 5.3.12.20260606, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -23882,7 +23880,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -bash config.status 5.3-release +scallop config.status 5.3.12.20260606 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 5a76267e..8d2e85ba 100644 --- a/configure.ac +++ b/configure.ac @@ -24,9 +24,11 @@ dnl Process this file with autoconf to produce a configure script. AC_REVISION([for Bash 5.3, version 5.080])dnl define(bashvers, 5.3) +define(patchlevel, 12) +define(patchdate, 20260606) define(relstatus, release) -AC_INIT([bash], bashvers-relstatus, [bug-bash@gnu.org]) +AC_INIT([scallop], bashvers.patchlevel.patchdate, [bug-bash@gnu.org]) dnl make sure we are using a recent autoconf version AC_PREREQ(2.69) @@ -432,7 +434,7 @@ if test -z "$CFLAGS"; then fi echo "" -echo "Beginning configuration for bash-$BASHVERS-$RELSTATUS for ${host_cpu}-${host_vendor}-${host_os}" +echo "Beginning configuration for $PACKAGE_NAME-$PACKAGE_VERSION for ${host_cpu}-${host_vendor}-${host_os}" echo "" dnl compilation checks From d3bbdf21f9cd6cca76151753dcd4f6e4b18eccf6 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Thu, 30 Dec 2021 01:51:49 -0700 Subject: [PATCH 02/37] configure: force -fPIC for external shared library creation --- configure | 20 ++++++++++++-------- configure.ac | 4 ++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 655d894b..fd9a928d 100755 --- a/configure +++ b/configure @@ -5411,6 +5411,10 @@ if test "$opt_static_link" = yes; then fi fi +# TODO: trigger this via configure option +# enable position-independent code for library creation +CFLAGS="$CFLAGS -fPIC" + # set the appropriate make variables for building the "build tools" # modify defaults based on whether or not we are cross compiling, since the # options for the target host may not be appropriate for the build host @@ -9355,8 +9359,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ LIBS=$save_LIBS test $gl_pthread_api = yes && break done - echo "$as_me:9358: gl_pthread_api=$gl_pthread_api" >&5 - echo "$as_me:9359: LIBPTHREAD=$LIBPTHREAD" >&5 + echo "$as_me:9362: gl_pthread_api=$gl_pthread_api" >&5 + echo "$as_me:9363: LIBPTHREAD=$LIBPTHREAD" >&5 gl_pthread_in_glibc=no # On Linux with glibc >= 2.34, libc contains the fully functional @@ -9382,7 +9386,7 @@ rm -rf conftest* ;; esac - echo "$as_me:9385: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 + echo "$as_me:9389: 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.) @@ -9560,7 +9564,7 @@ fi fi fi - echo "$as_me:9563: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 + echo "$as_me:9567: 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; } @@ -9807,8 +9811,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ LIBS=$save_LIBS test $gl_pthread_api = yes && break done - echo "$as_me:9810: gl_pthread_api=$gl_pthread_api" >&5 - echo "$as_me:9811: LIBPTHREAD=$LIBPTHREAD" >&5 + echo "$as_me:9814: gl_pthread_api=$gl_pthread_api" >&5 + echo "$as_me:9815: LIBPTHREAD=$LIBPTHREAD" >&5 gl_pthread_in_glibc=no # On Linux with glibc >= 2.34, libc contains the fully functional @@ -9834,7 +9838,7 @@ rm -rf conftest* ;; esac - echo "$as_me:9837: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 + echo "$as_me:9841: 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.) @@ -10012,7 +10016,7 @@ fi fi fi - echo "$as_me:10015: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 + echo "$as_me:10019: 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 8d2e85ba..010d62ba 100644 --- a/configure.ac +++ b/configure.ac @@ -535,6 +535,10 @@ if test "$opt_static_link" = yes; then fi fi +# TODO: trigger this via configure option +# enable position-independent code for library creation +CFLAGS="$CFLAGS -fPIC" + # set the appropriate make variables for building the "build tools" # modify defaults based on whether or not we are cross compiling, since the # options for the target host may not be appropriate for the build host From d7dd417892599d00e329e9ff7a837ae950b6add1 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Mon, 3 Jan 2022 04:10:32 -0700 Subject: [PATCH 03/37] configure: add flag for library build support And rename main() to bash_main() in order to use it externally when library support is enabled. --- config.h.in | 3 +++ configure | 28 ++++++++++++++++++++-------- configure.ac | 4 ++++ shell.c | 8 ++++++++ shell.h | 11 +++++++++++ 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/config.h.in b/config.h.in index 1367eaaa..4687e60a 100644 --- a/config.h.in +++ b/config.h.in @@ -162,6 +162,9 @@ memory contents on malloc() and free(). */ #undef MEMSCRAMBLE +/* Define BUILD_LIBRARY for library build support. */ +#undef BUILD_LIBRARY + /* Define for case-modifying variable attributes; variables modified on assignment */ #undef CASEMOD_ATTRS diff --git a/configure b/configure index fd9a928d..82fd7eb3 100755 --- a/configure +++ b/configure @@ -894,6 +894,7 @@ enable_xpg_echo_default enable_mem_scramble enable_profiling enable_static_link +enable_library enable_largefile enable_nls enable_threads @@ -1620,6 +1621,7 @@ Optional Features: --enable-mem-scramble scramble memory on calls to malloc and free --enable-profiling allow profiling with gprof --enable-static-link link bash statically, for use as a root shell + --enable-library build bash as a library --disable-largefile omit support for large files --disable-nls do not use Native Language Support --enable-threads={isoc|posix|isoc+posix|windows} @@ -3750,6 +3752,12 @@ then : enableval=$enable_static_link; opt_static_link=$enableval fi +# Check whether --enable-library was given. +if test ${enable_library+y} +then : + enableval=$enable_library; opt_library=$enableval +fi + @@ -3904,6 +3912,10 @@ fi if test $opt_memscramble = yes; then printf "%s\n" "#define MEMSCRAMBLE 1" >>confdefs.h +fi +if test $opt_library = yes; then +printf "%s\n" "#define BUILD_LIBRARY 1" >>confdefs.h + fi if test "$opt_minimal_config" = yes; then @@ -9359,8 +9371,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ LIBS=$save_LIBS test $gl_pthread_api = yes && break done - echo "$as_me:9362: gl_pthread_api=$gl_pthread_api" >&5 - echo "$as_me:9363: LIBPTHREAD=$LIBPTHREAD" >&5 + echo "$as_me:9374: gl_pthread_api=$gl_pthread_api" >&5 + echo "$as_me:9375: LIBPTHREAD=$LIBPTHREAD" >&5 gl_pthread_in_glibc=no # On Linux with glibc >= 2.34, libc contains the fully functional @@ -9386,7 +9398,7 @@ rm -rf conftest* ;; esac - echo "$as_me:9389: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 + echo "$as_me:9401: 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.) @@ -9564,7 +9576,7 @@ fi fi fi - echo "$as_me:9567: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 + echo "$as_me:9579: 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; } @@ -9811,8 +9823,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ LIBS=$save_LIBS test $gl_pthread_api = yes && break done - echo "$as_me:9814: gl_pthread_api=$gl_pthread_api" >&5 - echo "$as_me:9815: LIBPTHREAD=$LIBPTHREAD" >&5 + echo "$as_me:9826: gl_pthread_api=$gl_pthread_api" >&5 + echo "$as_me:9827: LIBPTHREAD=$LIBPTHREAD" >&5 gl_pthread_in_glibc=no # On Linux with glibc >= 2.34, libc contains the fully functional @@ -9838,7 +9850,7 @@ rm -rf conftest* ;; esac - echo "$as_me:9841: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 + echo "$as_me:9853: 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.) @@ -10016,7 +10028,7 @@ fi fi fi - echo "$as_me:10019: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 + echo "$as_me:10031: 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 010d62ba..0464b2a9 100644 --- a/configure.ac +++ b/configure.ac @@ -262,6 +262,7 @@ dnl options that alter how bash is compiled and linked AC_ARG_ENABLE(mem-scramble, AS_HELP_STRING([--enable-mem-scramble], [scramble memory on calls to malloc and free]), opt_memscramble=$enableval) AC_ARG_ENABLE(profiling, AS_HELP_STRING([--enable-profiling], [allow profiling with gprof]), opt_profiling=$enableval) AC_ARG_ENABLE(static-link, AS_HELP_STRING([--enable-static-link], [link bash statically, for use as a root shell]), opt_static_link=$enableval) +AC_ARG_ENABLE(library, AS_HELP_STRING([--enable-library], [build bash as a library]), opt_library=$enableval) dnl So-called `precious' variables AC_ARG_VAR([CC_FOR_BUILD], [C compiler used when compiling binaries used only at build time]) @@ -385,6 +386,9 @@ fi if test $opt_memscramble = yes; then AC_DEFINE(MEMSCRAMBLE) fi +if test $opt_library = yes; then +AC_DEFINE(BUILD_LIBRARY) +fi if test "$opt_minimal_config" = yes; then TESTSCRIPT=run-minimal diff --git a/shell.c b/shell.c index e59029cc..34b64894 100644 --- a/shell.c +++ b/shell.c @@ -368,10 +368,18 @@ _cygwin32_check_tmp (void) #if defined (NO_MAIN_ENV_ARG) /* systems without third argument to main() */ int +#if defined (BUILD_LIBRARY) +bash_main (int argc, char **argv) +#else main (int argc, char **argv) +#endif /* BUILD_LIBRARY */ #else /* !NO_MAIN_ENV_ARG */ int +#if defined (BUILD_LIBRARY) +bash_main (int argc, char **argv, char **env) +#else main (int argc, char **argv, char **env) +#endif /* BUILD_LIBRARY */ #endif /* !NO_MAIN_ENV_ARG */ { register int i; diff --git a/shell.h b/shell.h index 74d6fd97..437a03e4 100644 --- a/shell.h +++ b/shell.h @@ -18,6 +18,9 @@ along with Bash. If not, see . */ +#if !defined (_SHELL_H_) +#define _SHELL_H_ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -250,3 +253,11 @@ extern void uw_restore_parser_state (void *); extern sh_input_line_state_t *save_input_line_state (sh_input_line_state_t *); extern void restore_input_line_state (sh_input_line_state_t *); + +#if defined (NO_MAIN_ENV_ARG) +extern int bash_main (int argc, char **argv); +#else /* !NO_MAIN_ENV_ARG */ +extern int bash_main (int argc, char **argv, char **env); +#endif /* !NO_MAIN_ENV_ARG */ + +#endif /* _SHELL_H_ */ From c8931b106afabe4570341fe973dec4826011bc5c Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Fri, 16 Sep 2022 14:03:47 -0600 Subject: [PATCH 04/37] configure: don't configure doc, examples, po, and support dirs --- configure | 11 +---------- configure.ac | 7 +------ 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/configure b/configure index 82fd7eb3..77145a23 100755 --- a/configure +++ b/configure @@ -23301,7 +23301,7 @@ fi #AC_SUBST(ALLOCA_SOURCE) #AC_SUBST(ALLOCA_OBJECT) -ac_config_files="$ac_config_files Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile lib/intl/Makefile lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile lib/tilde/Makefile doc/Makefile support/Makefile po/Makefile.in examples/loadables/Makefile examples/loadables/Makefile.inc examples/loadables/Makefile.sample examples/loadables/perl/Makefile support/bash.pc support/bashbug.sh" +ac_config_files="$ac_config_files Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile lib/intl/Makefile lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile lib/tilde/Makefile" ac_config_commands="$ac_config_commands stamp-h" @@ -24041,15 +24041,6 @@ do "lib/sh/Makefile") CONFIG_FILES="$CONFIG_FILES lib/sh/Makefile" ;; "lib/termcap/Makefile") CONFIG_FILES="$CONFIG_FILES lib/termcap/Makefile" ;; "lib/tilde/Makefile") CONFIG_FILES="$CONFIG_FILES lib/tilde/Makefile" ;; - "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; - "support/Makefile") CONFIG_FILES="$CONFIG_FILES support/Makefile" ;; - "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; - "examples/loadables/Makefile") CONFIG_FILES="$CONFIG_FILES examples/loadables/Makefile" ;; - "examples/loadables/Makefile.inc") CONFIG_FILES="$CONFIG_FILES examples/loadables/Makefile.inc" ;; - "examples/loadables/Makefile.sample") CONFIG_FILES="$CONFIG_FILES examples/loadables/Makefile.sample" ;; - "examples/loadables/perl/Makefile") CONFIG_FILES="$CONFIG_FILES examples/loadables/perl/Makefile" ;; - "support/bash.pc") CONFIG_FILES="$CONFIG_FILES support/bash.pc" ;; - "support/bashbug.sh") CONFIG_FILES="$CONFIG_FILES support/bashbug.sh" ;; "stamp-h") CONFIG_COMMANDS="$CONFIG_COMMANDS stamp-h" ;; *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;; diff --git a/configure.ac b/configure.ac index 0464b2a9..173af80c 100644 --- a/configure.ac +++ b/configure.ac @@ -1375,12 +1375,7 @@ AC_SUBST(LOCAL_DEFS) AC_CONFIG_FILES([Makefile builtins/Makefile lib/readline/Makefile \ lib/glob/Makefile lib/intl/Makefile \ lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile \ - lib/tilde/Makefile doc/Makefile support/Makefile \ - po/Makefile.in examples/loadables/Makefile \ - examples/loadables/Makefile.inc \ - examples/loadables/Makefile.sample \ - examples/loadables/perl/Makefile \ - support/bash.pc support/bashbug.sh]) + lib/tilde/Makefile]) dnl Makefile uses this timestamp file to record whether config.h is up to date. AC_CONFIG_COMMANDS([stamp-h], [echo timestamp > stamp-h]) From f46618ef4b3ab53d3264672727f7744036eaf26c Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Thu, 30 Dec 2021 01:23:29 -0700 Subject: [PATCH 05/37] Makefile.in: add static and shared library targets --- Makefile.in | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index c4a882f7..b81592ac 100644 --- a/Makefile.in +++ b/Makefile.in @@ -118,6 +118,10 @@ Version = @BASHVERS@ PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p` RELSTATUS = @RELSTATUS@ +# scallop targets +StaticLibrary = libscallop.a +SharedLibrary = libscallop.so + Machine = @host_cpu@ OS = @host_os@ VENDOR = @host_vendor@ @@ -636,6 +640,22 @@ $(Program): $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP) .build ls -l $(Program) -$(SIZE) $(Program) +$(StaticLibrary): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP) + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(OBJECTS) + -for lib in $(BUILTINS_DEP) $(LIBDEP); do \ + for obj in $$($(AR) t $$lib); do \ + $(AR) q $@ $$(dirname $$lib)/$$obj ;\ + done ;\ + done + $(RANLIB) $@ + +$(SharedLibrary): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP) + $(RM) $@ + $(eval SCALLOP_LIBRARY = $(SharedLibrary).$(PACKAGE_VERSION)) + $(CC) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) $(LDFLAGS) \ + -Wl,-soname,${SCALLOP_LIBRARY} -shared -o ${SCALLOP_LIBRARY} $(OBJECTS) $(LIBS) + .build: $(SOURCES) config.h Makefile $(DEFDIR)/builtext.h version.h $(VERSPROG) @echo @echo " ***********************************************************" @@ -925,6 +945,11 @@ install: .made installdirs -( cd $(PO_DIR) ; $(MAKE) $(BASH_MAKEFLAGS) DESTDIR=$(DESTDIR) $@ ) -( cd $(LOADABLES_DIR) && $(MAKE) $(BASH_MAKEFLAGS) DESTDIR=$(DESTDIR) $@ ) +install-library: + @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL) $(INSTALLMODE) $(SharedLibrary).* $(DESTDIR)$(libdir) + cd $(DESTDIR)$(libdir) && ln -sf $(SharedLibrary).* $(SharedLibrary) + install-strip: $(MAKE) $(BASH_MAKEFLAGS) INSTALL_PROGRAM='$(INSTALL_STRIP_PROGRAM)' \ prefix=${prefix} exec_prefix=${exec_prefix} \ @@ -1003,7 +1028,7 @@ LIB_SUBDIRS = ${RL_LIBDIR} ${HIST_LIBDIR} ${TERM_LIBDIR} ${GLOB_LIBDIR} \ ${INTL_LIBDIR} ${TILDE_LIBDIR} ${ALLOC_LIBDIR} ${SH_LIBDIR} basic-clean: - $(RM) $(OBJECTS) $(Program) bashbug + $(RM) $(OBJECTS) $(Program) $(StaticLibrary) $(SharedLibrary)* bashbug $(RM) .build .made version.h clean: basic-clean From 413f66fd5467df2ece52fd9a11e457016004db1b Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sat, 29 Nov 2025 14:24:54 -0700 Subject: [PATCH 06/37] Makefile.in: avoid running autoconf when building library Previously when building libraries for scallop, the configure target would trigger autoconf to be run unnecessarily as the bundled configure script should up-to-date. --- Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index b81592ac..5f874ed8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -882,8 +882,8 @@ $(SUPPORT_DIR)/bashbug.sh: $(SUPPORT_DIR)/bashbug.sh.in CONFIG_FILES=$(SUPPORT_DIR)/bashbug.sh CONFIG_HEADERS= $(SHELL) ./config.status # comment out for distribution -$(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/aclocal.m4 $(srcdir)/config.h.in - cd $(srcdir) && autoconf +#$(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/aclocal.m4 $(srcdir)/config.h.in +# cd $(srcdir) && autoconf # for chet reconfig: force From 30cf480e3656be209854341984ddbf3dda608d26 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sat, 29 Nov 2025 14:59:31 -0700 Subject: [PATCH 07/37] Makefile.in: use $(shell ...) instead of backticks to determine PatchLevel This makes deferred vs immediate expansion work as expected for other variables using $(PatchLevel). --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 5f874ed8..8acb0331 100644 --- a/Makefile.in +++ b/Makefile.in @@ -115,7 +115,7 @@ VERSOBJ = bashversion.$(OBJEXT) Program = bash$(EXEEXT) Version = @BASHVERS@ -PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p` +PatchLevel = $(shell $(BUILD_DIR)/$(VERSPROG) -p) RELSTATUS = @RELSTATUS@ # scallop targets From 09c6a91d48265e0e748793440be0c459a20434b8 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Wed, 3 Dec 2025 01:26:40 -0700 Subject: [PATCH 08/37] Makefile.in: install additional headers needed by scallop bindings --- Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index 8acb0331..90e7d3f8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -508,11 +508,11 @@ INSTALLED_HEADERS = shell.h bashjmp.h command.h syntax.h general.h error.h \ bashtypes.h xmalloc.h config-top.h config-bot.h \ bashintl.h bashansi.h bashjmp.h alias.h hashlib.h \ conftypes.h unwind_prot.h jobs.h siglist.h \ - execute_cmd.h + execute_cmd.h input.h pathexp.h flags.h # these can appear in either the source directory or the build directory and # are installed by install-headers HYBRID_HEADERS = y.tab.h -INSTALLED_BUILTINS_HEADERS = bashgetopt.h common.h getopt.h +INSTALLED_BUILTINS_HEADERS = builtext.h bashgetopt.h common.h getopt.h INSTALLED_INCLUDE_HEADERS = posixstat.h ansi_stdlib.h filecntl.h posixdir.h \ memalloc.h stdc.h posixjmp.h posixwait.h posixtime.h systimes.h \ unionwait.h maxpath.h shtty.h typemax.h ocache.h chartypes.h gettext.h \ From 9501b245b4cc1bd8306ff5241882a6a83996f2dc Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Wed, 3 Dec 2025 23:46:16 -0700 Subject: [PATCH 09/37] Makefile.in: install scallop pkgconfig file --- Makefile.in | 4 ++-- configure | 3 ++- configure.ac | 2 +- support/scallop.pc.in | 11 +++++++++++ 4 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 support/scallop.pc.in diff --git a/Makefile.in b/Makefile.in index 90e7d3f8..218a22d9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -991,7 +991,7 @@ install-headers: maybe-install-headers ${INSTALL_DATA} $(srcdir)/"$$hf" $(DESTDIR)$(headersdir)/$$hf || exit 1; \ fi ; \ done - -$(INSTALL_DATA) $(SUPPORT_DIR)/bash.pc $(DESTDIR)$(pkgconfigdir)/bash.pc + -$(INSTALL_DATA) $(SUPPORT_DIR)/$(PACKAGE).pc $(DESTDIR)$(pkgconfigdir)/$(PACKAGE).pc uninstall-headers-dirs: -$(RMDIR) $(DESTDIR)$(headersdir)/builtins $(DESTDIR)$(headersdir)/include @@ -1006,7 +1006,7 @@ uninstall-headers: for hf in $${SDH} ; do \ ( cd $(DESTDIR)$(headersdir) && $(RM) $$(basename "$$hf") ) \ done - -( $(RM) $(DESTDIR)$(pkgconfigdir)/bash.pc ) + -( $(RM) $(DESTDIR)$(pkgconfigdir)/$(PACKAGE).pc ) # uninstall-headers-dirs -$(RMDIR) $(DESTDIR)$(headersdir)/builtins $(DESTDIR)$(headersdir)/include -$(RMDIR) $(DESTDIR)$(headersdir) diff --git a/configure b/configure index 77145a23..82b6feea 100755 --- a/configure +++ b/configure @@ -23301,7 +23301,7 @@ fi #AC_SUBST(ALLOCA_SOURCE) #AC_SUBST(ALLOCA_OBJECT) -ac_config_files="$ac_config_files Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile lib/intl/Makefile lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile lib/tilde/Makefile" +ac_config_files="$ac_config_files Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile lib/intl/Makefile lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile lib/tilde/Makefile support/scallop.pc" ac_config_commands="$ac_config_commands stamp-h" @@ -24041,6 +24041,7 @@ do "lib/sh/Makefile") CONFIG_FILES="$CONFIG_FILES lib/sh/Makefile" ;; "lib/termcap/Makefile") CONFIG_FILES="$CONFIG_FILES lib/termcap/Makefile" ;; "lib/tilde/Makefile") CONFIG_FILES="$CONFIG_FILES lib/tilde/Makefile" ;; + "support/scallop.pc") CONFIG_FILES="$CONFIG_FILES support/scallop.pc" ;; "stamp-h") CONFIG_COMMANDS="$CONFIG_COMMANDS stamp-h" ;; *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;; diff --git a/configure.ac b/configure.ac index 173af80c..f1367601 100644 --- a/configure.ac +++ b/configure.ac @@ -1375,7 +1375,7 @@ AC_SUBST(LOCAL_DEFS) AC_CONFIG_FILES([Makefile builtins/Makefile lib/readline/Makefile \ lib/glob/Makefile lib/intl/Makefile \ lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile \ - lib/tilde/Makefile]) + lib/tilde/Makefile support/scallop.pc]) dnl Makefile uses this timestamp file to record whether config.h is up to date. AC_CONFIG_COMMANDS([stamp-h], [echo timestamp > stamp-h]) diff --git a/support/scallop.pc.in b/support/scallop.pc.in new file mode 100644 index 00000000..ac2d0bdc --- /dev/null +++ b/support/scallop.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +libdir=@libdir@ +headersdir=${includedir}/@PACKAGE_NAME@ + +Name: @PACKAGE_NAME@ +Description: Fork of bash enabling integration into pkgcraft +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -l@PACKAGE_NAME@ +Cflags: -I${headersdir} -I${headersdir}/builtins -I${headersdir}/include From b4dab24700f70fc8bec1effc18996689aa053aba Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Thu, 30 Dec 2021 01:23:48 -0700 Subject: [PATCH 10/37] builtins: disable complete plugin if support is disabled --- builtins/complete.def | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builtins/complete.def b/builtins/complete.def index 236cd42c..d6243542 100644 --- a/builtins/complete.def +++ b/builtins/complete.def @@ -51,6 +51,7 @@ $END #include +#if defined (PROGRAMMABLE_COMPLETION) #include #include "../bashtypes.h" @@ -916,3 +917,4 @@ compopt_builtin (WORD_LIST *list) return (ret); } +#endif /* PROGRAMMABLE_COMPLETION */ From 4012cc11ff365403fcc05d07100784143be48d76 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Thu, 30 Dec 2021 01:25:15 -0700 Subject: [PATCH 11/37] config-top.h: prefer mkstemp over mktemp to avoid linking warning About the security issues with mktemp. --- config-top.h | 1 - 1 file changed, 1 deletion(-) diff --git a/config-top.h b/config-top.h index c47ab01b..cf847bb2 100644 --- a/config-top.h +++ b/config-top.h @@ -174,7 +174,6 @@ #define SOURCENEST_MAX 0 /* Define to use libc mktemp/mkstemp instead of replacements in lib/sh/tmpfile.c */ -#define USE_MKTEMP #define USE_MKSTEMP #define USE_MKDTEMP From e26a88b1f43fba22583ccab19e8c1fabd1838873 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Fri, 7 Jan 2022 19:57:04 -0700 Subject: [PATCH 12/37] add initial register_builtins() support That allows external code to register builtins internally instead of always having to using dynamic loading. --- builtins/common.c | 36 ++++++++++++++++++++++++++++++++++++ builtins/common.h | 6 ++++++ 2 files changed, 42 insertions(+) diff --git a/builtins/common.c b/builtins/common.c index a681cee4..fbcd435d 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -1081,3 +1081,39 @@ set_expand_once (int nval, int uwp) return oa; } #endif + +#if defined (BUILD_LIBRARY) +/* Register a given array of new builtins into the internal list. + * (Mostly copied from the enable builtin used when loading dynamic builtins.) + */ +int +register_builtins (struct builtin **new_builtins, size_t num_new_builtins) +{ + size_t total, size, replaced; + struct builtin *new_shell_builtins; + + total = num_shell_builtins + num_new_builtins; + size = (total + 1) * sizeof (struct builtin); + + new_shell_builtins = (struct builtin *)xmalloc (size); + FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins, + num_shell_builtins * sizeof (struct builtin)); + for (replaced = 0; replaced < num_new_builtins; replaced++) + FASTCOPY ((char *)new_builtins[replaced], + (char *)&new_shell_builtins[num_shell_builtins + replaced], + sizeof (struct builtin)); + + new_shell_builtins[total].name = (char *)0; + new_shell_builtins[total].function = (sh_builtin_func_t *)0; + new_shell_builtins[total].flags = 0; + + if (shell_builtins != static_shell_builtins) + free (shell_builtins); + + shell_builtins = new_shell_builtins; + num_shell_builtins = total; + initialize_shell_builtins (); + + return (EXECUTION_SUCCESS); +} +#endif diff --git a/builtins/common.h b/builtins/common.h index a169f494..bef2367e 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -22,6 +22,7 @@ # define __COMMON_H #include "stdc.h" +#include "builtins.h" #define ISOPTION(s, c) (s[0] == '-' && s[1] == c && !s[2]) #define ISHELP(s) (STREQ ((s), "--help")) @@ -88,6 +89,11 @@ extern void builtin_usage (void); extern void no_args (WORD_LIST *, int); extern int no_options (WORD_LIST *); +#if defined (BUILD_LIBRARY) +/* scallop extensions */ +extern int register_builtins (struct builtin **, size_t); +#endif + /* common error message functions */ extern void sh_needarg (const char *); extern void sh_neednumarg (const char *); From 86a7eb5fdbdcc19b1b784cfa0eb2d7573e37d341 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sun, 9 Jan 2022 00:59:40 -0700 Subject: [PATCH 13/37] add support for a `command_not_found_handle` builtin as well With the builtin being used if it exists instead of the function. --- execute_cmd.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/execute_cmd.c b/execute_cmd.c index 6a22395e..772dd3b9 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -5775,6 +5775,7 @@ execute_disk_command (WORD_LIST *words, REDIRECT *redirects, char *command_line, char *pathname, *command, **args, *p; int nofork, stdpath, result, fork_flags; pid_t pid; + sh_builtin_func_t *hookb; SHELL_VAR *hookf; WORD_LIST *wl; @@ -5902,8 +5903,9 @@ execute_disk_command (WORD_LIST *words, REDIRECT *redirects, char *command_line, if (command == 0) { + hookb = find_shell_builtin (NOTFOUND_HOOK); hookf = find_function (NOTFOUND_HOOK); - if (hookf == 0) + if (hookb == 0 && hookf == 0) { /* Make sure filenames are displayed using printable characters */ pathname = printable_filename (pathname, 0); @@ -5921,7 +5923,13 @@ execute_disk_command (WORD_LIST *words, REDIRECT *redirects, char *command_line, #endif wl = make_word_list (make_word (NOTFOUND_HOOK), words); - exit (execute_shell_function (hookf, wl)); + if (hookb != 0) + { + this_command_name = NOTFOUND_HOOK; + exit (execute_builtin (hookb, wl, 0, 0)); + } + else + exit (execute_shell_function (hookf, wl)); } /* Execve expects the command name to be in args[0]. So we From a7289a88ed5c6e935c0861533b0e28c8b8abc082 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Mon, 10 Jan 2022 00:04:30 -0700 Subject: [PATCH 14/37] export lib_init() and lib_reset() to initialize/reset the global state Bash uses an extensive amount of global state and when used as a library init/reset actions are required for regular operation. --- shell.c | 17 +++++++++++++++++ shell.h | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/shell.c b/shell.c index 34b64894..526037c0 100644 --- a/shell.c +++ b/shell.c @@ -2061,6 +2061,23 @@ shell_reinitialize (void) shell_reinitialized = 1; } +#if defined (BUILD_LIBRARY) +void +lib_init () +{ + shell_initialize(); +} + +void +lib_reset () +{ + shell_reinitialize(); + initialize_shell_variables (shell_environment, privileged_mode||running_setuid); + initialize_shell_options (privileged_mode||running_setuid); + initialize_bashopts (privileged_mode||running_setuid); +} +#endif + static void show_shell_usage (FILE *fp, int extra) { diff --git a/shell.h b/shell.h index 437a03e4..a46ec885 100644 --- a/shell.h +++ b/shell.h @@ -260,4 +260,9 @@ extern int bash_main (int argc, char **argv); extern int bash_main (int argc, char **argv, char **env); #endif /* !NO_MAIN_ENV_ARG */ +#if defined (BUILD_LIBRARY) +extern void lib_init (void); +extern void lib_reset (void); +#endif + #endif /* _SHELL_H_ */ From 373bffb010f84919159eae8d9fe68a2f422efde8 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Thu, 13 Jan 2022 05:06:44 -0700 Subject: [PATCH 15/37] allow BASH_CMDS and BASH_ALIASES data to be freed on reset Without this both leak their underlying array data whenever lib_reset() is called. --- variables.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/variables.c b/variables.c index 4e6f93bf..0bdbca40 100644 --- a/variables.c +++ b/variables.c @@ -1892,9 +1892,9 @@ initialize_dynamic_variables (void) v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset); v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset); - v = init_dynamic_assoc_var ("BASH_CMDS", get_hashcmd, assign_hashcmd, att_nofree); + v = init_dynamic_assoc_var ("BASH_CMDS", get_hashcmd, assign_hashcmd, att_noassign); # if defined (ALIAS) - v = init_dynamic_assoc_var ("BASH_ALIASES", get_aliasvar, assign_aliasvar, att_nofree); + v = init_dynamic_assoc_var ("BASH_ALIASES", get_aliasvar, assign_aliasvar, att_noassign); # endif #endif From ff79e3b0aaf0bfb7bc9395b554b3317791690b27 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sat, 15 Jan 2022 15:14:11 -0700 Subject: [PATCH 16/37] add longjmp wrappers for sourcing and execution functionality Bash uses setjmp/longjmp for error, interrupt, and signal handling cases and thus initializes jump targets in main() which doesn't get called when used as a library. Adding jump targets in the main entry points (sourcing and execution) allows returning proper error codes during library operation and avoids issues with unwinding across rust frames (which is currently UB and generally causes segfaults) when using scallop rust support. Without this, a segfault occurs if a file with errors is sourced under library usage and `set -e` enabled since no top level jump target is set and parse_and_execute() tries to longjmp to a NULL target. Note that the call stack is tracked from scallop so reentrant calls jump back to where they entered and not the initial call's entry point. --- builtins/common.h | 2 ++ builtins/evalfile.c | 16 +++++++++++++++ builtins/evalstring.c | 16 +++++++++++++++ execute_cmd.c | 48 ++++++++++++++++++++++++++++++++++++++++++- execute_cmd.h | 5 +++++ jobs.c | 8 ++++++++ shell.h | 1 + subst.c | 8 ++++++++ 8 files changed, 103 insertions(+), 1 deletion(-) diff --git a/builtins/common.h b/builtins/common.h index bef2367e..d398ee56 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -92,6 +92,8 @@ extern int no_options (WORD_LIST *); #if defined (BUILD_LIBRARY) /* scallop extensions */ extern int register_builtins (struct builtin **, size_t); +extern int scallop_source_file (const char *); +extern int scallop_evalstring (const char *, int); #endif /* common error message functions */ diff --git a/builtins/evalfile.c b/builtins/evalfile.c index 3026c5f0..7aa35232 100644 --- a/builtins/evalfile.c +++ b/builtins/evalfile.c @@ -395,3 +395,19 @@ source_file (const char *filename, int sflags) run_return_trap (); return rval; } + +#if defined (BUILD_LIBRARY) +int +scallop_source_file (const char *filename) +{ + int code, result; + + code = setjmp_nosigs (top_level); + if (code) { + return EXECUTION_FAILURE; + } + + result = source_file(filename, 0); + return result; +} +#endif diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 2b15b9dd..c2aa3d30 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -864,3 +864,19 @@ evalstring (char *string, const char *from_file, int flags) return (r); } + +#if defined (BUILD_LIBRARY) +int +scallop_evalstring (const char *string, int flags) +{ + int code, result; + + code = setjmp_nosigs (top_level); + if (code) { + return EXECUTION_FAILURE; + } + + result = evalstring((char *)string, "scallop", flags | SEVAL_NOFREE); + return result; +} +#endif diff --git a/execute_cmd.c b/execute_cmd.c index 772dd3b9..881e7398 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -788,6 +788,14 @@ execute_command_internal (COMMAND *command, int asynchronous, int pipe_in, int p jump_to_top_level (ERREXIT); } +#if defined (BUILD_LIBRARY) + if (last_command_exit_value == EX_LONGJMP) + { + last_command_exit_value = EXECUTION_FAILURE; + jump_to_top_level (ERREXIT); + } +#endif + return (last_command_exit_value); } else @@ -4858,7 +4866,7 @@ itrace("execute_simple_command: posix mode tempenv assignment error"); cmdflags); if (builtin) { - if (result > EX_SHERRBASE) + if (result > EX_SHERRBASE || result == EX_LONGJMP) { switch (result) { @@ -4872,6 +4880,12 @@ itrace("execute_simple_command: posix mode tempenv assignment error"); jump_to_top_level (ERREXIT); } break; +#if defined (BUILD_LIBRARY) + case EX_LONGJMP: + last_command_exit_value = EXECUTION_FAILURE; + jump_to_top_level (ERREXIT); + break; +#endif case EX_DISKFALLBACK: /* XXX - experimental */ executing_builtin = old_builtin; @@ -6415,3 +6429,35 @@ do_piping (int pipe_in, int pipe_out) #endif /* __CYGWIN__ */ } } + +#if defined (BUILD_LIBRARY) +int +scallop_execute_command (COMMAND *command) +{ + int code, result; + + code = setjmp_nosigs (top_level); + if (code) { + return EXECUTION_FAILURE; + } + + result = execute_command(command); + QUIT; + return result; +} + +int +scallop_execute_shell_function (SHELL_VAR *var, WORD_LIST *words) +{ + int code, result; + + code = setjmp_nosigs (top_level); + if (code) { + return EXECUTION_FAILURE; + } + + result = execute_shell_function(var, words); + QUIT; + return result; +} +#endif diff --git a/execute_cmd.h b/execute_cmd.h index cd2bad86..a28bab9f 100644 --- a/execute_cmd.h +++ b/execute_cmd.h @@ -136,4 +136,9 @@ extern void uw_close (void *); extern void init_notfound_str (void); +#if defined (BUILD_LIBRARY) +extern int scallop_execute_command (COMMAND *); +extern int scallop_execute_shell_function (SHELL_VAR *, WORD_LIST *); +#endif + #endif /* _EXECUTE_CMD_H_ */ diff --git a/jobs.c b/jobs.c index 0f32ebbf..da14c110 100644 --- a/jobs.c +++ b/jobs.c @@ -3389,6 +3389,14 @@ if (job == NO_JOB) UNBLOCK_CHILD (oset); +#if defined (BUILD_LIBRARY) + if (termination_state == EX_LONGJMP) + { + last_command_exit_value = EXECUTION_FAILURE; + jump_to_top_level (ERREXIT); + } +#endif + return (termination_state); } diff --git a/shell.h b/shell.h index a46ec885..686562c3 100644 --- a/shell.h +++ b/shell.h @@ -68,6 +68,7 @@ extern int EOF_Reached; #define EX_NOINPUT 126 #define EX_NOTFOUND 127 +#define EX_LONGJMP 255 /* longjmp to top level */ #define EX_SHERRBASE 256 /* all special error values are > this. */ #define EX_BADSYNTAX 257 /* shell syntax error */ diff --git a/subst.c b/subst.c index dd5d57bf..c4556614 100644 --- a/subst.c +++ b/subst.c @@ -7468,6 +7468,14 @@ command_substitute (char *string, int quoted, int flags) cleanup_the_pipeline (); #endif +#if defined (BUILD_LIBRARY) + if (last_command_exit_value == EX_LONGJMP) + { + last_command_exit_value = EXECUTION_FAILURE; + jump_to_top_level (ERREXIT); + } +#endif + ret = alloc_word_desc (); ret->word = istring; ret->flags = tflag; From d9cce266cb213c4944638b0f5cda10ec8c6402da Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Mon, 20 Nov 2023 13:41:28 -0700 Subject: [PATCH 17/37] save and restore the previous top level longjmp on entry/exit --- builtins/evalfile.c | 4 ++++ builtins/evalstring.c | 4 ++++ execute_cmd.c | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/builtins/evalfile.c b/builtins/evalfile.c index 7aa35232..b59539b5 100644 --- a/builtins/evalfile.c +++ b/builtins/evalfile.c @@ -401,13 +401,17 @@ int scallop_source_file (const char *filename) { int code, result; + volatile procenv_t save_top_level; + COPY_PROCENV (top_level, save_top_level); code = setjmp_nosigs (top_level); if (code) { + COPY_PROCENV (save_top_level, top_level); return EXECUTION_FAILURE; } result = source_file(filename, 0); + COPY_PROCENV (save_top_level, top_level); return result; } #endif diff --git a/builtins/evalstring.c b/builtins/evalstring.c index c2aa3d30..68fa76fa 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -870,13 +870,17 @@ int scallop_evalstring (const char *string, int flags) { int code, result; + volatile procenv_t save_top_level; + COPY_PROCENV (top_level, save_top_level); code = setjmp_nosigs (top_level); if (code) { + COPY_PROCENV (save_top_level, top_level); return EXECUTION_FAILURE; } result = evalstring((char *)string, "scallop", flags | SEVAL_NOFREE); + COPY_PROCENV (save_top_level, top_level); return result; } #endif diff --git a/execute_cmd.c b/execute_cmd.c index 881e7398..12625a15 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -6435,13 +6435,17 @@ int scallop_execute_command (COMMAND *command) { int code, result; + volatile procenv_t save_top_level; + COPY_PROCENV (top_level, save_top_level); code = setjmp_nosigs (top_level); if (code) { + COPY_PROCENV (save_top_level, top_level); return EXECUTION_FAILURE; } result = execute_command(command); + COPY_PROCENV (save_top_level, top_level); QUIT; return result; } @@ -6450,13 +6454,17 @@ int scallop_execute_shell_function (SHELL_VAR *var, WORD_LIST *words) { int code, result; + volatile procenv_t save_top_level; + COPY_PROCENV (top_level, save_top_level); code = setjmp_nosigs (top_level); if (code) { + COPY_PROCENV (save_top_level, top_level); return EXECUTION_FAILURE; } result = execute_shell_function(var, words); + COPY_PROCENV (save_top_level, top_level); QUIT; return result; } From cfcf1da20a6aa61887812273660cf2f710b8a6a5 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sat, 22 Jan 2022 00:01:12 -0700 Subject: [PATCH 18/37] add initial support for proxying errors and warnings back to rust Instead of always dumping them into stderr. --- builtins/common.c | 45 +++++++++++------ error.c | 126 ++++++++++++++++++++++++++++++---------------- error.h | 3 ++ shell.c | 7 ++- shell.h | 6 ++- 5 files changed, 128 insertions(+), 59 deletions(-) diff --git a/builtins/common.c b/builtins/common.c index fbcd435d..6b36af44 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -80,47 +80,64 @@ sh_builtin_func_t *this_shell_builtin = (sh_builtin_func_t *)NULL; shell. */ static void -builtin_error_prolog (void) +builtin_error_prolog (char *buf) { char *name; + int line; name = get_name_for_error (); - fprintf (stderr, "%s: ", name); + snprintf(buf, MAX_ERROR_LEN, "%s: ", name); - if (interactive_shell == 0) - fprintf (stderr, _("line %d: "), executing_line_number ()); + if (interactive_shell == 0) { + line = executing_line_number (); + if (line != 0) { + snprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), _("line %d: "), line); + } + } if (this_command_name && *this_command_name) - fprintf (stderr, "%s: ", this_command_name); + snprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), "%s: ", this_command_name); } void builtin_error (const char *format, ...) { va_list args; + char buf[MAX_ERROR_LEN] = ""; - builtin_error_prolog (); + builtin_error_prolog (&buf[0]); va_start (args, format); - - vfprintf (stderr, format, args); + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); va_end (args); - fprintf (stderr, "\n"); + +#if defined (BUILD_LIBRARY) + scallop_error(buf); +#else + fprintf (stderr, "%s\n", buf); +#endif } void builtin_warning (const char *format, ...) { va_list args; + char buf[MAX_ERROR_LEN] = ""; - builtin_error_prolog (); - fprintf (stderr, _("warning: ")); + builtin_error_prolog (&buf[0]); +#if !defined (BUILD_LIBRARY) + snprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), _("warning: ")); +#endif va_start (args, format); - - vfprintf (stderr, format, args); + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); va_end (args); - fprintf (stderr, "\n"); + +#if defined (BUILD_LIBRARY) + scallop_warning(buf); +#else + fprintf (stderr, "%s\n", buf); +#endif } /* Print a usage summary for the currently-executing builtin command. */ diff --git a/error.c b/error.c index 10af0709..75d43d42 100644 --- a/error.c +++ b/error.c @@ -58,7 +58,7 @@ extern int give_terminal_to (pid_t, int); extern const char * const bash_badsub_errmsg; #endif -static void error_prolog (int); +static void error_prolog (int, char *); /* The current maintainer of the shell. You change this in the Makefile. */ @@ -71,7 +71,7 @@ const char * const the_current_maintainer = MAINTAINER; int gnu_error_format = 0; static void -error_prolog (int print_lineno) +error_prolog (int print_lineno, char *buf) { char *ename; int line; @@ -80,9 +80,9 @@ error_prolog (int print_lineno) line = (print_lineno && interactive_shell == 0) ? executing_line_number () : -1; if (line > 0) - fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), line); + snprintf (buf, MAX_ERROR_LEN, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), line); else - fprintf (stderr, "%s: ", ename); + snprintf (buf, MAX_ERROR_LEN, "%s: ", ename); } /* Return the name of the shell or the shell script for error reporting. */ @@ -132,6 +132,7 @@ void programming_error (const char *format, ...) { va_list args; + char buf[MAX_ERROR_LEN] = ""; char *h; #if defined (JOB_CONTROL) @@ -139,11 +140,14 @@ programming_error (const char *format, ...) #endif /* JOB_CONTROL */ va_start (args, format); - - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); va_end (args); +#if defined (BUILD_LIBRARY) + scallop_error(buf); +#else + fprintf (stderr, "%s\n", buf); + #if defined (HISTORY) if (remember_on_history) { @@ -158,6 +162,7 @@ programming_error (const char *format, ...) fprintf (stderr, _("Aborting...")); fflush (stderr); +#endif /* BUILD_LIBRARY */ abort (); } @@ -170,15 +175,20 @@ void report_error (const char *format, ...) { va_list args; + char buf[MAX_ERROR_LEN] = ""; - error_prolog (1); + error_prolog (1, &buf[0]); va_start (args, format); + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); + va_end (args); - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); +#if defined (BUILD_LIBRARY) + scallop_error(buf); +#else + fprintf (stderr, "%s\n", buf); +#endif - va_end (args); if (exit_immediately_on_error) { if (last_command_exit_value == 0) @@ -191,15 +201,20 @@ void fatal_error (const char *format, ...) { va_list args; + char buf[MAX_ERROR_LEN] = ""; - error_prolog (0); + error_prolog (0, &buf[0]); va_start (args, format); + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); + va_end (args); - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); +#if defined (BUILD_LIBRARY) + scallop_error(buf); +#else + fprintf (stderr, "%s\n", buf); +#endif - va_end (args); sh_exit (2); } @@ -207,48 +222,64 @@ void internal_error (const char *format, ...) { va_list args; + char buf[MAX_ERROR_LEN] = ""; - error_prolog (1); + error_prolog (1, &buf[0]); va_start (args, format); - - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); - + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); va_end (args); + +#if defined (BUILD_LIBRARY) + scallop_error(buf); +#else + fprintf (stderr, "%s\n", buf); +#endif } void internal_warning (const char *format, ...) { va_list args; + char buf[MAX_ERROR_LEN] = ""; - error_prolog (1); + error_prolog (1, &buf[0]); +#if !defined (BUILD_LIBRARY) fprintf (stderr, _("warning: ")); +#endif va_start (args, format); - - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); - + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); va_end (args); + +#if defined (BUILD_LIBRARY) + scallop_warning(buf); +#else + fprintf (stderr, "%s\n", buf); +#endif } void internal_inform (const char *format, ...) { va_list args; + char buf[MAX_ERROR_LEN] = ""; - error_prolog (1); + error_prolog (1, &buf[0]); /* TRANSLATORS: this is a prefix for informational messages. */ +#if !defined (BUILD_LIBRARY) fprintf (stderr, _("INFORM: ")); +#endif va_start (args, format); - - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); - + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); va_end (args); + +#if defined (BUILD_LIBRARY) + scallop_warning(buf); +#else + fprintf (stderr, "%s\n", buf); +#endif } void @@ -276,16 +307,21 @@ sys_error (const char *format, ...) { int e; va_list args; + char buf[MAX_ERROR_LEN] = ""; e = errno; - error_prolog (0); + error_prolog (0, &buf[0]); va_start (args, format); - - vfprintf (stderr, format, args); - fprintf (stderr, ": %s\n", strerror (e)); - + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); va_end (args); + snprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), ": %s", strerror (e)); + +#if defined (BUILD_LIBRARY) + scallop_error(buf); +#else + fprintf (stderr, "%s\n", buf); +#endif } /* An error from the parser takes the general form @@ -300,27 +336,31 @@ void parser_error (int lineno, const char *format, ...) { va_list args; + char buf[MAX_ERROR_LEN] = ""; char *ename, *iname; ename = get_name_for_error (); iname = yy_input_name (); if (interactive) - fprintf (stderr, "%s: ", ename); + snprintf (buf, MAX_ERROR_LEN, "%s: ", ename); else if (interactive_shell) - fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno); + snprintf (buf, MAX_ERROR_LEN, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno); else if (STREQ (ename, iname)) - fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), lineno); + snprintf (buf, MAX_ERROR_LEN, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), lineno); else - fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno); + snprintf (buf, MAX_ERROR_LEN, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno); va_start (args, format); - - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); - + vsnprintf(buf + strlen(buf), MAX_ERROR_LEN - strlen(buf), format, args); va_end (args); +#if defined (BUILD_LIBRARY) + scallop_error(buf); +#else + fprintf (stderr, "%s\n", buf); +#endif + if (exit_immediately_on_error) exit_shell (last_command_exit_value = 2); } diff --git a/error.h b/error.h index db0972bc..e9e7fc4d 100644 --- a/error.h +++ b/error.h @@ -81,4 +81,7 @@ extern void err_invalidid (const char *); # define INTERNAL_DEBUG(x) #endif +/* Maximum length of an error message, the rest is truncated. */ +#define MAX_ERROR_LEN 512 + #endif /* !_ERROR_H_ */ diff --git a/shell.c b/shell.c index 526037c0..636071c9 100644 --- a/shell.c +++ b/shell.c @@ -2062,9 +2062,14 @@ shell_reinitialize (void) } #if defined (BUILD_LIBRARY) +scallop_cb scallop_error; +scallop_cb scallop_warning; + void -lib_init () +lib_init (scallop_cb error_cb, scallop_cb warning_cb) { + scallop_error = error_cb; + scallop_warning = warning_cb; shell_initialize(); } diff --git a/shell.h b/shell.h index 686562c3..06ef6e4a 100644 --- a/shell.h +++ b/shell.h @@ -262,7 +262,11 @@ extern int bash_main (int argc, char **argv, char **env); #endif /* !NO_MAIN_ENV_ARG */ #if defined (BUILD_LIBRARY) -extern void lib_init (void); +typedef void (*scallop_cb)(char *); +extern scallop_cb scallop_error; +extern scallop_cb scallop_warning; + +extern void lib_init (scallop_cb error_cb, scallop_cb warning_cb); extern void lib_reset (void); #endif From 43a8f50abf9feff71c907f854ceef61baf0770ea Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Mon, 14 Feb 2022 15:32:55 -0700 Subject: [PATCH 19/37] add error support that reads the message from shared memory Used via external library to inject errors into bash across process boundaries (e.g. erroring out from subshells). --- error.c | 2 ++ error.h | 2 ++ shell.c | 9 +++++++-- shell.h | 3 ++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/error.c b/error.c index 75d43d42..e9f9312a 100644 --- a/error.c +++ b/error.c @@ -48,6 +48,8 @@ extern int errno; #endif extern int executing_line_number (void); +/* Shared memory buffer used to inject errors. */ +void *SHM_BUF; #if defined (JOB_CONTROL) extern pid_t shell_pgrp; diff --git a/error.h b/error.h index e9e7fc4d..825a2070 100644 --- a/error.h +++ b/error.h @@ -83,5 +83,7 @@ extern void err_invalidid (const char *); /* Maximum length of an error message, the rest is truncated. */ #define MAX_ERROR_LEN 512 +/* Shared memory buffer used to inject errors. */ +extern void *SHM_BUF; #endif /* !_ERROR_H_ */ diff --git a/shell.c b/shell.c index 636071c9..b007c282 100644 --- a/shell.c +++ b/shell.c @@ -2066,11 +2066,16 @@ scallop_cb scallop_error; scallop_cb scallop_warning; void -lib_init (scallop_cb error_cb, scallop_cb warning_cb) +lib_init () +{ + shell_initialize(); +} + +void +lib_error_handlers (scallop_cb error_cb, scallop_cb warning_cb) { scallop_error = error_cb; scallop_warning = warning_cb; - shell_initialize(); } void diff --git a/shell.h b/shell.h index 06ef6e4a..1f0c982f 100644 --- a/shell.h +++ b/shell.h @@ -266,7 +266,8 @@ typedef void (*scallop_cb)(char *); extern scallop_cb scallop_error; extern scallop_cb scallop_warning; -extern void lib_init (scallop_cb error_cb, scallop_cb warning_cb); +extern void lib_init (void); +extern void lib_error_handlers (scallop_cb error_cb, scallop_cb warning_cb); extern void lib_reset (void); #endif From 20525ad25d355419025dce8cb72b442cd61a65ee Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Tue, 28 Jun 2022 22:29:34 -0600 Subject: [PATCH 20/37] jobs: don't set SIGCHLD handler by default when job control is disabled Installing a SIGCHLD handler by default breaks pkgcraft unit tests that spawn child processes and use wait() or waitpid() to wait for completion, e.g. tests for builtins such as `econf`. When enabled by default the tests fail with ECHILD (errno 10) when trying to wait on child processes since the installed signal handler gets control instead during child termination. --- jobs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jobs.c b/jobs.c index da14c110..f6b0d0f9 100644 --- a/jobs.c +++ b/jobs.c @@ -4872,7 +4872,8 @@ initialize_job_control (int force) if (shell_tty != fileno (stderr)) SET_CLOSE_ON_EXEC (shell_tty); - set_signal_handler (SIGCHLD, sigchld_handler); + if (job_control) + set_signal_handler (SIGCHLD, sigchld_handler); change_flag ('m', job_control ? '-' : '+'); From 9d066fcd07962ac2f1de2e242c740b0f2feec69f Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Fri, 23 Dec 2022 20:15:12 -0700 Subject: [PATCH 21/37] use custom values for restricted shell name and static PATH --- config-bot.h | 2 +- config-top.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config-bot.h b/config-bot.h index 07e910f1..6dd1fd52 100644 --- a/config-bot.h +++ b/config-bot.h @@ -93,7 +93,7 @@ /* If the shell is called by this name, it will become restricted. */ #if defined (RESTRICTED_SHELL) -# define RESTRICTED_SHELL_NAME "rbash" +# define RESTRICTED_SHELL_NAME "rscallop" #endif /***********************************************************/ diff --git a/config-top.h b/config-top.h index cf847bb2..1145b7df 100644 --- a/config-top.h +++ b/config-top.h @@ -63,7 +63,7 @@ /* If you want to unconditionally set a value for PATH in every restricted shell, set this. */ -/* #define RBASH_STATIC_PATH_VALUE "/rbin:/usr/rbin" */ +#define RBASH_STATIC_PATH_VALUE "/dev/null" /* The value for PATH when invoking `command -p'. This is only used when the Posix.2 confstr () function, or CS_PATH define are not present. */ From 2b7a0962687fc5dce6933e1e5dcb01d474100544 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Fri, 23 Dec 2022 20:15:53 -0700 Subject: [PATCH 22/37] shell: add support for toggling restricted mode --- shell.c | 35 ++++++++++++++++++++++++++++++++--- shell.h | 2 ++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/shell.c b/shell.c index b007c282..eff9f114 100644 --- a/shell.c +++ b/shell.c @@ -2081,10 +2081,39 @@ lib_error_handlers (scallop_cb error_cb, scallop_cb warning_cb) void lib_reset () { + int orig_restricted = restricted; shell_reinitialize(); - initialize_shell_variables (shell_environment, privileged_mode||running_setuid); - initialize_shell_options (privileged_mode||running_setuid); - initialize_bashopts (privileged_mode||running_setuid); + restricted = orig_restricted; + initialize_shell_variables (shell_environment, privileged_mode||restricted||running_setuid); + initialize_shell_options (privileged_mode||restricted||running_setuid); + initialize_bashopts (privileged_mode||restricted||running_setuid); + + // reinitialization resets restricted status, so re-enable it if requested + if (orig_restricted) { + scallop_toggle_restricted(orig_restricted); + } +} + +void +scallop_toggle_restricted (int status) +{ + if (status && !restricted) { + bind_variable ("PATH", "/dev/null", 0); + stupidly_hack_special_variables ("PATH"); /* clear hash table */ + set_var_read_only ("PATH"); + set_var_read_only ("SHELL"); + set_var_read_only ("ENV"); + set_var_read_only ("BASH_ENV"); + set_var_read_only ("HISTFILE"); + restricted = 1; + } else if (!status && restricted) { + restricted = 0; + set_var_read_write ("PATH"); + set_var_read_write ("SHELL"); + set_var_read_write ("ENV"); + set_var_read_write ("BASH_ENV"); + set_var_read_write ("HISTFILE"); + } } #endif diff --git a/shell.h b/shell.h index 1f0c982f..41ecef3b 100644 --- a/shell.h +++ b/shell.h @@ -269,6 +269,8 @@ extern scallop_cb scallop_warning; extern void lib_init (void); extern void lib_error_handlers (scallop_cb error_cb, scallop_cb warning_cb); extern void lib_reset (void); + +extern void scallop_toggle_restricted (int); #endif #endif /* _SHELL_H_ */ From 33d255ef36f02c9cde7e2ea3909a66bfde18dfff Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sat, 28 Jan 2023 03:18:40 -0700 Subject: [PATCH 23/37] shell: add support to set shell name via lib_init() --- shell.c | 1 + 1 file changed, 1 insertion(+) diff --git a/shell.c b/shell.c index eff9f114..196dfdba 100644 --- a/shell.c +++ b/shell.c @@ -2068,6 +2068,7 @@ scallop_cb scallop_warning; void lib_init () { + set_shell_name("scallop"); shell_initialize(); } From fd59a27be1e5495add3801d208a6d3b16844f971 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Fri, 23 Dec 2022 23:13:35 -0700 Subject: [PATCH 24/37] redir: allow write redirections to /dev/null under restricted mode --- redir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redir.c b/redir.c index 343536b7..d340b0a9 100644 --- a/redir.c +++ b/redir.c @@ -916,7 +916,7 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp) return (AMBIGUOUS_REDIRECT); #if defined (RESTRICTED_SHELL) - if (restricted && (WRITE_REDIRECT (ri))) + if (restricted && (WRITE_REDIRECT (ri)) && (strcmp(redirectee_word, "/dev/null") != 0)) { free (redirectee_word); return (RESTRICTED_REDIRECT); From a20234ee5b7469b22d191aaf4748a5f942e62036 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Tue, 9 May 2023 21:12:31 -0600 Subject: [PATCH 25/37] variables: add set_var_read_write() support That allows easily reverting set_var_read_only() settings when toggling restricted mode. --- variables.c | 13 +++++++++++++ variables.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/variables.c b/variables.c index 0bdbca40..96798162 100644 --- a/variables.c +++ b/variables.c @@ -4084,6 +4084,19 @@ set_var_read_only (char *name) VSETATTR (entry, att_readonly); } +#if defined (BUILD_LIBRARY) +/* Make the variable associated with NAME be read/write. */ +void +set_var_read_write (char *name) +{ + SHELL_VAR *entry; + + entry = find_variable (name); + if (entry) + VUNSETATTR (entry, att_readonly); +} +#endif + #ifdef INCLUDE_UNUSED /* Make the function associated with NAME be readonly. If NAME does not exist, we just punt, like auto_export code below. */ diff --git a/variables.h b/variables.h index e939e596..5cd12881 100644 --- a/variables.h +++ b/variables.h @@ -395,6 +395,9 @@ extern void kill_all_local_variables (void); extern HASH_TABLE *copy_vartab (HASH_TABLE *); extern void set_var_read_only (char *); +#if defined (BUILD_LIBRARY) +extern void set_var_read_write (char *); +#endif extern void set_func_read_only (const char *); extern void set_var_auto_export (char *); extern void set_func_auto_export (const char *); From 947f442ca9eb51c875409dcc5667d1a317c6f36d Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Mon, 15 May 2023 10:33:47 -0600 Subject: [PATCH 26/37] shell: fix environment propagation for library usage Without this the process environment isn't inherited and the bash initialization methods unset everything. --- shell.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell.c b/shell.c index 196dfdba..d9fabf1a 100644 --- a/shell.c +++ b/shell.c @@ -2069,6 +2069,7 @@ void lib_init () { set_shell_name("scallop"); + shell_environment = environ; shell_initialize(); } @@ -2083,6 +2084,7 @@ void lib_reset () { int orig_restricted = restricted; + shell_environment = environ; shell_reinitialize(); restricted = orig_restricted; initialize_shell_variables (shell_environment, privileged_mode||restricted||running_setuid); From 0eefb25f0266e0fad86ac5c684a9d7ac50efcf83 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sun, 18 Jun 2023 10:48:43 -0600 Subject: [PATCH 27/37] builtins: use a warning for `declare -p` with undefined variables Instead of raising an error. The exit status of the command should be enough to signify failure. This avoids the issue where `declare -p UNDEFINED_VAR` is being used to determine if a variable is defined causing errors when sourcing the related file or string. --- builtins/declare.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtins/declare.def b/builtins/declare.def index 8f7f4834..76baa9ae 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -398,7 +398,7 @@ declare_internal (WORD_LIST *list, int local_var) pflag = show_name_attributes (list->word->word, nodefs); if (pflag) { - sh_notfound (list->word->word); + builtin_warning (_("%s: not found"), list->word->word); any_failed++; } } From d371d0a974daca1d74b3eb33a9214d2f5da4d13e Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Thu, 21 Sep 2023 08:05:34 -0600 Subject: [PATCH 28/37] execute_cmd: always search for special builtins during simple command exec This allows externally registered special builtins to always override functions even when bash isn't built with strict posix mode enabled. This will also have the affect that special builtins native to bash, e.g. exit and source (see the full list via `enable -s`), won't be able to be overridden by functions which in our case shouldn't matter and probably is a good thing anyway. --- execute_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execute_cmd.c b/execute_cmd.c index 12625a15..0f06a34f 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -4670,7 +4670,7 @@ execute_simple_command (SIMPLE_COM *simple_command, int pipe_in, int pipe_out, i being used, and we don't want to exit the shell if a special builtin executed with `command builtin' fails. `command' is not a special builtin. */ - if (posixly_correct) + if (posixly_correct || BUILD_LIBRARY) { builtin = find_special_builtin (words->word->word); if (builtin) From b6338146fa56cc18f0b189d5a57d601572d9fdbb Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sun, 27 Apr 2025 22:58:38 -0600 Subject: [PATCH 29/37] shell: support setting the environment via passed in values --- shell.c | 8 ++++---- shell.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/shell.c b/shell.c index d9fabf1a..3270ec56 100644 --- a/shell.c +++ b/shell.c @@ -2066,10 +2066,10 @@ scallop_cb scallop_error; scallop_cb scallop_warning; void -lib_init () +lib_init (char **env) { set_shell_name("scallop"); - shell_environment = environ; + shell_environment = env; shell_initialize(); } @@ -2081,10 +2081,10 @@ lib_error_handlers (scallop_cb error_cb, scallop_cb warning_cb) } void -lib_reset () +lib_reset (char **env) { int orig_restricted = restricted; - shell_environment = environ; + shell_environment = env; shell_reinitialize(); restricted = orig_restricted; initialize_shell_variables (shell_environment, privileged_mode||restricted||running_setuid); diff --git a/shell.h b/shell.h index 41ecef3b..8992224d 100644 --- a/shell.h +++ b/shell.h @@ -266,9 +266,9 @@ typedef void (*scallop_cb)(char *); extern scallop_cb scallop_error; extern scallop_cb scallop_warning; -extern void lib_init (void); +extern void lib_init (char **); extern void lib_error_handlers (scallop_cb error_cb, scallop_cb warning_cb); -extern void lib_reset (void); +extern void lib_reset (char **); extern void scallop_toggle_restricted (int); #endif From 212b890b61d94e26fc184ef3b9e5afb8a72df162 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sat, 6 Dec 2025 14:25:12 -0700 Subject: [PATCH 30/37] add required scallop configure options and related wrapper script These should be used externally to build with the options required by scallop otherwise it's unsupported when used for pkgcraft. --- configure-scallop | 16 ++++++++++++++++ configure-scallop-options | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100755 configure-scallop create mode 100644 configure-scallop-options diff --git a/configure-scallop b/configure-scallop new file mode 100755 index 00000000..4bfc8c19 --- /dev/null +++ b/configure-scallop @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# +# Configure bash using the required scallop options. + +# change working directory to bash repo +cd "$(dirname "${BASH_SOURCE[0]}")" + +# load required configure options +declare -a myconf +while IFS= read -r line; do + [[ -z ${line} || ${line} =~ ^# ]] && continue + myconf+=( ${line} ) +done < configure-scallop-options + +# configure using defined options +./configure "${myconf[@]}" "$@" diff --git a/configure-scallop-options b/configure-scallop-options new file mode 100644 index 00000000..df8b51c7 --- /dev/null +++ b/configure-scallop-options @@ -0,0 +1,19 @@ +# configure options required by scallop + +--disable-readline +--disable-history +--disable-bang-history +--disable-progcomp +--without-bash-malloc +--disable-mem-scramble +--disable-net-redirections +--disable-nls + +# job control is required for $PIPESTATUS +--enable-job-control + +# enable restricted shell +--enable-restricted + +# enable scallop library +--enable-library From 87dd4fce35f80b0a29fe410fc191b4b53afb343e Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Thu, 4 Dec 2025 01:33:52 -0700 Subject: [PATCH 31/37] ci: add release workflow --- .github/dependabot.yml | 6 ++ .github/workflows/release.yml | 108 ++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..5ace4600 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..a6bbbaa6 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,108 @@ +name: release + +on: + push: + tags: [scallop-*] + branches: ['**'] + paths: + - ".github/workflows/release.yml" + workflow_dispatch: + +jobs: + release: + runs-on: ubuntu-latest + outputs: + release: ${{ steps.release.outputs.release }} + version: ${{ steps.release.outputs.version }} + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Get the release name + id: release + run: | + name=$(sed -rn "/^PACKAGE_NAME=/ s/^.*='(.*)'/\1/p" configure) + version=$(sed -rn "/^PACKAGE_VERSION=/ s/^.*='(.*)'/\1/p" configure) + release=${name}-${version} + ref=${{ github.ref_name }} + + # verify tag name matches configure script + if [[ ${{ github.ref_type }} == tag && ${ref} != ${release} ]]; then + echo "tag name ${ref} doesn't match package: ${release}" + exit 1 + fi + + echo "release=${release}" >> $GITHUB_OUTPUT + echo "version=${version}" >> $GITHUB_OUTPUT + + source: + needs: release + runs-on: ubuntu-latest + env: + RELEASE: ${{ needs.release.outputs.release }} + VERSION: ${{ needs.release.outputs.version }} + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + path: bash + + - name: Create release tarball + run: | + # remove unused files + rm -r bash/{doc,examples,tests,po} + + # copy non-hidden files + mkdir ${RELEASE} + cp -a bash/* ${RELEASE} + + # create tarball + tar -c -I "xz -9 -T0" -f ${RELEASE}.tar.xz ${RELEASE} + + - name: Build and install + run: | + cd ${RELEASE} + + # configure using required scallop options + ./configure-scallop + + # build static and shared libraries + make -j libscallop.a libscallop.so + + # install shared library and headers + sudo make install-library install-headers + + - name: Test + run: | + # verify shared library is installed and pkg-config works as expected + pkg-config --modversion scallop + pkg-config --exact-version ${VERSION} scallop + + - name: Upload artifact + uses: actions/upload-artifact@v7 + with: + name: source + path: ./*.tar.xz + if-no-files-found: error + retention-days: 3 + + publish: + if: startsWith(github.ref, 'refs/tags/') + needs: source + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Download artifacts + uses: actions/download-artifact@v8 + with: + path: artifacts + merge-multiple: true + + - name: Create GitHub release + uses: softprops/action-gh-release@v2 + with: + files: artifacts/*.tar.xz + fail_on_unmatched_files: true From 26d72ac2e034c310f7e5acd1fa0908b9830269ab Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sat, 6 Dec 2025 15:28:12 -0700 Subject: [PATCH 32/37] ci: add test workflow --- .github/workflows/test.yml | 57 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..c60d54f4 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,57 @@ +name: test + +on: + push: + branches: '**' + workflow_dispatch: + +jobs: + version: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Get the package version + id: version + run: | + version=$(sed -rn "/^PACKAGE_VERSION=/ s/^.*='(.*)'/\1/p" configure) + date=${version##*.} + expected_date=$(date -u +"%Y%m%d") + + # verify patch date + if [[ ${date} != ${expected_date} ]]; then + echo outdated scallop patch date: ${date} + exit 1 + fi + + echo "version=${version}" >> $GITHUB_OUTPUT + + test: + needs: version + runs-on: ubuntu-latest + env: + VERSION: ${{ needs.version.outputs.version }} + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Build and install + run: | + # configure using required scallop options + ./configure-scallop + + # build static and shared libraries + make -j libscallop.a libscallop.so + + # install shared library and headers + sudo make install-library install-headers + + - name: Test + run: | + # verify shared library is installed and pkg-config works as expected + pkg-config --modversion scallop + pkg-config --exact-version ${VERSION} scallop From 1d35becda1389e3ddc2d79e24f42110aa8505a99 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sat, 6 Dec 2025 19:43:24 -0700 Subject: [PATCH 33/37] readme: add initial pkgcraft-related info --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..dd0f7033 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +[![ci](https://github.com/pkgcraft/bash/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/pkgcraft/bash/actions/workflows/test.yml) + +# bash + +Forked version of bash supporting shell interactions (e.g. writing builtins or +modifying variables, arrays, and functions) natively in rust via the scallop crate. + +## Development + +Note that the development workflow involves rebasing against upstream and force +pushing to keep the patch stack in order. From cb98247f50331d46a941369d2f4f17a1e541440a Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sun, 7 Dec 2025 01:16:31 -0700 Subject: [PATCH 34/37] shopt: don't copy option names for get_shopt_options() This makes the option name handling match get_minus_o_opts() in the `set` builtin and is what the the only usage for get_shopt_options() in pcomplete.c expects as it explicitly doesn't free the list members the same as it does for the set options list. --- builtins/shopt.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtins/shopt.def b/builtins/shopt.def index cf6f6be1..3c1946c5 100644 --- a/builtins/shopt.def +++ b/builtins/shopt.def @@ -777,7 +777,7 @@ get_shopt_options (void) n = sizeof (shopt_vars) / sizeof (shopt_vars[0]); ret = strvec_create (n + 1); for (i = 0; shopt_vars[i].name; i++) - ret[i] = savestring (shopt_vars[i].name); + ret[i] = shopt_vars[i].name; ret[i] = (char *)NULL; return ret; } From b091e474227935050b1a3995c152e6874c231124 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sun, 7 Dec 2025 05:16:14 -0700 Subject: [PATCH 35/37] make `enable` builtin use register_builtins() --- builtins/common.c | 6 +----- builtins/common.h | 2 +- builtins/enable.def | 24 +----------------------- 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/builtins/common.c b/builtins/common.c index 6b36af44..af66091d 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -1099,10 +1099,7 @@ set_expand_once (int nval, int uwp) } #endif -#if defined (BUILD_LIBRARY) -/* Register a given array of new builtins into the internal list. - * (Mostly copied from the enable builtin used when loading dynamic builtins.) - */ +/* Register a given array of new builtins into the internal list. */ int register_builtins (struct builtin **new_builtins, size_t num_new_builtins) { @@ -1133,4 +1130,3 @@ register_builtins (struct builtin **new_builtins, size_t num_new_builtins) return (EXECUTION_SUCCESS); } -#endif diff --git a/builtins/common.h b/builtins/common.h index d398ee56..d21eee5f 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -91,7 +91,6 @@ extern int no_options (WORD_LIST *); #if defined (BUILD_LIBRARY) /* scallop extensions */ -extern int register_builtins (struct builtin **, size_t); extern int scallop_source_file (const char *); extern int scallop_evalstring (const char *, int); #endif @@ -149,6 +148,7 @@ extern sh_builtin_func_t *find_shell_builtin (const char *); extern sh_builtin_func_t *builtin_address (const char *); extern sh_builtin_func_t *find_special_builtin (const char *); extern void initialize_shell_builtins (void); +extern int register_builtins (struct builtin **, size_t); #if defined (ARRAY_VARS) extern int set_expand_once (int, int); diff --git a/builtins/enable.def b/builtins/enable.def index 72da559c..ed6fc787 100644 --- a/builtins/enable.def +++ b/builtins/enable.def @@ -472,29 +472,7 @@ dyn_load_builtin (WORD_LIST *list, int flags, char *filename) } if (new) - { - total = num_shell_builtins + new; - size = (total + 1) * sizeof (struct builtin); - - new_shell_builtins = (struct builtin *)xmalloc (size); - FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins, - num_shell_builtins * sizeof (struct builtin)); - for (replaced = 0; replaced < new; replaced++) - FASTCOPY ((char *)new_builtins[replaced], - (char *)&new_shell_builtins[num_shell_builtins + replaced], - sizeof (struct builtin)); - - new_shell_builtins[total].name = (char *)0; - new_shell_builtins[total].function = (sh_builtin_func_t *)0; - new_shell_builtins[total].flags = 0; - - if (shell_builtins != static_shell_builtins) - free (shell_builtins); - - shell_builtins = new_shell_builtins; - num_shell_builtins = total; - initialize_shell_builtins (); - } + register_builtins(new_builtins, new); free (new_builtins); return (EXECUTION_SUCCESS); From 745a583cd0aad1579c7bc7f3101fcd74d3d09467 Mon Sep 17 00:00:00 2001 From: Tim Harder Date: Sun, 7 Dec 2025 14:12:42 -0700 Subject: [PATCH 36/37] execute_cmd.h: externally export `the_printed_command` global variable --- execute_cmd.h | 1 + 1 file changed, 1 insertion(+) diff --git a/execute_cmd.h b/execute_cmd.h index a28bab9f..e73326a4 100644 --- a/execute_cmd.h +++ b/execute_cmd.h @@ -62,6 +62,7 @@ extern int sourcenest, sourcenest_max; extern int stdin_redir; extern int line_number_for_err_trap; +extern char *the_printed_command; extern char *the_printed_command_except_trap; extern COMMAND *currently_executing_command; From 3cefe392d7ba7f49fdacf5feef030edb5dc39f6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 23:53:59 +0000 Subject: [PATCH 37/37] Bump softprops/action-gh-release from 2 to 3 Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2...v3) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a6bbbaa6..10e0ef77 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -102,7 +102,7 @@ jobs: merge-multiple: true - name: Create GitHub release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: files: artifacts/*.tar.xz fail_on_unmatched_files: true