]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
posix change for undoing redirections after failed exec; change readline to set lines...
authorChet Ramey <chet.ramey@case.edu>
Tue, 28 Jan 2025 15:15:16 +0000 (10:15 -0500)
committerChet Ramey <chet.ramey@case.edu>
Tue, 28 Jan 2025 15:15:16 +0000 (10:15 -0500)
15 files changed:
CWRU/CWRU.chlog
MANIFEST
arrayfunc.c
builtins/exec.def
doc/bash.html
doc/bashref.html
execute_cmd.c
lib/readline/rlprivate.h
lib/readline/rltty.c
lib/readline/rlwinsize.h
lib/readline/signals.c
lib/readline/terminal.c
tests/exec.right
tests/exec17.sub [new file with mode: 0644]
tests/execscript

index 22738d7c9146d7dd373909cb271a64885ed76521..9824a366eb54d913db8bc6b5bef19a0aa8645d9e 100644 (file)
@@ -10870,3 +10870,54 @@ lib/readline/display.c
          characters on the current line, and set _rl_last_c_pos accordingly
          in both multibyte and singlebyte locales.
          Fixes bug reported by Andreas Schwab <schwab@linux-m68k.org>
+
+                                  1/22
+                                  ----
+execute_cmd.c
+       - execute_builtin_or_function: if we're executing the exec builtin,
+         and there are redirections, let exec_builtin handle disposing of
+         redirection_undo_list if there is no program name to execute, so
+         it's still there if exec returns and doesn't exit the shell.
+         Then we can manage disposing of exec_redirection_undo_list and
+         letting the redirections be undone as normal.
+         This is POSIX interp 1896, with modifications from
+         https://www.austingroupbugs.net/view.php?id=1896#c7037
+
+builtins/exec.def
+       - exec_builtin: dispose of redirection_undo_list and set it to NULL
+         if there is no program name operand; let execute_builtin_or_function
+         clean it up
+
+                                  1/23
+                                  ----
+lib/readline/terminal.c
+       - _rl_tcgetwinsize,_rl_tcsetwinsize: function wrappers for tcgetwinsize/
+         tcsetwinsize with fallbacks to ioctl if those functions aren't
+         available
+       - _rl_get_screensize: use _rl_tcgetwinsize
+
+lib/readline/rlwinsize.h
+       - _rl_tcgetwinsize,_rl_tcsetwinsize: extern function declarations
+
+lib/readine/rltty.c
+       - set_winsize: use _rl_tcgetwinsize/_rl_tcsetwinsize
+       - set_winsize: if _rl_tcgetwinsize succeeds, use the values to set
+         readline's idea of the screen size via _rl_set_screen_size
+         Inspired by a discussion with Olav Mørkrid <omega@funker.no>
+
+                                  1/24
+                                  ----
+lib/readline/signals.c
+       - _rl_handling_signal: new private variable, set to the signal we're
+         currently handling in _rl_signal_handler (SIGWINCH) or
+         _rl_handle_signal (all others). Only valid if RL_STATE_SIGHANDLER
+         is set
+
+lib/readline/rlprivate.h
+       - _rl_handling_signal: new extern declaration
+
+lib/readline/rltty.c
+       - set_winsize: only set readline's idea of the screen size if we're
+         executing in a signal handler context and handling SIGTSTP and the
+         application has indicated that it doesn't want the environment
+         variables LINES and COLUMNS to have priority (rl_prefer_env_winsize)
index 72d684e3344be17d345da4e2c2f91714fface655..76917764f51450a865f775cbee11548bd1bec3fe 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1181,6 +1181,7 @@ tests/exec13.sub  f
 tests/exec14.sub       f
 tests/exec15.sub       f
 tests/exec16.sub       f
+tests/exec17.sub       f
 tests/exp.tests                f
 tests/exp.right                f
 tests/exp1.sub         f
index 72921a18ef4197ee1b9d8e9c0f6ca4b609d7cfed..a553748887cb86443d1dbb1bcd9ab4f48bd0b0d8 100644 (file)
@@ -916,7 +916,7 @@ assign_array_var_from_string (SHELL_VAR *var, char *value, int flags)
     return var;
 
   nlist = expand_compound_array_assignment (var, value, flags);
-  /* This is were we set ASS_NOEXPAND and ASS_ONEWORD if we need to, since
+  /* This is where we set ASS_NOEXPAND and ASS_ONEWORD if we need to, since
      expand_compound_array_assignment performs word expansions. Honors
      array_expand_once; allows @ and * as associative array keys. */
   aflags = flags | (array_expand_once ? ASS_NOEXPAND : 0) | ASS_ALLOWALLSUB;
index 461864b5b5039b1b96ded91bae836c1fdc5d4ce0..2582add77f3c121203ebf13c6e92b504a3666c7f 100644 (file)
@@ -128,12 +128,13 @@ exec_builtin (WORD_LIST *list)
     }
   list = loptend;
 
-  /* First, let the redirections remain. */
-  dispose_redirects (redirection_undo_list);
-  redirection_undo_list = (REDIRECT *)NULL;
-
+  /* First, let the redirections remain if exec is called without operands */
   if (list == 0)
-    return (EXECUTION_SUCCESS);
+    {
+      dispose_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+      return (EXECUTION_SUCCESS);
+    }
 
 #if defined (RESTRICTED_SHELL)
   if (restricted)
index 04b3b5ba8b023417c0d7d7bb23f61eebb3ed2749..e4635097b29168707fc271820156093cda181218 100644 (file)
@@ -2122,6 +2122,8 @@ If this variable is in the environment when
 
 starts up, the shell enables each option in the list before
 reading any startup files.
+If this variable is exported, child shells will enable each option
+in the list.
 This variable is read-only.
 <DT><B>BASHPID</B>
 
@@ -4822,10 +4824,9 @@ ${<I>parameter</I><B>/</B><I>pattern</I><B>/</B><I>string</I>}
 <DT>${<I>parameter</I><B>/%</B><I>pattern</I><B>/</B><I>string</I>}<DD>
 
 <B>Pattern substitution</B>.
-The <I>pattern</I> is expanded to produce a pattern just as in
-pathname expansion and matched against the expanded value of
-<I>parameter</I>
-using the rules described under
+The <I>pattern</I> is expanded to produce a pattern
+and matched against the expanded value of <I>parameter</I>
+as described under
 <B>Pattern Matching</B>
 
 below.
@@ -4910,18 +4911,31 @@ ${<I>parameter</I><B>^</B><I>pattern</I>}
 
 <B>Case modification</B>.
 This expansion modifies the case of alphabetic characters in <I>parameter</I>.
-The <I>pattern</I> is expanded to produce a pattern just as in
-pathname expansion.
-Each character in the expanded value of <I>parameter</I> is tested against
-<I>pattern</I>, and, if it matches the pattern, its case is converted.
+First, the <I>pattern</I> is expanded to produce a pattern
+as described below under
+<FONT SIZE=-1><B>Pattern Matching</B>.
+
+</FONT>
+<B>Bash</B>
+
+then examines characters in the expanded value of <I>parameter</I>
+against <I>pattern</I> as described below.
+If a character matches the pattern, its case is converted.
 The pattern should not attempt to match more than one character.
 <DT><DD>
-The <B>^</B> operator converts lowercase letters matching <I>pattern</I>
-to uppercase; the <B>,</B> operator converts matching uppercase letters
-to lowercase.
-The <B>^^</B> and <B>,,</B> expansions convert each matched character in the
-expanded value; the <B>^</B> and <B>,</B> expansions match and convert only
-the first character in the expanded value.
+Using
+
+converts lowercase letters matching <I>pattern</I> to uppercase;
+
+converts matching uppercase letters to lowercase.
+The
+<B>^</B> and <B>,</B> variants
+examine the first character in the expanded value
+and convert its case if it matches <I>pattern</I>;
+the
+<B>^^</B> and <B>,,</B> variants
+examine all characters in the expanded value
+and convert each one that matches <I>pattern</I>.
 If <I>pattern</I> is omitted, it is treated like a <B>?</B>, which matches
 every character.
 <DT><DD>
@@ -5524,6 +5538,7 @@ as described above under
 <P>
 
 <B>Pattern Matching</B>
+
 <P>
 
 Any character that appears in a pattern, other than the special pattern
@@ -14819,9 +14834,6 @@ under
 <DD>
 <DT><B>compat44</B>
 
-<DD>
-<DT><B>compat50</B>
-
 <DD>
 
 These control aspects of the shell's compatibility mode
@@ -16523,7 +16535,11 @@ builtin command.
 <DT>*<DD>
 Importing function definitions from the shell environment at startup.
 <DT>*<DD>
-Parsing the value of
+Parsing the values of
+<FONT SIZE=-1><B>BASHOPTS</B>
+
+</FONT>
+and
 <FONT SIZE=-1><B>SHELLOPTS</B>
 
 </FONT>
@@ -16858,7 +16874,7 @@ Array variables may not (yet) be exported.
 <DT><A HREF="#lbDJ">BUGS</A><DD>
 </DL>
 <HR>
-This document was created by man2html from /usr/local/src/bash/bash-20241227/doc/bash.1.<BR>
-Time: 08 January 2025 09:33:16 EST
+This document was created by man2html from /usr/local/src/bash/bash-20250122/doc/bash.1.<BR>
+Time: 28 January 2025 09:45:18 EST
 </BODY>
 </HTML>
index 3a6275713f1562fa2a5245587fc06f53ed372452..60a62c6f9e54da44829c57a5a8ca733e31d10a90 100644 (file)
@@ -2990,11 +2990,9 @@ array in turn, and the expansion is the resultant list.
 <dt><code class="code">${<var class="var">parameter</var>//<var class="var">pattern</var>/<var class="var">string</var>}</code></dt>
 <dt><code class="code">${<var class="var">parameter</var>/#<var class="var">pattern</var>/<var class="var">string</var>}</code></dt>
 <dt><code class="code">${<var class="var">parameter</var>/%<var class="var">pattern</var>/<var class="var">string</var>}</code></dt>
-<dd><p>The <var class="var">pattern</var> is expanded to produce a pattern just as in
-filename expansion and matched
-against the expanded value of <var class="var">parameter</var>
-according to the rules
-described below (see <a class="pxref" href="#Pattern-Matching">Pattern Matching</a>).
+<dd><p>The <var class="var">pattern</var> is expanded to produce a pattern
+and matched against the expanded value of <var class="var">parameter</var>
+as described below (see <a class="pxref" href="#Pattern-Matching">Pattern Matching</a>).
 The longest match of <var class="var">pattern</var>
 in the expanded value is replaced with <var class="var">string</var>.
 <var class="var">string</var> undergoes tilde expansion, parameter and variable expansion,
@@ -3098,18 +3096,28 @@ array in turn, and the expansion is the resultant list.
 <dt><code class="code">${<var class="var">parameter</var>,<var class="var">pattern</var>}</code></dt>
 <dt><code class="code">${<var class="var">parameter</var>,,<var class="var">pattern</var>}</code></dt>
 <dd><p>This expansion modifies the case of alphabetic characters in <var class="var">parameter</var>.
-The <var class="var">pattern</var> is expanded to produce a pattern just as in
-filename expansion.
-Each character in the expanded value of <var class="var">parameter</var> is tested against
-<var class="var">pattern</var>, and, if it matches the pattern, its case is converted.
+First, the <var class="var">pattern</var> is expanded to produce a pattern
+as described below in <a class="ref" href="#Pattern-Matching">Pattern Matching</a>.
+</p>
+<p><code class="code">Bash</code>
+then examines characters in the expanded value of <var class="var">parameter</var>
+against <var class="var">pattern</var> as described below.
+If a character matches the pattern, its case is converted.
 The pattern should not attempt to match more than one character.
 </p>
-<p>The &lsquo;<samp class="samp">^</samp>&rsquo; operator converts lowercase letters matching <var class="var">pattern</var>
-to uppercase; the &lsquo;<samp class="samp">,</samp>&rsquo; operator converts matching uppercase letters
-to lowercase.
-The &lsquo;<samp class="samp">^^</samp>&rsquo; and &lsquo;<samp class="samp">,,</samp>&rsquo; expansions convert each matched character in the
-expanded value; the &lsquo;<samp class="samp">^</samp>&rsquo; and &lsquo;<samp class="samp">,</samp>&rsquo; expansions match and convert only
-the first character in the expanded value.
+<p>Using
+&lsquo;<samp class="samp">^</samp>&rsquo;
+converts lowercase letters matching <var class="var">pattern</var> to uppercase;
+&lsquo;<samp class="samp">,</samp>&rsquo;
+converts matching uppercase letters to lowercase.
+The
+&lsquo;<samp class="samp">^</samp>&rsquo; and &lsquo;<samp class="samp">,</samp>&rsquo; variants
+examine the first character in the expanded value
+and convert its case if it matches <var class="var">pattern</var>;
+the
+&lsquo;<samp class="samp">^^</samp>&rsquo; and &lsquo;<samp class="samp">,,</samp>&rsquo; variants
+examine all characters in the expanded value
+and convert each one that matches <var class="var">pattern</var>.
 If <var class="var">pattern</var> is omitted, it is treated like a &lsquo;<samp class="samp">?</samp>&rsquo;, which matches
 every character.
 </p>
@@ -7466,6 +7474,8 @@ as &lsquo;<samp class="samp">on</samp>&rsquo; by &lsquo;<samp class="samp">shopt
 If this variable is in the environment when Bash
 starts up, the shell enables each option in the list before
 reading any startup files.
+If this variable is exported, child shells will enable each option
+in the list.
 This variable is readonly.
 </p>
 </dd>
@@ -14603,6 +14613,8 @@ It may be omitted if the word designator begins with a &lsquo;<samp class="samp"
 &lsquo;<samp class="samp">*</samp>&rsquo;, &lsquo;<samp class="samp">-</samp>&rsquo;, or &lsquo;<samp class="samp">%</samp>&rsquo;.
 Words are numbered from the beginning of the line,
 with the first word being denoted by 0 (zero).
+That first word is usually the command word, and the arguments begin
+with the second word.
 Words are inserted into the current line separated by single spaces.
 </p>
 <p>For example,
@@ -14614,7 +14626,7 @@ When you type this, the preceding command is repeated in toto.
 </p>
 </dd>
 <dt><code class="code">!!:$</code></dt>
-<dd><p>designates the last argument of the preceding command.
+<dd><p>designates the last word of the preceding command.
 This may be shortened to <code class="code">!$</code>.
 </p>
 </dd>
index d4d0febdf3830d21b3d924d2797606f5bcb5d5e8..50df6c104acb348fc7530cd2b398ebc8cfd27c25 100644 (file)
@@ -5570,7 +5570,7 @@ execute_builtin_or_function (WORD_LIST *words,
                             REDIRECT *redirects, struct fd_bitmap *fds_to_close,
                             int flags)
 {
-  int result;
+  int result, has_exec_redirects;
   REDIRECT *saved_undo_list;
 #if defined (PROCESS_SUBSTITUTION)
   int ofifo, nfifo, osize;
@@ -5597,17 +5597,25 @@ execute_builtin_or_function (WORD_LIST *words,
       return (EX_REDIRFAIL);   /* was EXECUTION_FAILURE */
     }
 
+  /* Is this the exec builtin with redirections? We want to undo them and
+     throw away the exec_redirection_undo_list if exec has a program name
+     argument, fails to execute it, and does not exit the shell */
+  has_exec_redirects = (builtin == exec_builtin) && redirection_undo_list;
+
   saved_undo_list = redirection_undo_list;
 
   /* Calling the "exec" builtin changes redirections forever. */
   if (builtin == exec_builtin)
     {
-      dispose_redirects (saved_undo_list);
+      /* let exec_builtin handle disposing redirection_undo_list */
       saved_undo_list = exec_redirection_undo_list;
       exec_redirection_undo_list = (REDIRECT *)NULL;
     }
   else
-    dispose_exec_redirects ();
+    {
+      dispose_exec_redirects ();
+      redirection_undo_list = (REDIRECT *)NULL;
+    }
 
   if (saved_undo_list)
     {
@@ -5615,8 +5623,6 @@ execute_builtin_or_function (WORD_LIST *words,
       add_unwind_protect (uw_cleanup_redirects, (char *)saved_undo_list);
     }
 
-  redirection_undo_list = (REDIRECT *)NULL;
-
   if (builtin)
     result = execute_builtin (builtin, words, flags, 0);
   else
@@ -5628,26 +5634,38 @@ execute_builtin_or_function (WORD_LIST *words,
   if (ferror (stdout))
     clearerr (stdout);  
 
-  /* If we are executing the `command' builtin, but this_shell_builtin is
-     set to `exec_builtin', we know that we have something like
-     `command exec [redirection]', since otherwise `exec' would have
-     overwritten the shell and we wouldn't get here.  In this case, we
-     want to behave as if the `command' builtin had not been specified
-     and preserve the redirections. */
-  if (builtin == command_builtin && this_shell_builtin == exec_builtin)
+  if (has_exec_redirects && redirection_undo_list)
     {
-      int discard;
-
-      discard = 0;
+      /* We have returned from the exec builtin. If redirection_undo_list is
+        still non-null, we had an operand and failed to exit the shell for
+        some reason. We want to dispose of saved_undo_list, discard the frame,
+        and let the redirections be undone as usual. If redirection_undo_list
+        is NULL, then exec_builtin had no program name operand and disposed
+        of it. In that case, we should perform the redirections in
+        exec_redirection_undo_list (saved_undo_list) like usual. */
+      if (saved_undo_list)
+        {
+         dispose_redirects (saved_undo_list);  /* exec_redirection_undo_list */
+         discard_unwind_frame ("saved-redirects");
+        }
+      saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;      
+    }
+  /* This code is no longer executed and remains only for explanatory reasons. */
+  else if (builtin == command_builtin && this_shell_builtin == exec_builtin)
+    {
+      /* If we are executing the `command' builtin, but this_shell_builtin is
+        set to `exec_builtin', we know that we have something like
+        `command exec [redirection]', since otherwise `exec' would have
+        overwritten the shell and we wouldn't get here. In this case, we
+        want to behave as if the `command' builtin had not been specified
+        and preserve the redirections. */
       if (saved_undo_list)
        {
-         dispose_redirects (saved_undo_list);
-         discard = 1;
+         dispose_redirects (saved_undo_list);  /* redirection_undo_list */
+         discard_unwind_frame ("saved-redirects");
        }
       redirection_undo_list = exec_redirection_undo_list;
       saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;      
-      if (discard)
-       discard_unwind_frame ("saved-redirects");
     }
 
   if (saved_undo_list)
index 23cf8d31d5741097f65379bb405e6340065eb884..ac1de28c77e3abec7f0860774b55008ffe745dc6 100644 (file)
@@ -640,6 +640,7 @@ extern int _rl_history_search_pos;
 
 /* signals.c */
 extern int volatile _rl_caught_signal;
+extern int volatile _rl_handling_signal;
 
 extern _rl_sigcleanup_func_t *_rl_sigcleanup;
 extern void *_rl_sigcleanarg;
index a4ad94c93b71663044afafd0b3baf2fd4f4603f4..9681775aca8c391179542f26c437214c2cbdde70 100644 (file)
@@ -80,15 +80,25 @@ static int ksrflow;
 #endif
 
 /* Dummy call to force a backgrounded readline to stop before it tries
-   to get the tty settings. */
+   to get the tty settings. But we use the information to set our idea
+   of the screen size if we're in a signal handling context, since it
+   doesn't make sense to waste it. */
 static void
 set_winsize (int tty)
 {
-#if defined (TIOCGWINSZ)
+#if defined (TIOCGWINSZ) || defined (HAVE_TCGETWINSIZE)
   struct winsize w;
-
-  if (ioctl (tty, TIOCGWINSZ, &w) == 0)
-      (void) ioctl (tty, TIOCSWINSZ, &w);
+  
+  if (_rl_tcgetwinsize (tty, &w) == 0)
+    {
+      (void) _rl_tcsetwinsize (tty, &w);
+      /* We restrict this to the case where we're running a signal handler
+        and executing after a SIGTSTP. We can relax it later. */
+#if defined (SIGTSTP)
+      if (RL_ISSTATE (RL_STATE_SIGHANDLER) && _rl_handling_signal == SIGTSTP && rl_prefer_env_winsize == 0)
+       _rl_set_screen_size (w.ws_row, w.ws_col);       /* don't waste the info */
+#endif
+    }
 #endif /* TIOCGWINSZ */
 }
 
index d198fcf87232f68fba0e26ee218b5d4f2a4dec05..3d1c97fcefa34f55d91a936442a2ccf83f3d499f 100644 (file)
@@ -55,4 +55,7 @@
 #  define tcflow(fd, action)   ioctl(fd, TCXONC, action)
 #endif
 
+extern int _rl_tcgetwinsize (int, struct winsize *);
+extern void _rl_tcsetwinsize (int, struct winsize *);
+
 #endif /* _RL_WINSIZE_H */
index 1cdb762981465e744baf32522e25eb89a2f81b39..8c4f3fad20380b23ba75419d5ebff0157692466d 100644 (file)
@@ -88,6 +88,7 @@ int rl_catch_sigwinch = 0;    /* for the readline state struct in readline.c */
 
 /* Private variables. */
 int volatile _rl_caught_signal = 0;    /* should be sig_atomic_t, but that requires including <signal.h> everywhere */
+int volatile _rl_handling_signal = 0;
 
 /* If non-zero, print characters corresponding to received signals as long as
    the user has indicated his desire to do so (_rl_echo_control_chars). */
@@ -133,6 +134,7 @@ _rl_signal_handler (int sig)
   if (sig == SIGWINCH)
     {
       RL_SETSTATE(RL_STATE_SIGHANDLER);
+      _rl_handling_signal = SIGWINCH;
 
       rl_resize_terminal ();
       /* XXX - experimental for now */
@@ -142,6 +144,7 @@ _rl_signal_handler (int sig)
       if (rl_signal_event_hook)
        (*rl_signal_event_hook) ();
 
+      _rl_handling_signal = 0;
       RL_UNSETSTATE(RL_STATE_SIGHANDLER);
     }
   else
@@ -177,6 +180,7 @@ _rl_handle_signal (int sig)
 #endif /* !HAVE_POSIX_SIGNALS */
 
   RL_SETSTATE(RL_STATE_SIGHANDLER);
+  _rl_handling_signal = sig;
 
 #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
   /* Since the signal will not be blocked while we are in the signal
@@ -301,6 +305,7 @@ _rl_handle_signal (int sig)
       rl_reset_after_signal ();      
     }
 
+  _rl_handling_signal = 0;
   RL_UNSETSTATE(RL_STATE_SIGHANDLER);
   SIGHANDLER_RETURN;
 }
index 7003d2a97d99cef0f10335bafd97ce6692643637..2c70553d1c9dcec96f45ec001c5ffa953a652ef5 100644 (file)
@@ -258,6 +258,30 @@ _win_get_screensize (int *swp, int *shp)
 }
 #endif
 
+int
+_rl_tcgetwinsize (int tty, struct winsize *wp)
+{
+#if defined (HAVE_TCGETWINSIZE)
+  return (tcgetwinsize (tty, wp));
+#elif defined (TIOCGWINSZ)
+  return (ioctl (tty, TIOCGWINSZ, wp));
+#else
+  return -1;
+#endif
+}
+
+void
+_rl_tcsetwinsize (int tty, struct winsize *wp)
+{
+#if defined (HAVE_TCGETWINSIZE)
+  tcsetwinsize (tty, wp);
+#elif defined (TIOCGWINSZ)
+  ioctl (tty, TIOCSWINSZ, wp);
+#else
+  ;
+#endif
+}
+
 /* Get readline's idea of the screen size.  TTY is a file descriptor open
    to the terminal.  If IGNORE_ENV is true, we do not pay attention to the
    values of $LINES and $COLUMNS.  The tests for TERM_STRING_BUFFER being
@@ -266,19 +290,19 @@ void
 _rl_get_screen_size (int tty, int ignore_env)
 {
   char *ss;
-#if defined (TIOCGWINSZ)
+#if defined (TIOCGWINSZ) || defined (HAVE_TCGETWINSIZE)
   struct winsize window_size;
-#endif /* TIOCGWINSZ */
+#endif /* TIOCGWINSZ || HAVE_TCGETWINSIZE */
   int wr, wc;
 
   wr = wc = -1;
-#if defined (TIOCGWINSZ)
-  if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
+#if defined (TIOCGWINSZ) || defined (HAVE_TCGETWINSIZE)
+  if (_rl_tcgetwinsize (tty, &window_size) == 0)
     {
       wc = (int) window_size.ws_col;
       wr = (int) window_size.ws_row;
     }
-#endif /* TIOCGWINSZ */
+#endif /* TIOCGWINSZ || HAVE_TCGETWINSIZE */
 
 #if defined (__EMX__)
   _emx_get_screensize (&wc, &wr);
index d584d805788f529aaaca30fac6d5e764a42efae1..0116f202f8965c982736acaa8f794dd95c08f591 100644 (file)
@@ -247,3 +247,25 @@ reached AND-AND body
 reached OR-OR body
 reached AND-AND group
 reached OR-OR group
+./exec17.sub: line 26: exec: notthere: not found
+after failed exec: 127
+./exec17.sub: line 31: exec: notthere: not found
+after failed exec with output redirection
+./exec17.sub: line 36: exec: notthere: not found
+./exec17.sub: line 37: 4: Bad file descriptor
+./exec17.sub: line 40: .: Is a directory
+after failed redir stdout
+after failed redir stderr
+./exec17.sub: line 44: exec: notthere: not found
+after failed exec with input redirection
+./exec17.sub: line 50: exec: notthere: not found
+after failed exec: 127
+./exec17.sub: line 55: exec: notthere: not found
+after failed exec with output redirection
+./exec17.sub: line 60: exec: notthere: not found
+./exec17.sub: line 61: 4: Bad file descriptor
+./exec17.sub: line 64: .: Is a directory
+after failed redir stdout
+after failed redir stderr
+./exec17.sub: line 68: exec: notthere: not found
+after failed exec with input redirection
diff --git a/tests/exec17.sub b/tests/exec17.sub
new file mode 100644 (file)
index 0000000..55b0507
--- /dev/null
@@ -0,0 +1,69 @@
+#   This program 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 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# test behavior of redirections when the shell doesn't exit and exec gets a
+# program name to execute as an operand
+
+# set up a fixed path so we know notthere will not be found
+PATH=/usr/bin:/bin
+export PATH
+
+FN=/tmp/output-$$
+shopt -s execfail
+
+# make sure execfail works right, otherwise none of the rest matters
+exec notthere
+echo after failed exec: $?
+
+# basic redirection undoing if exec fails
+rm -f $FN
+exec notthere >$FN
+echo after failed exec with output redirection
+rm -f $FN
+
+# undo successful redirections if exec fails but does not exit the shell
+exec notthere 4>&2
+echo foo >&4
+
+# we should undo successful redirects if one of the redirections fails
+exec >$FN 2>.
+echo after failed redir stdout
+echo after failed redir stderr >&2
+
+exec notthere <<<'foo bar baz'
+echo after failed exec with input redirection
+
+# the command builtin should not make a difference here
+
+# make sure execfail works right, otherwise none of the rest matters
+command exec notthere
+echo after failed exec: $?
+
+# basic redirection undoing if exec fails
+rm -f $FN
+command exec notthere >$FN
+echo after failed exec with output redirection
+rm -f $FN
+
+# undo successful redirections if exec fails but does not exit the shell
+command exec notthere 4>&2
+echo foo >&4
+
+# we should undo successful redirects if one of the redirections fails
+command exec >$FN 2>.
+echo after failed redir stdout
+echo after failed redir stderr >&2
+
+command exec notthere <<<'foo bar baz'
+echo after failed exec with input redirection
index 6dad13c98cd956394c77ce442b9cdca2b5a77925..aad37be4feff006a72183ca785dd83060a3495cb 100644 (file)
@@ -204,3 +204,6 @@ ${THIS_SH} ./exec15.sub
 
 # problems with set -e and inverting commands' return status
 ${THIS_SH} ./exec16.sub
+
+# test behavior of redirections when exec fails and does not exit the shell
+${THIS_SH} ./exec17.sub