]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20041007 snapshot
authorChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 18:37:49 +0000 (13:37 -0500)
committerChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 18:37:49 +0000 (13:37 -0500)
26 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
MANIFEST
aclocal.m4
aclocal.m4~
autom4te.cache/output.0
autom4te.cache/requests
autom4te.cache/traces.0
config.h.in
configure
configure.in
configure.in~
doc/bash.1
doc/bash.1~
doc/bashref.texi
doc/bashref.texi~
doc/version.texi
doc/version.texi~
execute_cmd.c~
input.c~ [new file with mode: 0644]
redir.c
redir.c~ [new file with mode: 0644]
subst.c
support/shobj-conf
tests/RUN-ONE-TEST
tests/run-tilde

index 5f7aeddfdb40d46a92a074433bfdb395090e1ba1..566fd9f414cfef3e2522138b19f30689fd52b556 100644 (file)
@@ -10281,3 +10281,40 @@ lib/readline/complete.c
 subst.c
        - use W_COMPASSIGN flag in do_assignment_internal instead of deciding
          lexically which assignments are compound array assignments
+
+                                  10/6
+                                  ----
+support/shobj-conf
+       - additions for System V.5 from Boyd Gerber <gerberb@zenez.com>
+
+subst.c
+       - in command_substitute, if subshell_environment includes
+         SUBSHELL_ASYNC, call make_child with the `async_p' argument set to
+         non-zero.  This keeps command substitutions for async commands or
+         pipelines from trying to give the terminal back to the shell's
+         pgrp.  make sure to save and restore last_asynchronous_pid.  Fix
+         suggested by <pierre.humblet@ieee.org>
+
+                                  10/7
+                                  ----
+config.h.in
+       - add a placeholder definition for WCONTINUED_BROKEN
+
+                                  10/9
+                                  ----
+aclocal.m4
+       - add BASH_CHECK_WCONTINUED, checks for glibc bug where WCONTINUED is
+         defined but rejected as invalid by waitpid(2)
+
+configure.in
+       - add call to BASH_CHECK_WCONTINUED, defines WCONTINUED_BROKEN
+
+redir.c
+       - experimental change to add_undo_redirect to save manipulations to
+         file descriptors >= SHELL_FD_BASE (10) on the list of redirections
+         to be undone even if `exec' causes the list to be discarded
+
+doc/{bash.1,bashref.texi}
+       - note that redirections using file descriptors > 9 should be used
+         carefully, because they might conflict with file descriptors the
+         shell uses internally
index 17f6c575d3228c45c450aafe32092618392f30fe..ed0deeef16e574f4ad376ea2f6487f77619d7b32 100644 (file)
@@ -10275,3 +10275,41 @@ doc/{bash.1,bashref.texi}
 lib/readline/complete.c
        - fixed rl_menu_complete so that a negative argument cycles backwards
          through the list
+
+                                  10/3
+                                  ----
+subst.c
+       - use W_COMPASSIGN flag in do_assignment_internal instead of deciding
+         lexically which assignments are compound array assignments
+
+                                  10/6
+                                  ----
+support/shobj-conf
+       - additions for System V.5 from Boyd Gerber <gerberb@zenez.com>
+
+subst.c
+       - in command_substitute, if subshell_environment includes
+         SUBSHELL_ASYNC, call make_child with the `async_p' argument set to
+         non-zero.  This keeps command substitutions for async commands or
+         pipelines from trying to give the terminal back to the shell's
+         pgrp.  make sure to save and restore last_asynchronous_pid.  Fix
+         suggested by <pierre.humblet@ieee.org>
+
+                                  10/7
+                                  ----
+config.h.in
+       - add a placeholder definition for WCONTINUED_BROKEN
+
+                                  10/9
+                                  ----
+aclocal.m4
+       - add BASH_CHECK_WCONTINUED, checks for glibc bug where WCONTINUED is
+         defined but rejected as invalid by waitpid(2)
+
+configure.in
+       - add call to BASH_CHECK_WCONTINUED, defines WCONTINUED_BROKEN
+
+redir.c
+       - experimental change to add_undo_redirect to save manipulations to
+         file descriptors >= SHELL_FD_BASE (10) on the list of redirections
+         to be undone even if `exec' causes the list to be discarded
index 398d522df6bfff5ad666e876e96cdf8a2426479c..2985f5402517bc3e6754aa7619f71b9bee23a27d 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -731,6 +731,8 @@ tests/extglob.tests f
 tests/extglob.right    f
 tests/extglob2.tests   f
 tests/extglob2.right   f
+tests/extglob3.tests   f
+tests/extglob3.right   f
 tests/func.tests       f
 tests/func.right       f
 tests/func1.sub                f
@@ -840,6 +842,7 @@ tests/run-execscript        f
 tests/run-exp-tests    f
 tests/run-extglob      f
 tests/run-extglob2     f
+tests/run-extglob3     f
 tests/run-func         f
 tests/run-getopts      f
 tests/run-glob-test    f
@@ -873,6 +876,7 @@ tests/run-shopt             f
 tests/run-strip                f
 tests/run-test         f
 tests/run-tilde                f
+tests/run-tilde2       f
 tests/run-trap         f
 tests/run-type         f
 tests/run-varenv       f
@@ -886,8 +890,10 @@ tests/strip.tests  f
 tests/strip.right      f
 tests/test.tests       f
 tests/test.right       f
-tests/tilde-tests      f
+tests/tilde.tests      f
 tests/tilde.right      f
+tests/tilde2.tests     f
+tests/tilde2.right     f
 tests/trap.tests       f
 tests/trap.right       f
 tests/trap1.sub                f       755
index 30d9b81312bd6dbb1950b0701833d244221dd216..bfcd5970cadc5ec360eed58b703edde3504830f8 100644 (file)
@@ -1859,6 +1859,39 @@ AC_DEFINE(CTYPE_NON_ASCII)
 fi
 ])
 
+AC_DEFUN(BASH_CHECK_WCONTINUED,
+[
+AC_MSG_CHECKING(whether WCONTINUED flag to waitpid is unavailable or available but broken)
+AC_CACHE_VAL(bash_cv_wcontinued_broken,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+main()
+{
+       int     x;
+
+       x = waitpid(-1, (int *)0, WNOHANG|WCONTINUED);
+       if (x == -1 && errno == EINVAL)
+               exit (1);
+       else
+               exit (0);
+}
+], bash_cv_wcontinued_broken=no,bash_cv_wcontinued_broken=yes,
+   [AC_MSG_WARN(cannot check WCONTINUED if cross compiling -- defaulting to no)
+    bash_cv_wcontinued_broken=no]
+)])
+AC_MSG_RESULT($bash_cv_wcontinued_broken)
+if test $bash_cv_wcontinued_broken = yes; then
+AC_DEFINE(WCONTINUED_BROKEN)
+fi
+])
+
 dnl
 dnl tests added for bashdb
 dnl
index 9d2ed54420cca39631f7f76f11cb5524378fecec..8ca5329826b3761ceee74c5f82d460ecda1d5e92 100644 (file)
@@ -1541,7 +1541,14 @@ AC_DEFUN(BASH_CHECK_DEV_FD,
 [AC_MSG_CHECKING(whether /dev/fd is available)
 AC_CACHE_VAL(bash_cv_dev_fd,
 [if test -d /dev/fd  && test -r /dev/fd/0 < /dev/null; then
-   bash_cv_dev_fd=standard
+# check for systems like FreeBSD 5 that only provide /dev/fd/[012]
+   exec 3<&0
+   if test -r /dev/fd/3; then
+     bash_cv_dev_fd=standard
+   else
+     bash_cv_dev_fd=absent
+   fi
+   exec 3<&-
  elif test -d /proc/self/fd && test -r /proc/self/fd/0 < /dev/null; then
    bash_cv_dev_fd=whacky
  else
@@ -1852,6 +1859,39 @@ AC_DEFINE(CTYPE_NON_ASCII)
 fi
 ])
 
+AC_DEFUN(BASH_CHECK_WCONTINUED,
+[
+AC_MSG_CHECKING(whether WCONTINUED flag to waitpid is unavailable or available but broken)
+AC_CACHE_VAL(bash_cv_wcontinued_broken,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+main()
+{
+       int     x;
+
+       x = waitpid(-1, (int *)0, WNOHANG|WCONTINUED);
+       if (x == -1 && errno == EINVAL)
+               exit (1);
+       else
+               exit (0);
+}
+], bash_cv_wcontinued_broken=no,bash_cv_wcontined_broken=yes,
+   [AC_MSG_WARN(cannot check WCONTINUED if cross compiling -- defaulting to no)
+    bash_cv_wcontinued_broken=no]
+)])
+AC_MSG_RESULT($bash_cv_wcontinued_broken)
+if test $bash_cv_wcontinued_broken = yes; then
+AC_DEFINE(WCONTINUED_BROKEN)
+fi
+])
+
 dnl
 dnl tests added for bashdb
 dnl
index fa2b495fa36338312b98067d660335016a8a54dd..798e4cc07c2570f4af24f76b3816ff315ae57d5c 100644 (file)
@@ -1,5 +1,5 @@
 @%:@! /bin/sh
-@%:@ From configure.in for Bash 3.0, version 3.169, from autoconf version AC_ACVERSION.
+@%:@ From configure.in for Bash 3.0, version 3.170, from autoconf version AC_ACVERSION.
 @%:@ Guess values for system-dependent variables and create Makefiles.
 @%:@ Generated by GNU Autoconf 2.57 for bash 3.1-devel.
 @%:@
@@ -23202,6 +23202,80 @@ _ACEOF
 fi
 
 
+
+echo "$as_me:$LINENO: checking whether WCONTINUED flag to waitpid is unavailable or available but broken" >&5
+echo $ECHO_N "checking whether WCONTINUED flag to waitpid is unavailable or available but broken... $ECHO_C" >&6
+if test "${bash_cv_wcontinued_broken+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  { echo "$as_me:$LINENO: WARNING: cannot check WCONTINUED if cross compiling -- defaulting to no" >&5
+echo "$as_me: WARNING: cannot check WCONTINUED if cross compiling -- defaulting to no" >&2;}
+    bash_cv_wcontinued_broken=no
+
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+main()
+{
+       int     x;
+
+       x = waitpid(-1, (int *)0, WNOHANG|WCONTINUED);
+       if (x == -1 && errno == EINVAL)
+               exit (1);
+       else
+               exit (0);
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  bash_cv_wcontinued_broken=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+bash_cv_wcontinued_broken=yes
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+
+echo "$as_me:$LINENO: result: $bash_cv_wcontinued_broken" >&5
+echo "${ECHO_T}$bash_cv_wcontinued_broken" >&6
+if test $bash_cv_wcontinued_broken = yes; then
+cat >>confdefs.h <<\_ACEOF
+@%:@define WCONTINUED_BROKEN 1
+_ACEOF
+
+fi
+
+
 echo "$as_me:$LINENO: checking for speed_t in sys/types.h" >&5
 echo $ECHO_N "checking for speed_t in sys/types.h... $ECHO_C" >&6
 if test "${bash_cv_speed_t_in_sys_types+set}" = set; then
index 6ac24b719702a231b320d3897b2ddf3f06819b4b..462f649d8f856487bb62c0699a2b7a4a79826499 100644 (file)
                         'configure.in'
                       ],
                       {
-                        'AC_HEADER_MAJOR' => 1,
-                        'AC_FUNC_GETPGRP' => 1,
-                        'AC_CONFIG_SUBDIRS' => 1,
-                        'AC_HEADER_STAT' => 1,
+                        'AC_CONFIG_FILES' => 1,
+                        'AC_HEADER_TIME' => 1,
+                        'AC_PROG_CPP' => 1,
+                        'AC_FUNC_REALLOC' => 1,
+                        'AC_C_CONST' => 1,
+                        'AC_C_VOLATILE' => 1,
+                        'AC_STRUCT_TIMEZONE' => 1,
+                        'AC_SUBST' => 1,
+                        'AC_TYPE_SIGNAL' => 1,
+                        'AC_CHECK_MEMBERS' => 1,
+                        'AC_TYPE_SIZE_T' => 1,
+                        'AC_FUNC_SETPGRP' => 1,
+                        'AC_TYPE_OFF_T' => 1,
+                        'AC_FUNC_GETMNTENT' => 1,
                         'AC_FUNC_LSTAT' => 1,
-                        'AC_HEADER_DIRENT' => 1,
-                        'AC_FUNC_STAT' => 1,
-                        'AC_FUNC_SELECT_ARGTYPES' => 1,
-                        'AC_FUNC_CHOWN' => 1,
-                        'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1,
-                        'AC_STRUCT_ST_BLOCKS' => 1,
-                        'AC_TYPE_PID_T' => 1,
-                        'AC_FUNC_STRERROR_R' => 1,
-                        'AC_FUNC_VPRINTF' => 1,
-                        'AH_OUTPUT' => 1,
-                        'm4_pattern_allow' => 1,
+                        'AC_FUNC_GETGROUPS' => 1,
                         'AC_CONFIG_HEADERS' => 1,
+                        'AC_FUNC_SELECT_ARGTYPES' => 1,
+                        'AC_PROG_CC' => 1,
+                        'AM_CONDITIONAL' => 1,
+                        'AC_REPLACE_FNMATCH' => 1,
                         'AC_FUNC_MEMCMP' => 1,
-                        'AC_HEADER_STDC' => 1,
-                        'AC_CHECK_HEADERS' => 1,
-                        'AC_FUNC_CLOSEDIR_VOID' => 1,
-                        'm4_include' => 1,
+                        'AC_FUNC_STRTOD' => 1,
                         'AM_AUTOMAKE_VERSION' => 1,
+                        'AC_TYPE_UID_T' => 1,
+                        'AC_FUNC_STRERROR_R' => 1,
+                        'AC_PROG_YACC' => 1,
                         'AC_CONFIG_AUX_DIR' => 1,
-                        'AC_FUNC_MALLOC' => 1,
-                        'AC_DECL_SYS_SIGLIST' => 1,
-                        'AC_C_CONST' => 1,
-                        'AC_FUNC_SETPGRP' => 1,
-                        'AC_CANONICAL_SYSTEM' => 1,
-                        'AC_C_VOLATILE' => 1,
-                        'AC_FUNC_FSEEKO' => 1,
-                        'AC_FUNC_MBRTOWC' => 1,
+                        'AC_FUNC_OBSTACK' => 1,
+                        'AC_HEADER_STAT' => 1,
+                        'AC_FUNC_CLOSEDIR_VOID' => 1,
+                        'AC_PROG_CXX' => 1,
                         'AC_STRUCT_TM' => 1,
-                        'AC_FUNC_STRCOLL' => 1,
-                        'AC_HEADER_SYS_WAIT' => 1,
+                        'AC_FUNC_STRFTIME' => 1,
+                        'AC_FUNC_UTIME_NULL' => 1,
                         'AC_PROG_LIBTOOL' => 1,
-                        'AC_CHECK_TYPES' => 1,
-                        'AC_CONFIG_FILES' => 1,
-                        'AC_CHECK_LIB' => 1,
-                        'include' => 1,
-                        'AC_FUNC_GETGROUPS' => 1,
-                        'AC_PATH_X' => 1,
-                        'AC_PROG_CC' => 1,
-                        'AC_FUNC_GETLOADAVG' => 1,
-                        'AC_HEADER_TIME' => 1,
-                        'AC_REPLACE_FNMATCH' => 1,
-                        'AC_LIBSOURCE' => 1,
-                        'AC_PROG_LN_S' => 1,
-                        'AC_FUNC_OBSTACK' => 1,
-                        'AC_PROG_LEX' => 1,
-                        'AC_FUNC_STRTOD' => 1,
-                        'AC_TYPE_MODE_T' => 1,
-                        'AC_CHECK_MEMBERS' => 1,
-                        'AC_FUNC_ERROR_AT_LINE' => 1,
-                        'AM_CONDITIONAL' => 1,
-                        'AC_STRUCT_TIMEZONE' => 1,
-                        'AC_FUNC_REALLOC' => 1,
-                        'AM_PROG_CC_C_O' => 1,
+                        'AC_FUNC_FSEEKO' => 1,
                         'AM_GNU_GETTEXT' => 1,
-                        'AC_PROG_MAKE_SET' => 1,
-                        'AC_FUNC_UTIME_NULL' => 1,
-                        'AC_PROG_CXX' => 1,
-                        'AC_FUNC_MMAP' => 1,
-                        'AC_PROG_GCC_TRADITIONAL' => 1,
-                        'AC_DEFINE_TRACE_LITERAL' => 1,
-                        'AC_PROG_AWK' => 1,
+                        'AC_PROG_RANLIB' => 1,
                         'AC_FUNC_FORK' => 1,
-                        'AC_FUNC_ALLOCA' => 1,
+                        'AC_FUNC_MALLOC' => 1,
                         'AC_FUNC_SETVBUF_REVERSED' => 1,
-                        'AC_TYPE_OFF_T' => 1,
-                        'AC_PROG_RANLIB' => 1,
-                        'AC_TYPE_SIGNAL' => 1,
-                        'AC_PROG_CPP' => 1,
-                        'AC_C_INLINE' => 1,
+                        'AC_TYPE_PID_T' => 1,
+                        'AC_PROG_GCC_TRADITIONAL' => 1,
+                        'AC_PROG_LEX' => 1,
+                        'AC_FUNC_STRCOLL' => 1,
+                        'AC_PATH_X' => 1,
                         'AM_INIT_AUTOMAKE' => 1,
-                        'AC_TYPE_UID_T' => 1,
-                        'AC_PROG_YACC' => 1,
-                        'AC_FUNC_STRNLEN' => 1,
-                        'AC_PROG_INSTALL' => 1,
-                        'AC_FUNC_WAIT3' => 1,
+                        'AC_CHECK_TYPES' => 1,
+                        'AC_FUNC_GETLOADAVG' => 1,
+                        'include' => 1,
+                        'AC_LIBSOURCE' => 1,
                         'AC_CHECK_FUNCS' => 1,
-                        'AM_MAINTAINER_MODE' => 1,
-                        'AC_CANONICAL_HOST' => 1,
-                        'AC_FUNC_STRFTIME' => 1,
+                        'm4_include' => 1,
                         'AC_FUNC_MKTIME' => 1,
-                        'AC_SUBST' => 1,
-                        'AC_TYPE_SIZE_T' => 1,
+                        'AC_FUNC_STAT' => 1,
+                        'AC_FUNC_CHOWN' => 1,
+                        'AC_HEADER_DIRENT' => 1,
+                        'AC_FUNC_STRNLEN' => 1,
+                        'AM_MAINTAINER_MODE' => 1,
+                        'AC_FUNC_WAIT3' => 1,
+                        'AC_PROG_LN_S' => 1,
+                        'AC_PROG_INSTALL' => 1,
+                        'm4_pattern_allow' => 1,
+                        'AC_FUNC_GETPGRP' => 1,
+                        'AC_PROG_AWK' => 1,
                         'AC_INIT' => 1,
-                        'AC_FUNC_GETMNTENT' => 1,
-                        'm4_pattern_forbid' => 1
+                        'AC_DEFINE_TRACE_LITERAL' => 1,
+                        'AC_CHECK_LIB' => 1,
+                        'AC_HEADER_MAJOR' => 1,
+                        'AC_FUNC_MBRTOWC' => 1,
+                        'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1,
+                        'AC_FUNC_MMAP' => 1,
+                        'AC_CANONICAL_HOST' => 1,
+                        'AC_CONFIG_SUBDIRS' => 1,
+                        'AC_DECL_SYS_SIGLIST' => 1,
+                        'AC_HEADER_SYS_WAIT' => 1,
+                        'AC_C_INLINE' => 1,
+                        'AC_STRUCT_ST_BLOCKS' => 1,
+                        'AC_FUNC_ALLOCA' => 1,
+                        'AM_PROG_CC_C_O' => 1,
+                        'AC_CANONICAL_SYSTEM' => 1,
+                        'AC_FUNC_VPRINTF' => 1,
+                        'AC_FUNC_ERROR_AT_LINE' => 1,
+                        'AH_OUTPUT' => 1,
+                        'AC_TYPE_MODE_T' => 1,
+                        'AC_PROG_MAKE_SET' => 1,
+                        'm4_pattern_forbid' => 1,
+                        'AC_HEADER_STDC' => 1,
+                        'AC_CHECK_HEADERS' => 1
                       }
                     ], 'Request' )
            );
index 2aa1b3fabe8bfae255d12b3e1a6f500518b2d375..9d125d4a9be8cda90e07a65ac4bda34ec74a35a9 100644 (file)
@@ -1122,64 +1122,65 @@ m4trace:configure.in:859: -1- AH_OUTPUT([GWINSZ_IN_SYS_IOCTL], [/* Define to 1 i
 #undef GWINSZ_IN_SYS_IOCTL])
 m4trace:configure.in:860: -1- AC_DEFINE_TRACE_LITERAL([TIOCSTAT_IN_SYS_IOCTL])
 m4trace:configure.in:861: -1- AC_DEFINE_TRACE_LITERAL([FIONREAD_IN_SYS_IOCTL])
-m4trace:configure.in:864: -1- AC_DEFINE_TRACE_LITERAL([SPEED_T_IN_SYS_TYPES])
-m4trace:configure.in:865: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETPW_DECLS])
-m4trace:configure.in:866: -1- AC_DEFINE_TRACE_LITERAL([UNUSABLE_RT_SIGNALS])
-m4trace:configure.in:867: -1- AC_SUBST([SIGLIST_O])
-m4trace:configure.in:871: -1- AC_DEFINE_TRACE_LITERAL([RLIMIT_NEEDS_KERNEL])
-m4trace:configure.in:879: -1- AC_CHECK_LIB([termcap], [tgetent], [bash_cv_termcap_lib=libtermcap], [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
+m4trace:configure.in:863: -1- AC_DEFINE_TRACE_LITERAL([WCONTINUED_BROKEN])
+m4trace:configure.in:866: -1- AC_DEFINE_TRACE_LITERAL([SPEED_T_IN_SYS_TYPES])
+m4trace:configure.in:867: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETPW_DECLS])
+m4trace:configure.in:868: -1- AC_DEFINE_TRACE_LITERAL([UNUSABLE_RT_SIGNALS])
+m4trace:configure.in:869: -1- AC_SUBST([SIGLIST_O])
+m4trace:configure.in:873: -1- AC_DEFINE_TRACE_LITERAL([RLIMIT_NEEDS_KERNEL])
+m4trace:configure.in:881: -1- AC_CHECK_LIB([termcap], [tgetent], [bash_cv_termcap_lib=libtermcap], [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
         [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
            [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
                bash_cv_termcap_lib=gnutermcap)])])])
-m4trace:configure.in:879: -1- AC_CHECK_LIB([tinfo], [tgetent], [bash_cv_termcap_lib=libtinfo], [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
+m4trace:configure.in:881: -1- AC_CHECK_LIB([tinfo], [tgetent], [bash_cv_termcap_lib=libtinfo], [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
            [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
                bash_cv_termcap_lib=gnutermcap)])])
-m4trace:configure.in:879: -1- AC_CHECK_LIB([curses], [tgetent], [bash_cv_termcap_lib=libcurses], [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
+m4trace:configure.in:881: -1- AC_CHECK_LIB([curses], [tgetent], [bash_cv_termcap_lib=libcurses], [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
                bash_cv_termcap_lib=gnutermcap)])
-m4trace:configure.in:879: -1- AC_CHECK_LIB([ncurses], [tgetent], [bash_cv_termcap_lib=libncurses], [bash_cv_termcap_lib=gnutermcap])
-m4trace:configure.in:881: -1- AC_SUBST([TERMCAP_LIB])
-m4trace:configure.in:882: -1- AC_SUBST([TERMCAP_DEP])
-m4trace:configure.in:884: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_FD])
-m4trace:configure.in:884: -1- AC_DEFINE_TRACE_LITERAL([DEV_FD_PREFIX])
-m4trace:configure.in:884: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_FD])
-m4trace:configure.in:884: -1- AC_DEFINE_TRACE_LITERAL([DEV_FD_PREFIX])
-m4trace:configure.in:885: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_STDIN])
-m4trace:configure.in:886: -1- AC_DEFINE_TRACE_LITERAL([DEFAULT_MAIL_DIRECTORY])
-m4trace:configure.in:893: -1- AC_DEFINE_TRACE_LITERAL([JOB_CONTROL])
-m4trace:configure.in:899: -1- AC_SUBST([JOBS_O])
-m4trace:configure.in:912: -1- AC_DEFINE_TRACE_LITERAL([SVR4_2])
-m4trace:configure.in:913: -1- AC_DEFINE_TRACE_LITERAL([SVR4])
-m4trace:configure.in:914: -1- AC_DEFINE_TRACE_LITERAL([SVR4])
-m4trace:configure.in:915: -1- AC_DEFINE_TRACE_LITERAL([SVR5])
-m4trace:configure.in:972: -1- AC_SUBST([SHOBJ_CC])
-m4trace:configure.in:973: -1- AC_SUBST([SHOBJ_CFLAGS])
-m4trace:configure.in:974: -1- AC_SUBST([SHOBJ_LD])
-m4trace:configure.in:975: -1- AC_SUBST([SHOBJ_LDFLAGS])
-m4trace:configure.in:976: -1- AC_SUBST([SHOBJ_XLDFLAGS])
-m4trace:configure.in:977: -1- AC_SUBST([SHOBJ_LIBS])
-m4trace:configure.in:978: -1- AC_SUBST([SHOBJ_STATUS])
-m4trace:configure.in:999: -1- AC_SUBST([PROFILE_FLAGS])
-m4trace:configure.in:1001: -1- AC_SUBST([incdir])
-m4trace:configure.in:1002: -1- AC_SUBST([BUILD_DIR])
-m4trace:configure.in:1004: -1- AC_SUBST([YACC])
-m4trace:configure.in:1005: -1- AC_SUBST([AR])
-m4trace:configure.in:1006: -1- AC_SUBST([ARFLAGS])
-m4trace:configure.in:1008: -1- AC_SUBST([BASHVERS])
-m4trace:configure.in:1009: -1- AC_SUBST([RELSTATUS])
-m4trace:configure.in:1010: -1- AC_SUBST([DEBUG])
-m4trace:configure.in:1011: -1- AC_SUBST([MALLOC_DEBUG])
-m4trace:configure.in:1013: -1- AC_SUBST([host_cpu])
-m4trace:configure.in:1014: -1- AC_SUBST([host_vendor])
-m4trace:configure.in:1015: -1- AC_SUBST([host_os])
-m4trace:configure.in:1017: -1- AC_SUBST([LOCAL_LIBS])
-m4trace:configure.in:1018: -1- AC_SUBST([LOCAL_CFLAGS])
-m4trace:configure.in:1019: -1- AC_SUBST([LOCAL_LDFLAGS])
-m4trace:configure.in:1020: -1- AC_SUBST([LOCAL_DEFS])
-m4trace:configure.in:1034: -1- AC_CONFIG_FILES([Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \
+m4trace:configure.in:881: -1- AC_CHECK_LIB([ncurses], [tgetent], [bash_cv_termcap_lib=libncurses], [bash_cv_termcap_lib=gnutermcap])
+m4trace:configure.in:883: -1- AC_SUBST([TERMCAP_LIB])
+m4trace:configure.in:884: -1- AC_SUBST([TERMCAP_DEP])
+m4trace:configure.in:886: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_FD])
+m4trace:configure.in:886: -1- AC_DEFINE_TRACE_LITERAL([DEV_FD_PREFIX])
+m4trace:configure.in:886: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_FD])
+m4trace:configure.in:886: -1- AC_DEFINE_TRACE_LITERAL([DEV_FD_PREFIX])
+m4trace:configure.in:887: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_STDIN])
+m4trace:configure.in:888: -1- AC_DEFINE_TRACE_LITERAL([DEFAULT_MAIL_DIRECTORY])
+m4trace:configure.in:895: -1- AC_DEFINE_TRACE_LITERAL([JOB_CONTROL])
+m4trace:configure.in:901: -1- AC_SUBST([JOBS_O])
+m4trace:configure.in:914: -1- AC_DEFINE_TRACE_LITERAL([SVR4_2])
+m4trace:configure.in:915: -1- AC_DEFINE_TRACE_LITERAL([SVR4])
+m4trace:configure.in:916: -1- AC_DEFINE_TRACE_LITERAL([SVR4])
+m4trace:configure.in:917: -1- AC_DEFINE_TRACE_LITERAL([SVR5])
+m4trace:configure.in:974: -1- AC_SUBST([SHOBJ_CC])
+m4trace:configure.in:975: -1- AC_SUBST([SHOBJ_CFLAGS])
+m4trace:configure.in:976: -1- AC_SUBST([SHOBJ_LD])
+m4trace:configure.in:977: -1- AC_SUBST([SHOBJ_LDFLAGS])
+m4trace:configure.in:978: -1- AC_SUBST([SHOBJ_XLDFLAGS])
+m4trace:configure.in:979: -1- AC_SUBST([SHOBJ_LIBS])
+m4trace:configure.in:980: -1- AC_SUBST([SHOBJ_STATUS])
+m4trace:configure.in:1001: -1- AC_SUBST([PROFILE_FLAGS])
+m4trace:configure.in:1003: -1- AC_SUBST([incdir])
+m4trace:configure.in:1004: -1- AC_SUBST([BUILD_DIR])
+m4trace:configure.in:1006: -1- AC_SUBST([YACC])
+m4trace:configure.in:1007: -1- AC_SUBST([AR])
+m4trace:configure.in:1008: -1- AC_SUBST([ARFLAGS])
+m4trace:configure.in:1010: -1- AC_SUBST([BASHVERS])
+m4trace:configure.in:1011: -1- AC_SUBST([RELSTATUS])
+m4trace:configure.in:1012: -1- AC_SUBST([DEBUG])
+m4trace:configure.in:1013: -1- AC_SUBST([MALLOC_DEBUG])
+m4trace:configure.in:1015: -1- AC_SUBST([host_cpu])
+m4trace:configure.in:1016: -1- AC_SUBST([host_vendor])
+m4trace:configure.in:1017: -1- AC_SUBST([host_os])
+m4trace:configure.in:1019: -1- AC_SUBST([LOCAL_LIBS])
+m4trace:configure.in:1020: -1- AC_SUBST([LOCAL_CFLAGS])
+m4trace:configure.in:1021: -1- AC_SUBST([LOCAL_LDFLAGS])
+m4trace:configure.in:1022: -1- AC_SUBST([LOCAL_DEFS])
+m4trace:configure.in:1036: -1- 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/perl/Makefile \
          pathnames.h])
-m4trace:configure.in:1034: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
-m4trace:configure.in:1034: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
+m4trace:configure.in:1036: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
+m4trace:configure.in:1036: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
index 8e3e4569f588e63cd84998bfa769fb3c109f7ef9..3bfc4624c1f3e3e0c2e085af4ebdc6150b6c0096 100644 (file)
 
 #undef HAVE_LIBC_FNM_EXTMATCH
 
-
 #undef HAVE_DECL_CONFSTR
 
 #undef HAVE_DECL_PRINTF
 
 #undef HAVE_MBSTATE_T
 
+/* Define if WCONTINUED is defined in system headers, but rejected by waitpid */
+#undef WCONTINUED_BROKEN
+
 /* These are checked with BASH_CHECK_DECL */
 
 #undef HAVE_DECL_STRTOIMAX
index 5910defe62650d87b4636e5a960f12a9200d07c7..6b689cd27c609b84977b63827ee721582d501420 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in for Bash 3.0, version 3.169, from autoconf version AC_ACVERSION.
+# From configure.in for Bash 3.0, version 3.170, from autoconf version AC_ACVERSION.
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.57 for bash 3.1-devel.
 #
@@ -23202,6 +23202,80 @@ _ACEOF
 fi
 
 
+
+echo "$as_me:$LINENO: checking whether WCONTINUED flag to waitpid is unavailable or available but broken" >&5
+echo $ECHO_N "checking whether WCONTINUED flag to waitpid is unavailable or available but broken... $ECHO_C" >&6
+if test "${bash_cv_wcontinued_broken+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  { echo "$as_me:$LINENO: WARNING: cannot check WCONTINUED if cross compiling -- defaulting to no" >&5
+echo "$as_me: WARNING: cannot check WCONTINUED if cross compiling -- defaulting to no" >&2;}
+    bash_cv_wcontinued_broken=no
+
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+main()
+{
+       int     x;
+
+       x = waitpid(-1, (int *)0, WNOHANG|WCONTINUED);
+       if (x == -1 && errno == EINVAL)
+               exit (1);
+       else
+               exit (0);
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  bash_cv_wcontinued_broken=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+bash_cv_wcontinued_broken=yes
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+
+echo "$as_me:$LINENO: result: $bash_cv_wcontinued_broken" >&5
+echo "${ECHO_T}$bash_cv_wcontinued_broken" >&6
+if test $bash_cv_wcontinued_broken = yes; then
+cat >>confdefs.h <<\_ACEOF
+#define WCONTINUED_BROKEN 1
+_ACEOF
+
+fi
+
+
 echo "$as_me:$LINENO: checking for speed_t in sys/types.h" >&5
 echo $ECHO_N "checking for speed_t in sys/types.h... $ECHO_C" >&6
 if test "${bash_cv_speed_t_in_sys_types+set}" = set; then
index d1fc8048a24196ef7ac75a7facf82c35c0205515..19dfe611cd16d9df3b526b8b0d0a20874889a725 100644 (file)
@@ -22,7 +22,7 @@ dnl Process this file with autoconf to produce a configure script.
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 # 02111-1307, USA.
 
-AC_REVISION([for Bash 3.0, version 3.169, from autoconf version] AC_ACVERSION)dnl
+AC_REVISION([for Bash 3.0, version 3.170, from autoconf version] AC_ACVERSION)dnl
 
 define(bashvers, 3.1)
 define(relstatus, devel)
@@ -860,6 +860,8 @@ AC_HEADER_TIOCGWINSZ
 BASH_HAVE_TIOCSTAT
 BASH_HAVE_FIONREAD
 
+BASH_CHECK_WCONTINUED
+
 dnl miscellaneous
 BASH_CHECK_SPEED_T
 BASH_CHECK_GETPW_FUNCS
index 55c8a5c75551f161f96aae26695c7ea9ce04fa09..d1fc8048a24196ef7ac75a7facf82c35c0205515 100644 (file)
@@ -22,10 +22,10 @@ dnl Process this file with autoconf to produce a configure script.
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 # 02111-1307, USA.
 
-AC_REVISION([for Bash 3.0, version 3.168, from autoconf version] AC_ACVERSION)dnl
+AC_REVISION([for Bash 3.0, version 3.169, from autoconf version] AC_ACVERSION)dnl
 
-define(bashvers, 3.0)
-define(relstatus, release)
+define(bashvers, 3.1)
+define(relstatus, devel)
 
 AC_INIT(bash, bashvers-relstatus, bug-bash@gnu.org)
 
@@ -646,7 +646,7 @@ AC_CHECK_FUNCS(bcopy bzero confstr sysconf pathconf setenv putenv unsetenv \
                getaddrinfo gethostbyname getservbyname getservent inet_aton \
                vsnprintf snprintf vasprintf asprintf fnmatch regcomp regexec)
 AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit)
-AC_REPLACE_FUNCS(getcwd strcasecmp strerror strftime strpbrk memset strstr)
+AC_REPLACE_FUNCS(getcwd strcasecmp strerror strftime strpbrk memset strstr strnlen)
 AC_REPLACE_FUNCS(strtod strtol strtoul strtoll strtoull strtoimax strtoumax)
 
 AC_CHECK_DECLS([confstr])
index e0d7f797bd7d3f09031ff0adf7b53cd962c96b74..7eba6f08fff8fb921cdac93b4d38c8386fa43169 100644 (file)
@@ -2950,6 +2950,10 @@ a UDP connection to the corresponding socket.
 .RE
 .PP
 A failure to open or create a file causes the redirection to fail.
+.PP
+Redirections using file descriptors greater than 9 should be used with
+care, as they may conflict with file descriptors the shell uses
+internally.
 .SS Redirecting Input
 .PP
 Redirection of input causes the file whose name results from
index e95567fa68be5ce87eceb57a43c18ba556ff8448..e0d7f797bd7d3f09031ff0adf7b53cd962c96b74 100644 (file)
@@ -6,12 +6,12 @@
 .\"    Case Western Reserve University
 .\"    chet@po.CWRU.Edu
 .\"
-.\"    Last Change: Thu Sep 30 22:29:05 EDT 2004
+.\"    Last Change: Sat Oct  2 18:05:57 EDT 2004
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2004 Sep 30" "GNU Bash-3.0"
+.TH BASH 1 "2004 Oct 2" "GNU Bash-3.1-devel"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -2853,7 +2853,7 @@ Matches zero or more occurrences of the given patterns
 Matches one or more occurrences of the given patterns
 .TP
 \fB@(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches exactly one of the given patterns
+Matches one of the given patterns
 .TP
 \fB!(\fP\^\fIpattern-list\^\fP\fB)\fP
 Matches anything except one of the given patterns
index 9df7ead7b63afe2ba5447868e63c1eb70e942d84..94814d67675f65c06988b0601cadcaa93250f1d4 100644 (file)
@@ -2017,6 +2017,10 @@ connection to the corresponding socket.
 
 A failure to open or create a file causes the redirection to fail.
 
+Redirections using file descriptors greater than 9 should be used with
+care, as they may conflict with file descriptors the shell uses
+internally.
+
 @subsection Redirecting Input
 Redirection of input causes the file whose name results from
 the expansion of @var{word}
index 1e0e446da474dda366a62187d478f30ba69358e7..9df7ead7b63afe2ba5447868e63c1eb70e942d84 100644 (file)
@@ -1931,7 +1931,7 @@ Matches zero or more occurrences of the given patterns.
 Matches one or more occurrences of the given patterns.
 
 @item @@(@var{pattern-list})
-Matches exactly one of the given patterns.
+Matches one of the given patterns.
 
 @item !(@var{pattern-list})
 Matches anything except one of the given patterns.
index af20a424a875199a183ed1ebfda928fa2f5506a6..fe49140e237fcc52b32cf414f7fffc40cedb8088 100644 (file)
@@ -4,7 +4,7 @@ Copyright (C) 1988-2004 Free Software Foundation, Inc.
 
 @set EDITION 3.1-devel
 @set VERSION 3.1-devel
-@set UPDATED 2 October 2004
+@set UPDATED 9 October 2004
 @set UPDATED-MONTH October 2004
 
-@set LASTCHANGE Sat Oct  2 18:05:41 EDT 2004
+@set LASTCHANGE Sat Oct  9 18:40:05 EDT 2004
index 9dd2c46a0cfba3f845944bba15102df09d7f3f33..74cf713d68bbc289738c408a3c49a9d82cce4a77 100644 (file)
@@ -2,9 +2,9 @@
 Copyright (C) 1988-2004 Free Software Foundation, Inc.
 @end ignore
 
-@set EDITION 3.0
-@set VERSION 3.0
-@set UPDATED 2 October 2004
+@set EDITION 3.1-devel
+@set VERSION 3.1-devel
+@set UPDATED 9 October 2004
 @set UPDATED-MONTH October 2004
 
-@set LASTCHANGE Sat Oct  2 18:05:41 EDT 2004
+@set LASTCHANGE 
index cea110aba04c8f3e03e05b6841769019c616386f..968f23454cc9f69bb10a8dd5185d86864442e162 100644 (file)
@@ -160,7 +160,7 @@ static int execute_while_command __P((WHILE_COM *));
 static int execute_until_command __P((WHILE_COM *));
 static int execute_while_or_until __P((WHILE_COM *, int));
 static int execute_if_command __P((IF_COM *));
-static int execute_null_command __P((REDIRECT *, int, int, int, pid_t));
+static int execute_null_command __P((REDIRECT *, int, int, int));
 static void fix_assignment_words __P((WORD_LIST *));
 static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
 static int execute_builtin __P((sh_builtin_func_t *, WORD_LIST *, int, int));
@@ -491,7 +491,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
 {
   int exec_result, invert, ignore_return, was_error_trap;
   REDIRECT *my_undo_list, *exec_undo_list;
-  volatile pid_t last_pid;
   volatile int save_line_number;
 
   if (command == 0 || breaking || continuing || read_but_dont_execute)
@@ -648,7 +647,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
        /* We can't rely on variables retaining their values across a
           call to execute_simple_command if a longjmp occurs as the
           result of a `return' builtin.  This is true for sure with gcc. */
-       last_pid = last_made_pid;
+       last_made_pid = NO_PID;
        was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
 
        if (ignore_return && command->value.Simple)
@@ -678,7 +677,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
        /* XXX - this is something to watch out for if there are problems
           when the shell is compiled without job control. */
        if (already_making_children && pipe_out == NO_PIPE &&
-           last_pid != last_made_pid)
+           last_made_pid != NO_PID)
          {
            stop_pipeline (asynchronous, (COMMAND *)NULL);
 
@@ -698,14 +697,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
               subshells forked to execute builtin commands (e.g., in
               pipelines) to be waited for twice. */
              exec_result = wait_for (last_made_pid);
-#if defined (RECYCLES_PIDS)
-             /* LynxOS, for one, recycles pids very quickly -- so quickly
-                that a new process may have the same pid as the last one
-                created.  This has been reported to fix the problem on that
-                OS, and a similar problem on Cygwin. */
-             if (exec_result == 0)
-               last_made_pid = NO_PID;
-#endif
          }
       }
 
@@ -2583,10 +2574,9 @@ bind_lastarg (arg)
    to be run asynchronously.  This handles all the side effects that are
    supposed to take place. */
 static int
-execute_null_command (redirects, pipe_in, pipe_out, async, old_last_command_subst_pid)
+execute_null_command (redirects, pipe_in, pipe_out, async)
      REDIRECT *redirects;
      int pipe_in, pipe_out, async;
-     pid_t old_last_command_subst_pid;
 {
   int r;
 
@@ -2632,7 +2622,7 @@ execute_null_command (redirects, pipe_in, pipe_out, async, old_last_command_subs
 
       if (r != 0)
        return (EXECUTION_FAILURE);
-      else if (old_last_command_subst_pid != last_command_subst_pid)
+      else if (last_command_subst_pid != NO_PID)
        return (last_command_exit_value);
       else
        return (EXECUTION_SUCCESS);
@@ -2680,7 +2670,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
   WORD_LIST *words, *lastword;
   char *command_line, *lastarg, *temp;
   int first_word_quoted, result, builtin_is_special, already_forked, dofork;
-  pid_t old_last_command_subst_pid, old_last_async_pid;
+  pid_t old_last_async_pid;
   sh_builtin_func_t *builtin;
   SHELL_VAR *func;
 
@@ -2715,7 +2705,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
   first_word_quoted =
     simple_command->words ? (simple_command->words->word->flags & W_QUOTED): 0;
 
-  old_last_command_subst_pid = last_command_subst_pid;
+  last_command_subst_pid = NO_PID;
   old_last_async_pid = last_asynchronous_pid;
 
   already_forked = dofork = 0;
@@ -2809,8 +2799,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
       this_command_name = 0;
       result = execute_null_command (simple_command->redirects,
                                     pipe_in, pipe_out,
-                                    already_forked ? 0 : async,
-                                    old_last_command_subst_pid);
+                                    already_forked ? 0 : async);
       if (already_forked)
        exit (result);
       else
diff --git a/input.c~ b/input.c~
new file mode 100644 (file)
index 0000000..9ada733
--- /dev/null
+++ b/input.c~
@@ -0,0 +1,614 @@
+/* input.c -- functions to perform buffered input with synchronization. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#include "config.h"
+
+#include "bashtypes.h"
+#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
+#  include <sys/file.h>
+#endif
+#include "filecntl.h"
+#include "posixstat.h"
+#include <stdio.h>
+#include <errno.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "bashansi.h"
+#include "bashintl.h"
+
+#include "command.h"
+#include "general.h"
+#include "input.h"
+#include "error.h"
+#include "externs.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+/* Functions to handle reading input on systems that don't restart read(2)
+   if a signal is received. */
+
+static char localbuf[128];
+static int local_index, local_bufused;
+
+/* Posix and USG systems do not guarantee to restart read () if it is
+   interrupted by a signal.  We do the read ourselves, and restart it
+   if it returns EINTR. */
+int
+getc_with_restart (stream)
+     FILE *stream;
+{
+  unsigned char uc;
+
+  /* Try local buffering to reduce the number of read(2) calls. */
+  if (local_index == local_bufused || local_bufused == 0)
+    {
+      while (1)
+       {
+         local_bufused = read (fileno (stream), localbuf, sizeof(localbuf));
+         if (local_bufused > 0)
+           break;
+         else if (local_bufused == 0 || errno != EINTR)
+           {
+             local_index = 0;
+             return EOF;
+           }
+       }
+      local_index = 0;
+    }
+  uc = localbuf[local_index++];
+  return uc;
+}
+
+int
+ungetc_with_restart (c, stream)
+     int c;
+     FILE *stream;
+{
+  if (local_index == 0 || c == EOF)
+    return EOF;
+  localbuf[--local_index] = c;
+  return c;
+}
+
+#if defined (BUFFERED_INPUT)
+
+/* A facility similar to stdio, but input-only. */
+
+#if defined (USING_BASH_MALLOC)
+#  define MAX_INPUT_BUFFER_SIZE        8176
+#else
+#  define MAX_INPUT_BUFFER_SIZE        8192
+#endif
+
+#if !defined (SEEK_CUR)
+#  define SEEK_CUR 1
+#endif /* !SEEK_CUR */
+
+#ifdef max
+#  undef max
+#endif
+#define max(a, b)      (((a) > (b)) ? (a) : (b))
+#ifdef min
+#  undef min
+#endif
+#define min(a, b)      ((a) > (b) ? (b) : (a))
+
+extern int interactive_shell;
+
+int bash_input_fd_changed;
+
+/* This provides a way to map from a file descriptor to the buffer
+   associated with that file descriptor, rather than just the other
+   way around.  This is needed so that buffers are managed properly
+   in constructs like 3<&4.  buffers[x]->b_fd == x -- that is how the
+   correspondence is maintained. */
+static BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL;
+static int nbuffers;
+
+#define ALLOCATE_BUFFERS(n) \
+       do { if ((n) >= nbuffers) allocate_buffers (n); } while (0)
+
+/* Make sure `buffers' has at least N elements. */
+static void
+allocate_buffers (n)
+     int n;
+{
+  register int i, orig_nbuffers;
+
+  orig_nbuffers = nbuffers;
+  nbuffers = n + 20;
+  buffers = (BUFFERED_STREAM **)xrealloc
+    (buffers, nbuffers * sizeof (BUFFERED_STREAM *));
+
+  /* Zero out the new buffers. */
+  for (i = orig_nbuffers; i < nbuffers; i++)
+    buffers[i] = (BUFFERED_STREAM *)NULL;
+}
+
+/* Construct and return a BUFFERED_STREAM corresponding to file descriptor
+   FD, using BUFFER. */
+static BUFFERED_STREAM *
+make_buffered_stream (fd, buffer, bufsize)
+     int fd;
+     char *buffer;
+     size_t bufsize;
+{
+  BUFFERED_STREAM *bp;
+
+  bp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
+  ALLOCATE_BUFFERS (fd);
+  buffers[fd] = bp;
+  bp->b_fd = fd;
+  bp->b_buffer = buffer;
+  bp->b_size = bufsize;
+  bp->b_used = bp->b_inputp = bp->b_flag = 0;
+  if (bufsize == 1)
+    bp->b_flag |= B_UNBUFF;
+  return (bp);
+}
+
+/* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
+static BUFFERED_STREAM *
+copy_buffered_stream (bp)
+     BUFFERED_STREAM *bp;
+{
+  BUFFERED_STREAM *nbp;
+
+  if (!bp)
+    return ((BUFFERED_STREAM *)NULL);
+
+  nbp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
+  xbcopy ((char *)bp, (char *)nbp, sizeof (BUFFERED_STREAM));
+  return (nbp);
+}
+
+int
+set_bash_input_fd (fd)
+     int fd;
+{
+  if (bash_input.type == st_bstream)
+    bash_input.location.buffered_fd = fd;
+  else if (interactive_shell == 0)
+    default_buffered_input = fd;
+  return 0;
+}
+
+int
+fd_is_bash_input (fd)
+     int fd;
+{
+  if (bash_input.type == st_bstream && bash_input.location.buffered_fd == fd)
+    return 1;
+  else if (interactive_shell == 0 && default_buffered_input == fd)
+    return 1;
+  return 0;
+}
+
+/* Save the buffered stream corresponding to file descriptor FD (which bash
+   is using to read input) to a buffered stream associated with NEW_FD.  If
+   NEW_FD is -1, a new file descriptor is allocated with fcntl.  The new
+   file descriptor is returned on success, -1 on error. */
+int
+save_bash_input (fd, new_fd)
+     int fd, new_fd;
+{
+  int nfd;
+
+itrace("save_bash_input: %d -> %d", fd, new_fd);
+  /* Sync the stream so we can re-read from the new file descriptor.  We
+     might be able to avoid this by copying the buffered stream verbatim
+     to the new file descriptor. */
+  if (buffers[fd])
+    sync_buffered_stream (fd);
+
+  /* Now take care of duplicating the file descriptor that bash is
+     using for input, so we can reinitialize it later. */
+  nfd = (new_fd == -1) ? fcntl (fd, F_DUPFD, 10) : new_fd;
+  if (nfd == -1)
+    {
+      if (fcntl (fd, F_GETFD, 0) == 0)
+       sys_error (_("cannot allocate new file descriptor for bash input from fd %d"), fd);
+      return -1;
+    }
+
+  if (buffers[nfd])
+    {
+      /* What's this?  A stray buffer without an associated open file
+        descriptor?  Free up the buffer and report the error. */
+      internal_error (_("save_bash_input: buffer already exists for new fd %d"), nfd);
+      free_buffered_stream (buffers[nfd]);
+    }
+
+  /* Reinitialize bash_input.location. */
+  if (bash_input.type == st_bstream)
+    {
+      bash_input.location.buffered_fd = nfd;
+      fd_to_buffered_stream (nfd);
+      close_buffered_fd (fd);  /* XXX */
+    }
+  else
+    /* If the current input type is not a buffered stream, but the shell
+       is not interactive and therefore using a buffered stream to read
+       input (e.g. with an `eval exec 3>output' inside a script), note
+       that the input fd has been changed.  pop_stream() looks at this
+       value and adjusts the input fd to the new value of
+       default_buffered_input accordingly. */
+    bash_input_fd_changed++;
+
+  if (default_buffered_input == fd)
+    default_buffered_input = nfd;
+
+  SET_CLOSE_ON_EXEC (nfd);
+  return nfd;
+}
+
+/* Check that file descriptor FD is not the one that bash is currently
+   using to read input from a script.  FD is about to be duplicated onto,
+   which means that the kernel will close it for us.  If FD is the bash
+   input file descriptor, we need to seek backwards in the script (if
+   possible and necessary -- scripts read from stdin are still unbuffered),
+   allocate a new file descriptor to use for bash input, and re-initialize
+   the buffered stream.  Make sure the file descriptor used to save bash
+   input is set close-on-exec. Returns 0 on success, -1 on failure.  This
+   works only if fd is > 0 -- if fd == 0 and bash is reading input from
+   fd 0, save_bash_input is used instead, to cooperate with input
+   redirection (look at redir.c:add_undo_redirect()). */
+int
+check_bash_input (fd)
+     int fd;
+{
+itrace("check_bash_input: %d", fd);
+  if (fd_is_bash_input (fd))
+    {
+      if (fd > 0)
+       return ((save_bash_input (fd, -1) == -1) ? -1 : 0);
+      else if (fd == 0)
+        return ((sync_buffered_stream (fd) == -1) ? -1 : 0);
+    }
+  return 0;
+}
+      
+/* This is the buffered stream analogue of dup2(fd1, fd2).  The
+   BUFFERED_STREAM corresponding to fd2 is deallocated, if one exists.
+   BUFFERS[fd1] is copied to BUFFERS[fd2].  This is called by the
+   redirect code for constructs like 4<&0 and 3</etc/rc.local. */
+int
+duplicate_buffered_stream (fd1, fd2)
+     int fd1, fd2;
+{
+  int is_bash_input, m;
+
+  if (fd1 == fd2)
+    return 0;
+
+  m = max (fd1, fd2);
+  ALLOCATE_BUFFERS (m);
+
+  /* If FD2 is the file descriptor bash is currently using for shell input,
+     we need to do some extra work to make sure that the buffered stream
+     actually exists (it might not if fd1 was not active, and the copy
+     didn't actually do anything). */
+  is_bash_input = (bash_input.type == st_bstream) &&
+                 (bash_input.location.buffered_fd == fd2);
+
+  if (buffers[fd2])
+    free_buffered_stream (buffers[fd2]);
+  buffers[fd2] = copy_buffered_stream (buffers[fd1]);
+  if (buffers[fd2])
+    buffers[fd2]->b_fd = fd2;
+
+  if (is_bash_input)
+    {
+      if (!buffers[fd2])
+       fd_to_buffered_stream (fd2);
+      buffers[fd2]->b_flag |= B_WASBASHINPUT;
+    }
+
+  return (fd2);
+}
+
+/* Return 1 if a seek on FD will succeed. */
+#ifndef __CYGWIN__
+#  define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
+#else
+#  define fd_is_seekable(fd) 0
+#endif /* __CYGWIN__ */
+
+/* Take FD, a file descriptor, and create and return a buffered stream
+   corresponding to it.  If something is wrong and the file descriptor
+   is invalid, return a NULL stream. */
+BUFFERED_STREAM *
+fd_to_buffered_stream (fd)
+     int fd;
+{
+  char *buffer;
+  size_t size;
+  struct stat sb;
+
+  if (fstat (fd, &sb) < 0)
+    {
+      close (fd);
+      return ((BUFFERED_STREAM *)NULL);
+    }
+
+  size = (fd_is_seekable (fd)) ? min (sb.st_size, MAX_INPUT_BUFFER_SIZE) : 1;
+  if (size == 0)
+    size = 1;
+  buffer = (char *)xmalloc (size);
+
+  return (make_buffered_stream (fd, buffer, size));
+}
+
+/* Return a buffered stream corresponding to FILE, a file name. */
+BUFFERED_STREAM *
+open_buffered_stream (file)
+     char *file;
+{
+  int fd;
+
+  fd = open (file, O_RDONLY);
+  return ((fd >= 0) ? fd_to_buffered_stream (fd) : (BUFFERED_STREAM *)NULL);
+}
+
+/* Deallocate a buffered stream and free up its resources.  Make sure we
+   zero out the slot in BUFFERS that points to BP. */
+void
+free_buffered_stream (bp)
+     BUFFERED_STREAM *bp;
+{
+  int n;
+
+  if (!bp)
+    return;
+
+  n = bp->b_fd;
+  if (bp->b_buffer)
+    free (bp->b_buffer);
+  free (bp);
+  buffers[n] = (BUFFERED_STREAM *)NULL;
+}
+
+/* Close the file descriptor associated with BP, a buffered stream, and free
+   up the stream.  Return the status of closing BP's file descriptor. */
+int
+close_buffered_stream (bp)
+     BUFFERED_STREAM *bp;
+{
+  int fd;
+
+  if (!bp)
+    return (0);
+  fd = bp->b_fd;
+  free_buffered_stream (bp);
+  return (close (fd));
+}
+
+/* Deallocate the buffered stream associated with file descriptor FD, and
+   close FD.  Return the status of the close on FD. */
+int
+close_buffered_fd (fd)
+     int fd;
+{
+  if (fd < 0)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  if (fd >= nbuffers || !buffers || !buffers[fd])
+    return (close (fd));
+  return (close_buffered_stream (buffers[fd]));
+}
+
+/* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return
+   the old BUFFERED_STREAM. */
+BUFFERED_STREAM *
+set_buffered_stream (fd, bp)
+     int fd;
+     BUFFERED_STREAM *bp;
+{
+  BUFFERED_STREAM *ret;
+
+  ret = buffers[fd];
+  buffers[fd] = bp;
+  return ret;
+}
+
+/* Read a buffer full of characters from BP, a buffered stream. */
+static int
+b_fill_buffer (bp)
+     BUFFERED_STREAM *bp;
+{
+  ssize_t nr;
+
+  nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
+  if (nr <= 0)
+    {
+      bp->b_used = 0;
+      bp->b_buffer[0] = 0;
+      if (nr == 0)
+       bp->b_flag |= B_EOF;
+      else
+       bp->b_flag |= B_ERROR;
+      return (EOF);
+    }
+
+#if defined (__CYGWIN__)
+  /* If on cygwin, translate \r\n to \n. */
+  if (nr >= 2 && bp->b_buffer[nr - 2] == '\r' && bp->b_buffer[nr - 1] == '\n')
+    {
+      bp->b_buffer[nr - 2] = '\n';
+      nr--;
+    }
+#endif
+
+  bp->b_used = nr;
+  bp->b_inputp = 0;
+  return (bp->b_buffer[bp->b_inputp++] & 0xFF);
+}
+
+/* Get a character from buffered stream BP. */
+#define bufstream_getc(bp) \
+  (bp->b_inputp == bp->b_used || !bp->b_used) \
+               ? b_fill_buffer (bp) \
+               : bp->b_buffer[bp->b_inputp++] & 0xFF
+
+/* Push C back onto buffered stream BP. */
+static int
+bufstream_ungetc(c, bp)
+     int c;
+     BUFFERED_STREAM *bp;
+{
+  if (c == EOF || bp->b_inputp == 0)
+    return (EOF);
+
+  bp->b_buffer[--bp->b_inputp] = c;
+  return (c);
+}
+
+/* Seek backwards on file BFD to synchronize what we've read so far
+   with the underlying file pointer. */
+int
+sync_buffered_stream (bfd)
+     int bfd;
+{
+  BUFFERED_STREAM *bp;
+  off_t chars_left;
+
+  if (buffers == 0 || (bp = buffers[bfd]) == 0)
+    return (-1);
+
+  chars_left = bp->b_used - bp->b_inputp;
+  if (chars_left)
+    lseek (bp->b_fd, -chars_left, SEEK_CUR);
+  bp->b_used = bp->b_inputp = 0;
+  return (0);
+}
+
+int
+buffered_getchar ()
+{
+#if !defined (DJGPP)
+  return (bufstream_getc (buffers[bash_input.location.buffered_fd]));
+#else
+  /* On DJGPP, ignore \r. */
+  int ch;
+  while ((ch = bufstream_getc (buffers[bash_input.location.buffered_fd])) == '\r')
+    ;
+  return ch;
+#endif
+}
+
+int
+buffered_ungetchar (c)
+     int c;
+{
+  return (bufstream_ungetc (c, buffers[bash_input.location.buffered_fd]));
+}
+
+/* Make input come from file descriptor BFD through a buffered stream. */
+void
+with_input_from_buffered_stream (bfd, name)
+     int bfd;
+     char *name;
+{
+  INPUT_STREAM location;
+  BUFFERED_STREAM *bp;
+
+  location.buffered_fd = bfd;
+  /* Make sure the buffered stream exists. */
+  bp = fd_to_buffered_stream (bfd);
+  init_yy_io (bp == 0 ? return_EOF : buffered_getchar,
+             buffered_ungetchar, st_bstream, name, location);
+}
+
+#if defined (TEST)
+void *
+xmalloc(s)
+int s;
+{
+       return (malloc (s));
+}
+
+void *
+xrealloc(s, size)
+char   *s;
+int    size;
+{
+       if (!s)
+               return(malloc (size));
+       else
+               return(realloc (s, size));
+}
+
+void
+init_yy_io ()
+{
+}
+
+process(bp)
+BUFFERED_STREAM *bp;
+{
+       int c;
+
+       while ((c = bufstream_getc(bp)) != EOF)
+               putchar(c);
+}
+
+BASH_INPUT bash_input;
+
+struct stat dsb;               /* can be used from gdb */
+
+/* imitate /bin/cat */
+main(argc, argv)
+int    argc;
+char   **argv;
+{
+       register int i;
+       BUFFERED_STREAM *bp;
+
+       if (argc == 1) {
+               bp = fd_to_buffered_stream (0);
+               process(bp);
+               exit(0);
+       }
+       for (i = 1; i < argc; i++) {
+               if (argv[i][0] == '-' && argv[i][1] == '\0') {
+                       bp = fd_to_buffered_stream (0);
+                       if (!bp)
+                               continue;
+                       process(bp);
+                       free_buffered_stream (bp);
+               } else {
+                       bp = open_buffered_stream (argv[i]);
+                       if (!bp)
+                               continue;
+                       process(bp);
+                       close_buffered_stream (bp);
+               }
+       }
+       exit(0);
+}
+#endif /* TEST */
+#endif /* BUFFERED_INPUT */
diff --git a/redir.c b/redir.c
index 228d67ebb39b1a9fbfae491b540cd556db8e10ff..3ee44ca96b96feba8ce62db947c07c8b478032ce 100644 (file)
--- a/redir.c
+++ b/redir.c
@@ -970,6 +970,21 @@ add_undo_redirect (fd)
      is thrown away by the `exec' builtin. */
   add_exec_redirect (dummy_redirect);
 
+  /* experimental:  if we're saving a redirection to undo for a file descriptor
+     above SHELL_FD_BASE, add a redirection to be undone if the exec builtin
+     causes redirections to be discarded. */
+  if (fd >= SHELL_FD_BASE)
+    {
+      rd.dest = new_fd;
+      new_redirect = make_redirection (fd, r_duplicating_output, rd);
+#if 0
+      closer = copy_redirects (new_redirect);
+      add_exec_redirect (closer);
+#else
+      add_exec_redirect (new_redirect);
+#endif     
+    }
+
   /* File descriptors used only for saving others should always be
      marked close-on-exec.  Unfortunately, we have to preserve the
      close-on-exec state of the file descriptor we are saving, since
diff --git a/redir.c~ b/redir.c~
new file mode 100644 (file)
index 0000000..8b58776
--- /dev/null
+++ b/redir.c~
@@ -0,0 +1,1066 @@
+/* redir.c -- Functions to perform input and output redirection. */
+
+/* Copyright (C) 1997-2002 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#include "config.h"
+
+#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
+  #pragma alloca
+#endif /* _AIX && RISC6000 && !__GNUC__ */
+
+#include <stdio.h>
+#include "bashtypes.h"
+#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
+#  include <sys/file.h>
+#endif
+#include "filecntl.h"
+#include "posixstat.h"
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include <errno.h>
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#include "bashansi.h"
+#include "bashintl.h"
+
+#include "memalloc.h"
+#include "shell.h"
+#include "flags.h"
+#include "execute_cmd.h"
+#include "redir.h"
+
+#if defined (BUFFERED_INPUT)
+#  include "input.h"
+#endif
+
+int expanding_redir;
+
+extern int posixly_correct;
+extern REDIRECT *redirection_undo_list;
+extern REDIRECT *exec_redirection_undo_list;
+
+/* Static functions defined and used in this file. */
+static void add_undo_close_redirect __P((int));
+static void add_exec_redirect __P((REDIRECT *));
+static int add_undo_redirect __P((int));
+static int expandable_redirection_filename __P((REDIRECT *));
+static int stdin_redirection __P((enum r_instruction, int));
+static int do_redirection_internal __P((REDIRECT *, int));
+
+static int write_here_document __P((int, WORD_DESC *));
+static int write_here_string __P((int, WORD_DESC *));
+static int here_document_to_fd __P((WORD_DESC *, enum r_instruction));
+
+static int redir_special_open __P((int, char *, int, int, enum r_instruction));
+static int noclobber_open __P((char *, int, int, enum r_instruction));
+static int redir_open __P((char *, int, int, enum r_instruction));
+
+/* Spare redirector used when translating [N]>&WORD[-] or [N]<&WORD[-] to
+   a new redirection and when creating the redirection undo list. */
+static REDIRECTEE rd;
+
+/* Set to errno when a here document cannot be created for some reason.
+   Used to print a reasonable error message. */
+static int heredoc_errno;
+
+void
+redirection_error (temp, error)
+     REDIRECT *temp;
+     int error;
+{
+  char *filename, *allocname;
+  int oflags;
+
+  allocname = 0;
+  if (temp->redirector < 0)
+    /* This can happen when read_token_word encounters overflow, like in
+       exec 4294967297>x */
+    filename = _("file descriptor out of range");
+#ifdef EBADF
+  else if (temp->redirector >= 0 && errno == EBADF)
+    {
+      /* If we're dealing with two file descriptors, we have to guess about
+         which one is invalid; in the cases of r_{duplicating,move}_input and
+         r_{duplicating,move}_output we're here because dup2() failed. */
+      switch (temp->instruction)
+        {
+        case r_duplicating_input:
+        case r_duplicating_output:
+        case r_move_input:
+        case r_move_output:
+         filename = allocname = itos (temp->redirectee.dest);
+         break;
+       default:
+         filename = allocname = itos (temp->redirector);
+         break;
+        }
+    }
+#endif
+  else if (expandable_redirection_filename (temp))
+    {
+      if (posixly_correct && interactive_shell == 0)
+       {
+         oflags = temp->redirectee.filename->flags;
+         temp->redirectee.filename->flags |= W_NOGLOB;
+       }
+      filename = allocname = redirection_expand (temp->redirectee.filename);
+      if (posixly_correct && interactive_shell == 0)
+       temp->redirectee.filename->flags = oflags;
+      if (filename == 0)
+       filename = temp->redirectee.filename->word;
+    }
+  else if (temp->redirectee.dest < 0)
+    filename = "file descriptor out of range";
+  else
+    filename = allocname = itos (temp->redirectee.dest);
+
+  switch (error)
+    {
+    case AMBIGUOUS_REDIRECT:
+      internal_error (_("%s: ambiguous redirect"), filename);
+      break;
+
+    case NOCLOBBER_REDIRECT:
+      internal_error (_("%s: cannot overwrite existing file"), filename);
+      break;
+
+#if defined (RESTRICTED_SHELL)
+    case RESTRICTED_REDIRECT:
+      internal_error (_("%s: restricted: cannot redirect output"), filename);
+      break;
+#endif /* RESTRICTED_SHELL */
+
+    case HEREDOC_REDIRECT:
+      internal_error (_("cannot create temp file for here document: %s"), strerror (heredoc_errno));
+      break;
+
+    default:
+      internal_error ("%s: %s", filename, strerror (error));
+      break;
+    }
+
+  FREE (allocname);
+}
+
+/* Perform the redirections on LIST.  If flags & RX_ACTIVE, then actually
+   make input and output file descriptors, otherwise just do whatever is
+   neccessary for side effecting.  flags & RX_UNDOABLE says to remember
+   how to undo the redirections later, if non-zero.  If flags & RX_CLEXEC
+   is non-zero, file descriptors opened in do_redirection () have their
+   close-on-exec flag set. */
+int
+do_redirections (list, flags)
+     REDIRECT *list;
+     int flags;
+{
+  int error;
+  REDIRECT *temp;
+
+  if (flags & RX_UNDOABLE)
+    {
+      if (redirection_undo_list)
+       {
+         dispose_redirects (redirection_undo_list);
+         redirection_undo_list = (REDIRECT *)NULL;
+       }
+      if (exec_redirection_undo_list)
+       dispose_exec_redirects ();
+    }
+
+  for (temp = list; temp; temp = temp->next)
+    {
+      error = do_redirection_internal (temp, flags);
+      if (error)
+       {
+         redirection_error (temp, error);
+         return (error);
+       }
+    }
+  return (0);
+}
+
+/* Return non-zero if the redirection pointed to by REDIRECT has a
+   redirectee.filename that can be expanded. */
+static int
+expandable_redirection_filename (redirect)
+     REDIRECT *redirect;
+{
+  switch (redirect->instruction)
+    {
+    case r_output_direction:
+    case r_appending_to:
+    case r_input_direction:
+    case r_inputa_direction:
+    case r_err_and_out:
+    case r_input_output:
+    case r_output_force:
+    case r_duplicating_input_word:
+    case r_duplicating_output_word:
+    case r_move_input_word:
+    case r_move_output_word:
+      return 1;
+
+    default:
+      return 0;
+    }
+}
+
+/* Expand the word in WORD returning a string.  If WORD expands to
+   multiple words (or no words), then return NULL. */
+char *
+redirection_expand (word)
+     WORD_DESC *word;
+{
+  char *result;
+  WORD_LIST *tlist1, *tlist2;
+  WORD_DESC *w;
+
+  w = copy_word (word);
+  if (posixly_correct)
+    w->flags |= W_NOSPLIT;
+
+  tlist1 = make_word_list (w, (WORD_LIST *)NULL);
+  expanding_redir = 1;
+  tlist2 = expand_words_no_vars (tlist1);
+  expanding_redir = 0;
+  dispose_words (tlist1);
+
+  if (!tlist2 || tlist2->next)
+    {
+      /* We expanded to no words, or to more than a single word.
+        Dispose of the word list and return NULL. */
+      if (tlist2)
+       dispose_words (tlist2);
+      return ((char *)NULL);
+    }
+  result = string_list (tlist2);  /* XXX savestring (tlist2->word->word)? */
+  dispose_words (tlist2);
+  return (result);
+}
+
+static int
+write_here_string (fd, redirectee)
+     int fd;
+     WORD_DESC *redirectee;
+{
+  char *herestr;
+  int herelen, n, e;
+
+  herestr = expand_string_to_string (redirectee->word, 0);
+  herelen = STRLEN (herestr);
+
+  n = write (fd, herestr, herelen);
+  if (n == herelen)
+    {
+      n = write (fd, "\n", 1);
+      herelen = 1;
+    }
+  e = errno;
+  FREE (herestr);
+  if (n != herelen)
+    {
+      if (e == 0)
+       e = ENOSPC;
+      return e;
+    }
+  return 0;
+}  
+
+/* Write the text of the here document pointed to by REDIRECTEE to the file
+   descriptor FD, which is already open to a temp file.  Return 0 if the
+   write is successful, otherwise return errno. */
+static int
+write_here_document (fd, redirectee)
+     int fd;
+     WORD_DESC *redirectee;
+{
+  char *document;
+  int document_len, fd2;
+  FILE *fp;
+  register WORD_LIST *t, *tlist;
+
+  /* Expand the text if the word that was specified had
+     no quoting.  The text that we expand is treated
+     exactly as if it were surrounded by double quotes. */
+
+  if (redirectee->flags & W_QUOTED)
+    {
+      document = redirectee->word;
+      document_len = strlen (document);
+      /* Set errno to something reasonable if the write fails. */
+      if (write (fd, document, document_len) < document_len)
+       {
+         if (errno == 0)
+           errno = ENOSPC;
+         return (errno);
+       }
+      else
+       return 0;
+    }
+
+  tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);
+  if (tlist)
+    {
+      /* Try using buffered I/O (stdio) and writing a word
+        at a time, letting stdio do the work of buffering
+        for us rather than managing our own strings.  Most
+        stdios are not particularly fast, however -- this
+        may need to be reconsidered later. */
+      if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL)
+       {
+         if (fd2 >= 0)
+           close (fd2);
+         return (errno);
+       }
+      errno = 0;
+      for (t = tlist; t; t = t->next)
+       {
+         /* This is essentially the body of
+            string_list_internal expanded inline. */
+         document = t->word->word;
+         document_len = strlen (document);
+         if (t != tlist)
+           putc (' ', fp);     /* separator */
+         fwrite (document, document_len, 1, fp);
+         if (ferror (fp))
+           {
+             if (errno == 0)
+               errno = ENOSPC;
+             fd2 = errno;
+             fclose(fp);
+             dispose_words (tlist);
+             return (fd2);
+           }
+       }
+      dispose_words (tlist);
+      if (fclose (fp) != 0)
+       {
+         if (errno == 0)
+           errno = ENOSPC;
+         return (errno);
+       }
+    }
+  return 0;
+}
+
+/* Create a temporary file holding the text of the here document pointed to
+   by REDIRECTEE, and return a file descriptor open for reading to the temp
+   file.  Return -1 on any error, and make sure errno is set appropriately. */
+static int
+here_document_to_fd (redirectee, ri)
+     WORD_DESC *redirectee;
+     enum r_instruction ri;
+{
+  char *filename;
+  int r, fd, fd2;
+
+  fd = sh_mktmpfd ("sh-thd", MT_USERANDOM, &filename);
+
+  /* If we failed for some reason other than the file existing, abort */
+  if (fd < 0)
+    {
+      FREE (filename);
+      return (fd);
+    }
+
+  errno = r = 0;               /* XXX */
+  /* write_here_document returns 0 on success, errno on failure. */
+  if (redirectee->word)
+    r = (ri != r_reading_string) ? write_here_document (fd, redirectee)
+                                : write_here_string (fd, redirectee);
+
+  if (r)
+    {
+      close (fd);
+      unlink (filename);
+      free (filename);
+      errno = r;
+      return (-1);
+    }
+
+  /* In an attempt to avoid races, we close the first fd only after opening
+     the second. */
+  /* Make the document really temporary.  Also make it the input. */
+  fd2 = open (filename, O_RDONLY, 0600);
+
+  if (fd2 < 0)
+    {
+      r = errno;
+      unlink (filename);
+      free (filename);
+      close (fd);
+      errno = r;
+      return -1;
+    }
+
+  close (fd);
+  if (unlink (filename) < 0)
+    {
+      r = errno;
+#if defined (__CYGWIN__)
+      /* Under CygWin 1.1.0, the unlink will fail if the file is
+        open. This hack will allow the previous action of silently
+        ignoring the error, but will still leave the file there. This
+        needs some kind of magic. */
+      if (r == EACCES)
+       return (fd2);
+#endif /* __CYGWIN__ */
+      close (fd2);
+      free (filename);
+      errno = r;
+      return (-1);
+    }
+
+  free (filename);
+  return (fd2);
+}
+
+#define RF_DEVFD       1
+#define RF_DEVSTDERR   2
+#define RF_DEVSTDIN    3
+#define RF_DEVSTDOUT   4
+#define RF_DEVTCP      5
+#define RF_DEVUDP      6
+
+/* A list of pattern/value pairs for filenames that the redirection
+   code handles specially. */
+static STRING_INT_ALIST _redir_special_filenames[] = {
+#if !defined (HAVE_DEV_FD)
+  { "/dev/fd/[0-9]*", RF_DEVFD },
+#endif
+#if !defined (HAVE_DEV_STDIN)
+  { "/dev/stderr", RF_DEVSTDERR },
+  { "/dev/stdin", RF_DEVSTDIN },
+  { "/dev/stdout", RF_DEVSTDOUT },
+#endif
+#if defined (NETWORK_REDIRECTIONS)
+  { "/dev/tcp/*/*", RF_DEVTCP },
+  { "/dev/udp/*/*", RF_DEVUDP },
+#endif
+  { (char *)NULL, -1 }
+};
+
+static int
+redir_special_open (spec, filename, flags, mode, ri)
+     int spec;
+     char *filename;
+     int flags, mode;
+     enum r_instruction ri;
+{
+  int fd;
+#if !defined (HAVE_DEV_FD)
+  intmax_t lfd;
+#endif
+
+  fd = -1;
+  switch (spec)
+    {
+#if !defined (HAVE_DEV_FD)
+    case RF_DEVFD:
+      if (all_digits (filename+8) && legal_number (filename+8, &lfd) && lfd == (int)lfd)
+       {
+         fd = lfd;
+         fd = fcntl (fd, F_DUPFD, 10);
+       }
+      else
+       fd = AMBIGUOUS_REDIRECT;
+      break;
+#endif
+
+#if !defined (HAVE_DEV_STDIN)
+    case RF_DEVSTDIN:
+      fd = fcntl (0, F_DUPFD, 10);
+      break;
+    case RF_DEVSTDOUT:
+      fd = fcntl (1, F_DUPFD, 10);
+      break;
+    case RF_DEVSTDERR:
+      fd = fcntl (2, F_DUPFD, 10);
+      break;
+#endif
+
+#if defined (NETWORK_REDIRECTIONS)
+    case RF_DEVTCP:
+    case RF_DEVUDP:
+#if defined (HAVE_NETWORK)
+      fd = netopen (filename);
+#else
+      internal_warning (_("/dev/(tcp|udp)/host/port not supported without networking"));
+      fd = open (filename, flags, mode);
+#endif
+      break;
+#endif /* NETWORK_REDIRECTIONS */
+    }
+
+  return fd;
+}
+      
+/* Open FILENAME with FLAGS in noclobber mode, hopefully avoiding most
+   race conditions and avoiding the problem where the file is replaced
+   between the stat(2) and open(2). */
+static int
+noclobber_open (filename, flags, mode, ri)
+     char *filename;
+     int flags, mode;
+     enum r_instruction ri;
+{
+  int r, fd;
+  struct stat finfo, finfo2;
+
+  /* If the file exists and is a regular file, return an error
+     immediately. */
+  r = stat (filename, &finfo);
+  if (r == 0 && (S_ISREG (finfo.st_mode)))
+    return (NOCLOBBER_REDIRECT);
+
+  /* If the file was not present (r != 0), make sure we open it
+     exclusively so that if it is created before we open it, our open
+     will fail.  Make sure that we do not truncate an existing file.
+     Note that we don't turn on O_EXCL unless the stat failed -- if
+     the file was not a regular file, we leave O_EXCL off. */
+  flags &= ~O_TRUNC;
+  if (r != 0)
+    {
+      fd = open (filename, flags|O_EXCL, mode);
+      return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd);
+    }
+  fd = open (filename, flags, mode);
+
+  /* If the open failed, return the file descriptor right away. */
+  if (fd < 0)
+    return (errno == EEXIST ? NOCLOBBER_REDIRECT : fd);
+
+  /* OK, the open succeeded, but the file may have been changed from a
+     non-regular file to a regular file between the stat and the open.
+     We are assuming that the O_EXCL open handles the case where FILENAME
+     did not exist and is symlinked to an existing file between the stat
+     and open. */
+
+  /* If we can open it and fstat the file descriptor, and neither check
+     revealed that it was a regular file, and the file has not been replaced,
+     return the file descriptor. */
+  if ((fstat (fd, &finfo2) == 0) && (S_ISREG (finfo2.st_mode) == 0) &&
+      r == 0 && (S_ISREG (finfo.st_mode) == 0) &&
+      same_file (filename, filename, &finfo, &finfo2))
+    return fd;
+
+  /* The file has been replaced.  badness. */
+  close (fd);  
+  errno = EEXIST;
+  return (NOCLOBBER_REDIRECT);
+}
+
+static int
+redir_open (filename, flags, mode, ri)
+     char *filename;
+     int flags, mode;
+     enum r_instruction ri;
+{
+  int fd, r;
+
+  r = find_string_in_alist (filename, _redir_special_filenames, 1);
+  if (r >= 0)
+    return (redir_special_open (r, filename, flags, mode, ri));
+
+  /* If we are in noclobber mode, you are not allowed to overwrite
+     existing files.  Check before opening. */
+  if (noclobber && CLOBBERING_REDIRECT (ri))
+    {
+      fd = noclobber_open (filename, flags, mode, ri);
+      if (fd == NOCLOBBER_REDIRECT)
+       return (NOCLOBBER_REDIRECT);
+    }
+  else
+    {
+      fd = open (filename, flags, mode);
+#if defined (AFS)
+      if ((fd < 0) && (errno == EACCES))
+       fd = open (filename, flags & ~O_CREAT, mode);
+#endif /* AFS */
+    }
+
+  return fd;
+}
+
+/* Do the specific redirection requested.  Returns errno or one of the
+   special redirection errors (*_REDIRECT) in case of error, 0 on success.
+   If flags & RX_ACTIVE is zero, then just do whatever is neccessary to
+   produce the appropriate side effects.   flags & RX_UNDOABLE, if non-zero,
+   says to remember how to undo each redirection.  If flags & RX_CLEXEC is
+   non-zero, then we set all file descriptors > 2 that we open to be
+   close-on-exec.  */
+static int
+do_redirection_internal (redirect, flags)
+     REDIRECT *redirect;
+     int flags;
+{
+  WORD_DESC *redirectee;
+  int redir_fd, fd, redirector, r, oflags;
+  intmax_t lfd;
+  char *redirectee_word;
+  enum r_instruction ri;
+  REDIRECT *new_redirect;
+
+  redirectee = redirect->redirectee.filename;
+  redir_fd = redirect->redirectee.dest;
+  redirector = redirect->redirector;
+  ri = redirect->instruction;
+
+  if (TRANSLATE_REDIRECT (ri))
+    {
+      /* We have [N]>&WORD[-] or [N]<&WORD[-].  Expand WORD, then translate
+        the redirection into a new one and continue. */
+      redirectee_word = redirection_expand (redirectee);
+
+      /* XXX - what to do with [N]<&$w- where w is unset or null?  ksh93
+              closes N. */
+      if (redirectee_word == 0)
+       return (AMBIGUOUS_REDIRECT);
+      else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
+       {
+         rd.dest = 0;
+         new_redirect = make_redirection (redirector, r_close_this, rd);
+       }
+      else if (all_digits (redirectee_word))
+       {
+         if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
+           rd.dest = lfd;
+         else
+           rd.dest = -1;       /* XXX */
+         switch (ri)
+           {
+           case r_duplicating_input_word:
+             new_redirect = make_redirection (redirector, r_duplicating_input, rd);
+             break;
+           case r_duplicating_output_word:
+             new_redirect = make_redirection (redirector, r_duplicating_output, rd);
+             break;
+           case r_move_input_word:
+             new_redirect = make_redirection (redirector, r_move_input, rd);
+             break;
+           case r_move_output_word:
+             new_redirect = make_redirection (redirector, r_move_output, rd);
+             break;
+           }
+       }
+      else if (ri == r_duplicating_output_word && redirector == 1)
+       {
+         rd.filename = make_bare_word (redirectee_word);
+         new_redirect = make_redirection (1, r_err_and_out, rd);
+       }
+      else
+       {
+         free (redirectee_word);
+         return (AMBIGUOUS_REDIRECT);
+       }
+
+      free (redirectee_word);
+
+      /* Set up the variables needed by the rest of the function from the
+        new redirection. */
+      if (new_redirect->instruction == r_err_and_out)
+       {
+         char *alloca_hack;
+
+         /* Copy the word without allocating any memory that must be
+            explicitly freed. */
+         redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC));
+         xbcopy ((char *)new_redirect->redirectee.filename,
+                (char *)redirectee, sizeof (WORD_DESC));
+
+         alloca_hack = (char *)
+           alloca (1 + strlen (new_redirect->redirectee.filename->word));
+         redirectee->word = alloca_hack;
+         strcpy (redirectee->word, new_redirect->redirectee.filename->word);
+       }
+      else
+       /* It's guaranteed to be an integer, and shouldn't be freed. */
+       redirectee = new_redirect->redirectee.filename;
+
+      redir_fd = new_redirect->redirectee.dest;
+      redirector = new_redirect->redirector;
+      ri = new_redirect->instruction;
+
+      /* Overwrite the flags element of the old redirect with the new value. */
+      redirect->flags = new_redirect->flags;
+      dispose_redirects (new_redirect);
+    }
+
+  switch (ri)
+    {
+    case r_output_direction:
+    case r_appending_to:
+    case r_input_direction:
+    case r_inputa_direction:
+    case r_err_and_out:                /* command &>filename */
+    case r_input_output:
+    case r_output_force:
+      if (posixly_correct && interactive_shell == 0)
+       {
+         oflags = redirectee->flags;
+         redirectee->flags |= W_NOGLOB;
+       }
+      redirectee_word = redirection_expand (redirectee);
+      if (posixly_correct && interactive_shell == 0)
+       redirectee->flags = oflags;
+
+      if (redirectee_word == 0)
+       return (AMBIGUOUS_REDIRECT);
+
+#if defined (RESTRICTED_SHELL)
+      if (restricted && (WRITE_REDIRECT (ri)))
+       {
+         free (redirectee_word);
+         return (RESTRICTED_REDIRECT);
+       }
+#endif /* RESTRICTED_SHELL */
+
+      fd = redir_open (redirectee_word, redirect->flags, 0666, ri);
+      free (redirectee_word);
+
+      if (fd == NOCLOBBER_REDIRECT)
+       return (fd);
+
+      if (fd < 0)
+       return (errno);
+
+      if (flags & RX_ACTIVE)
+       {
+         if (flags & RX_UNDOABLE)
+           {
+             /* Only setup to undo it if the thing to undo is active. */
+             if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
+               add_undo_redirect (redirector);
+             else
+               add_undo_close_redirect (redirector);
+           }
+
+#if defined (BUFFERED_INPUT)
+         check_bash_input (redirector);
+#endif
+
+         if ((fd != redirector) && (dup2 (fd, redirector) < 0))
+           return (errno);
+
+#if defined (BUFFERED_INPUT)
+         /* Do not change the buffered stream for an implicit redirection
+            of /dev/null to fd 0 for asynchronous commands without job
+            control (r_inputa_direction). */
+         if (ri == r_input_direction || ri == r_input_output)
+           duplicate_buffered_stream (fd, redirector);
+#endif /* BUFFERED_INPUT */
+
+         /*
+          * If we're remembering, then this is the result of a while, for
+          * or until loop with a loop redirection, or a function/builtin
+          * executing in the parent shell with a redirection.  In the
+          * function/builtin case, we want to set all file descriptors > 2
+          * to be close-on-exec to duplicate the effect of the old
+          * for i = 3 to NOFILE close(i) loop.  In the case of the loops,
+          * both sh and ksh leave the file descriptors open across execs.
+          * The Posix standard mentions only the exec builtin.
+          */
+         if ((flags & RX_CLEXEC) && (redirector > 2))
+           SET_CLOSE_ON_EXEC (redirector);
+       }
+
+      if (fd != redirector)
+       {
+#if defined (BUFFERED_INPUT)
+         if (INPUT_REDIRECT (ri))
+           close_buffered_fd (fd);
+         else
+#endif /* !BUFFERED_INPUT */
+           close (fd);         /* Don't close what we just opened! */
+       }
+
+      /* If we are hacking both stdout and stderr, do the stderr
+        redirection here. */
+      if (ri == r_err_and_out)
+       {
+         if (flags & RX_ACTIVE)
+           {
+             if (flags & RX_UNDOABLE)
+               add_undo_redirect (2);
+             if (dup2 (1, 2) < 0)
+               return (errno);
+           }
+       }
+      break;
+
+    case r_reading_until:
+    case r_deblank_reading_until:
+    case r_reading_string:
+      /* REDIRECTEE is a pointer to a WORD_DESC containing the text of
+        the new input.  Place it in a temporary file. */
+      if (redirectee)
+       {
+         fd = here_document_to_fd (redirectee, ri);
+
+         if (fd < 0)
+           {
+             heredoc_errno = errno;
+             return (HEREDOC_REDIRECT);
+           }
+
+         if (flags & RX_ACTIVE)
+           {
+             if (flags & RX_UNDOABLE)
+               {
+                 /* Only setup to undo it if the thing to undo is active. */
+                 if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
+                   add_undo_redirect (redirector);
+                 else
+                   add_undo_close_redirect (redirector);
+               }
+
+#if defined (BUFFERED_INPUT)
+             check_bash_input (redirector);
+#endif
+             if (fd != redirector && dup2 (fd, redirector) < 0)
+               {
+                 r = errno;
+                 close (fd);
+                 return (r);
+               }
+
+#if defined (BUFFERED_INPUT)
+             duplicate_buffered_stream (fd, redirector);
+#endif
+
+             if ((flags & RX_CLEXEC) && (redirector > 2))
+               SET_CLOSE_ON_EXEC (redirector);
+           }
+
+         if (fd != redirector)
+#if defined (BUFFERED_INPUT)
+           close_buffered_fd (fd);
+#else
+           close (fd);
+#endif
+       }
+      break;
+
+    case r_duplicating_input:
+    case r_duplicating_output:
+    case r_move_input:
+    case r_move_output:
+      if ((flags & RX_ACTIVE) && (redir_fd != redirector))
+       {
+         if (flags & RX_UNDOABLE)
+           {
+             /* Only setup to undo it if the thing to undo is active. */
+             if (fcntl (redirector, F_GETFD, 0) != -1)
+               add_undo_redirect (redirector);
+             else
+               add_undo_close_redirect (redirector);
+           }
+
+#if defined (BUFFERED_INPUT)
+         check_bash_input (redirector);
+#endif
+         /* This is correct.  2>&1 means dup2 (1, 2); */
+         if (dup2 (redir_fd, redirector) < 0)
+           return (errno);
+
+#if defined (BUFFERED_INPUT)
+         if (ri == r_duplicating_input || ri == r_move_input)
+           duplicate_buffered_stream (redir_fd, redirector);
+#endif /* BUFFERED_INPUT */
+
+         /* First duplicate the close-on-exec state of redirectee.  dup2
+            leaves the flag unset on the new descriptor, which means it
+            stays open.  Only set the close-on-exec bit for file descriptors
+            greater than 2 in any case, since 0-2 should always be open
+            unless closed by something like `exec 2<&-'. */
+         /* if ((already_set || set_unconditionally) && (ok_to_set))
+               set_it () */
+         if (((fcntl (redir_fd, F_GETFD, 0) == 1) || (flags & RX_CLEXEC)) &&
+              (redirector > 2))
+           SET_CLOSE_ON_EXEC (redirector);
+
+         /* dup-and-close redirection */
+         if (ri == r_move_input || ri == r_move_output)
+           close (redir_fd);
+       }
+      break;
+
+    case r_close_this:
+      if (flags & RX_ACTIVE)
+       {
+         if ((flags & RX_UNDOABLE) && (fcntl (redirector, F_GETFD, 0) != -1))
+           add_undo_redirect (redirector);
+
+#if defined (BUFFERED_INPUT)
+         check_bash_input (redirector);
+         close_buffered_fd (redirector);
+#else /* !BUFFERED_INPUT */
+         close (redirector);
+#endif /* !BUFFERED_INPUT */
+       }
+      break;
+
+    case r_duplicating_input_word:
+    case r_duplicating_output_word:
+      break;
+    }
+  return (0);
+}
+
+#define SHELL_FD_BASE  10
+
+/* Remember the file descriptor associated with the slot FD,
+   on REDIRECTION_UNDO_LIST.  Note that the list will be reversed
+   before it is executed.  Any redirections that need to be undone
+   even if REDIRECTION_UNDO_LIST is discarded by the exec builtin
+   are also saved on EXEC_REDIRECTION_UNDO_LIST. */
+static int
+add_undo_redirect (fd)
+     int fd;
+{
+  int new_fd, clexec_flag;
+  REDIRECT *new_redirect, *closer, *dummy_redirect;
+
+  new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
+  if (new_fd < 0)
+    {
+      sys_error (_("redirection error: cannot duplicate fd"));
+      return (-1);
+    }
+
+  clexec_flag = fcntl (fd, F_GETFD, 0);
+
+  rd.dest = 0;
+  closer = make_redirection (new_fd, r_close_this, rd);
+  dummy_redirect = copy_redirects (closer);
+
+  rd.dest = new_fd;
+  if (fd == 0)
+    new_redirect = make_redirection (fd, r_duplicating_input, rd);
+  else
+    new_redirect = make_redirection (fd, r_duplicating_output, rd);
+  new_redirect->next = closer;
+
+  closer->next = redirection_undo_list;
+  redirection_undo_list = new_redirect;
+
+  /* Save redirections that need to be undone even if the undo list
+     is thrown away by the `exec' builtin. */
+  add_exec_redirect (dummy_redirect);
+
+  /* experimental:  if we're saving a redirection to undo for a file descriptor
+     above SHELL_FD_BASE, add a redirection to be undone if the exec builtin
+     causes redirections to be discarded. */
+  if (fd >= SHELL_FD_BASE)
+    {
+      rd.dest = new_fd;
+      new_redirect = make_redirection (fd, r_duplicating_output, rd);
+#if 0
+      closer = copy_redirects (new_redirect);
+      add_exec_redirect (closer);
+#else
+      add_exec_redirect (new_redirect);
+#endif     
+    }
+
+  /* File descriptors used only for saving others should always be
+     marked close-on-exec.  Unfortunately, we have to preserve the
+     close-on-exec state of the file descriptor we are saving, since
+     fcntl (F_DUPFD) sets the new file descriptor to remain open
+     across execs.  If, however, the file descriptor whose state we
+     are saving is <= 2, we can just set the close-on-exec flag,
+     because file descriptors 0-2 should always be open-on-exec,
+     and the restore above in do_redirection() will take care of it. */
+  if (clexec_flag || fd < 3)
+    SET_CLOSE_ON_EXEC (new_fd);
+
+  return (0);
+}
+
+/* Set up to close FD when we are finished with the current command
+   and its redirections. */
+static void
+add_undo_close_redirect (fd)
+     int fd;
+{
+  REDIRECT *closer;
+
+  rd.dest = 0;
+  closer = make_redirection (fd, r_close_this, rd);
+  closer->next = redirection_undo_list;
+  redirection_undo_list = closer;
+}
+
+static void
+add_exec_redirect (dummy_redirect)
+     REDIRECT *dummy_redirect;
+{
+  dummy_redirect->next = exec_redirection_undo_list;
+  exec_redirection_undo_list = dummy_redirect;
+}
+
+/* Return 1 if the redirection specified by RI and REDIRECTOR alters the
+   standard input. */
+static int
+stdin_redirection (ri, redirector)
+     enum r_instruction ri;
+     int redirector;
+{
+  switch (ri)
+    {
+    case r_input_direction:
+    case r_inputa_direction:
+    case r_input_output:
+    case r_reading_until:
+    case r_deblank_reading_until:
+    case r_reading_string:
+      return (1);
+    case r_duplicating_input:
+    case r_duplicating_input_word:
+    case r_close_this:
+      return (redirector == 0);
+    case r_output_direction:
+    case r_appending_to:
+    case r_duplicating_output:
+    case r_err_and_out:
+    case r_output_force:
+    case r_duplicating_output_word:
+      return (0);
+    }
+  return (0);
+}
+
+/* Return non-zero if any of the redirections in REDIRS alter the standard
+   input. */
+int
+stdin_redirects (redirs)
+     REDIRECT *redirs;
+{
+  REDIRECT *rp;
+  int n;
+
+  for (n = 0, rp = redirs; rp; rp = rp->next)
+    n += stdin_redirection (rp->instruction, rp->redirector);
+  return n;
+}
diff --git a/subst.c b/subst.c
index 1372bf80460f51e83d248b83a0cbc44dcaca1d68..85393c653787b39bf071ca292a9098a2809a4008 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -4351,7 +4351,7 @@ command_substitute (string, quoted)
      char *string;
      int quoted;
 {
-  pid_t pid, old_pid, old_pipeline_pgrp;
+  pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
   char *istring;
   int result, fildes[2], function_value, pflags, rc;
 
@@ -4399,7 +4399,14 @@ command_substitute (string, quoted)
   cleanup_the_pipeline ();
 #endif
 
+  old_async_pid = last_asynchronous_pid;
+#if 0
   pid = make_child ((char *)NULL, 0);
+#else
+  pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
+#endif
+  last_asynchronous_pid = old_async_pid;
+
   if (pid == 0)
     /* Reset the signal handlers in the child, but don't free the
        trap strings. */
index 4c1371708406867676c7dafbae3bd854da67c696..5b5c81c383ae59783c3ba85e9a457f7fa87e9299 100755 (executable)
@@ -408,7 +408,39 @@ sysv5uw7*)
 
        SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)'
        ;;
-       
+
+sysv5UnixWare*-*gcc*)
+       SHOBJ_CFLAGS=-fpic
+       SHOBJ_LD='${CC}'
+       SHOBJ_LDFLAGS='-shared'
+
+       SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)'
+       ;;
+
+sysv5UnixWare*)
+       SHOBJ_CFLAGS='-K PIC'
+       SHOBJ_LD=ld
+       SHOBJ_LDFLAGS='-G -dy -z text -h $@'
+
+       SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)'
+       ;;
+
+sysv5OpenUNIX*-*gcc*)
+       SHOBJ_CFLAGS=-fpic
+       SHOBJ_LD='${CC}'
+       SHOBJ_LDFLAGS='-shared'
+
+       SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)'
+       ;;
+
+sysv5OpenUNIX*)
+       SHOBJ_CFLAGS='-K PIC'
+       SHOBJ_LD=ld
+       SHOBJ_LDFLAGS='-G -dy -z text -h $@'
+
+       SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)'
+       ;;
+
 dgux*-*gcc*)
        SHOBJ_CFLAGS=-fpic
        SHOBJ_LD='${CC}'
index 72ec06a2c1fd8dde92acea5e8ac773e35f1d061b..3efcf32d68e9722024b6ca9d67f9e81b2aa5ac04 100755 (executable)
@@ -1,4 +1,4 @@
-BUILD_DIR=/usr/local/build/bash/bash-current
+BUILD_DIR=/usr/local/build/chet/bash/bash-current
 THIS_SH=$BUILD_DIR/bash
 PATH=$PATH:$BUILD_DIR
 
index ecb7e9a2539900a4a8e5a1b926a27484a07fdefd..b8569c11cd60a3b820a9275628467a3b0d15de61 100644 (file)
@@ -1,2 +1,2 @@
-${THIS_SH} ./tilde-tests > /tmp/xx
+${THIS_SH} ./tilde.tests > /tmp/xx
 diff /tmp/xx tilde.right && rm -f /tmp/xx