]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
make completion of nofork comsubs a little better; fix leaks on signals for non-incre...
authorChet Ramey <chet.ramey@case.edu>
Sat, 27 Jan 2024 21:28:31 +0000 (16:28 -0500)
committerChet Ramey <chet.ramey@case.edu>
Sat, 27 Jan 2024 21:28:31 +0000 (16:28 -0500)
CWRU/CWRU.chlog
bashline.c
braces.c
lib/readline/callback.c
lib/readline/readline.h
lib/readline/rlprivate.h
lib/readline/search.c
lib/readline/signals.c
lib/readline/text.c

index 9912f727358a277b87d12aef5e69a9c8b5dec712..fc38e0baf255c66491b098f492f156db1548777d 100644 (file)
@@ -8371,3 +8371,68 @@ subst.c
        - function_substitute: unwind-protect current_builtin and this_shell_builtin
          like we do this_shell_function
          From a fuzzing report by Nathan Mills <the.true.nathan.mills@gmail.com>
+
+                                  1/24
+                                  ----
+braces.c
+       - brace_gobbler: handle nofork command substitutions; skip over any
+         enclosed command and any braces it contains
+
+bashline.c
+       - check_redir: return 0 if we're in a nofork comsub, so we will attempt
+         command word completion if appropriate
+
+                                  1/26
+                                  ----
+lib/readline/readline.h
+       - RL_STATE_READSTR: new state flag saying we are reading an arbitrary
+         string from the keyboard using rl_readstr
+
+lib/readline/rlprivate.h
+       - READSTR_FREEPMT: new context state flag for rl_readstr; indicates
+         that we have allocated a new prompt with _rl_make_prompt_for_search
+         and we should free it with rl_restore_prompt because rl_clear_message
+         will not do it
+
+lib/readline/text.c
+       - _rl_readstr_init,_rl_readstr_cleanup: set and unset RL_STATE_READSTR
+       - _rl_unsave_saved_readstr_line: free any rl_undo_list, which we may
+         have accumulated while reading the string, before restoring the line
+         Fixes leaks reported by sparrowhawk996@gmail.com.
+       - _rl_readstr_init: set the READSTR_FREEPMT context flag after we
+         call _rl_make_prompt_for_search, which calls rl_save_prompt
+       - _rl_readstr_sigcleanup: new function to call from signal cleanup;
+         restores prompt and calls _rl_readstr_cleanup to free the readstr
+         context
+       - _rl_readstr_restore: if the RL_READSTR_FREEPMT flag is set in the
+         context, call rl_restore_prompt to deallocate the prompt we created
+
+lib/readline/callback.c
+       - rl_callback_sigcleanup: call _rl_readstr_sigcleanup to deallocate
+         readstr state on a signal
+
+lib/readline/text.c
+       - rl_execute_named_command: free COMMAND before returning
+
+                                  1/27
+                                  ----
+lib/readline/rlprivate.h
+       - SF_FREEPMT: new flag for non-incremental search contexts: means we
+         saved the prompt data with _rl_make_prompt_for_search and need to
+         restore it with rl_restore_prompt, since rl_clear_message will not
+
+lib/readline/search.c
+       - _rl_nsearch_sigcleanup: new function that if calls rl_restore_prompt
+         to clean up the saved prompt data if necessary before calling the
+         context cleanup function, avoids memory leak
+       - _rl_nsearch_init: set the SF_FREEPMPT flag after calling
+         _rl_make_prompt_from_search so we can clean it up properly on errors
+       - _rl_nsearch_abort,_rl_nsearch_dosearch: call rl_restore_prompt only
+         if cxt->sflags includes SF_FREEPMT, manage SF_FREEPMT state
+
+lib/readline/signals.c
+       - _rl_state_sigcleanup: call _rl_nsearch_sigcleanup
+
+lib/readline/callback.c
+       - _rl_callback_sigcleanup: call _rl_nsearch_sigcleanup
+
index 8ba34a8162c1db7ab755af9f979955b0734d20e9..c11484ecfe4469d37c34aea447e7b8db37a45ae7 100644 (file)
@@ -1385,17 +1385,18 @@ bash_spell_correct_shellword (int count, int key)
 static inline int
 check_redir (int ti)
 {
-  register int this_char, prev_char;
+  int this_char, prev_char, next_char;
 
   /* Handle the two character tokens `>&', `<&', and `>|'.
      We are not in a command position after one of these. */
   this_char = rl_line_buffer[ti];
   prev_char = (ti > 0) ? rl_line_buffer[ti - 1] : 0;
+  next_char = (ti < rl_end) ? rl_line_buffer[ti + 1] : 0;
 
   if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
       (this_char == '|' && prev_char == '>'))
     return (1);
-  else if (this_char == '{' && prev_char == '$') /*}*/
+  else if (this_char == '{' && prev_char == '$' && FUNSUB_CHAR (next_char) == 0) /*}*/
     return (1);
 #if 0  /* Not yet */
   else if (this_char == '(' && prev_char == '$') /*)*/
@@ -1789,6 +1790,8 @@ bash_default_completion (const char *text, int start, int end, int qc, int compf
     {
       if (qc != '\'' && text[1] == '(') /* ) */
        matches = rl_completion_matches (text, command_subst_completion_function);
+      else if (qc != '\'' && text[1] == '{' && FUNSUB_CHAR (text[2])) /* } */
+       matches = rl_completion_matches (text, command_subst_completion_function);
       else
        {
          matches = rl_completion_matches (text, variable_completion_function);
@@ -2401,6 +2404,8 @@ command_subst_completion_function (const char *text, int state)
        text++;
       else if (*text == '$' && text[1] == '(') /* ) */
        text += 2;
+      else if (*text == '$' && text[1] == '{' && FUNSUB_CHAR (text[2])) /*}*/
+       text += 3;      /* nofork command substitution */
       /* If the text was quoted, suppress any quote character that the
         readline completion code would insert. */
       rl_completion_suppress_quote = 1;
index bef62ea38d2679fc5baa896a3baf4775c6be605d..e2517c9819fba878541bec59a2f5575052182786 100644 (file)
--- a/braces.c
+++ b/braces.c
@@ -38,6 +38,7 @@
 
 #if defined (SHELL)
 #  include "shell.h"
+#  include "parser.h"          /* FUNSUB_CHAR */
 #else
 #  if defined (TEST)
 typedef char *WORD_DESC;
@@ -619,33 +620,34 @@ brace_gobbler (char *text, size_t tlen, int *indx, int satisfy)
 
 #if defined (SHELL)
       /* If compiling for the shell, treat ${...} like \{...} */
-      if (c == '$' && text[i+1] == '{' && quoted != '\'')              /* } */
+      if (c == '$' && i < tlen && text[i+1] == '{' && quoted != '\'')          /* } */
        {
-#if 0
-         /* If we want to inhibit brace expansion during parameter expansions,
-            we need to skip over parameter expansions here. This is easier
-            than teaching brace expansion about the idiosyncracies of shell
-            word expansion. */
-         int o, f;
-         o = no_longjmp_on_fatal_error;
-         no_longjmp_on_fatal_error = 1;
-         f = (quoted == '"') ? Q_DOUBLE_QUOTES : 0;
-         si = i + 2;
-         t = extract_dollar_brace_string (text, &si, f, SX_NOALLOC|SX_NOLONGJMP|SX_COMPLETE|SX_NOERROR);
-         i = si + 1;
-         no_longjmp_on_fatal_error = o;
-         if (i > tlen)
+#if 1
+         /* nofork command substitution */
+         if (i < tlen - 1 && FUNSUB_CHAR (text[i+2]))
            {
-             i = tlen;
-             c = 0;
-             break;
+             int o, f;
+funsub:
+             o = no_longjmp_on_fatal_error;
+             no_longjmp_on_fatal_error = 1;
+             f = (quoted == '"') ? Q_DOUBLE_QUOTES : 0;
+             si = i + 2;
+             t = extract_function_subst (text, &si, f, SX_NOALLOC|SX_NOLONGJMP|SX_NOERROR);
+             i = si + 1;
+             no_longjmp_on_fatal_error = o;
+             if (i > tlen)
+               {
+                 i = tlen;
+                 c = 0;
+                 break;
+               }
+             continue;
            }
-#else
+#endif
          pass_next = 1;
          i++;
          if (quoted == 0)
            level++;
-#endif
          continue;
        }
 #endif
@@ -656,7 +658,7 @@ brace_gobbler (char *text, size_t tlen, int *indx, int satisfy)
            quoted = 0;
 #if defined (SHELL)
          /* The shell allows quoted command substitutions */
-         if (quoted == '"' && c == '$' && text[i+1] == '(')    /*)*/
+         if (quoted == '"' && c == '$' && i < tlen && text[i+1] == '(')        /*)*/
            goto comsub;
 #endif
 #if defined (SHELL)
@@ -676,7 +678,7 @@ brace_gobbler (char *text, size_t tlen, int *indx, int satisfy)
 
 #if defined (SHELL)
       /* Pass new-style command and process substitutions through unchanged. */
-      if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(')                      /* ) */
+      if ((c == '$' || c == '<' || c == '>') && i < tlen && text[i+1] == '(')  /* ) */
        {
          int o;
 
@@ -684,11 +686,7 @@ comsub:
          o = no_longjmp_on_fatal_error;
          no_longjmp_on_fatal_error = 1;
          si = i + 2;
-#if 0
-         t = extract_command_subst (text, &si, SX_NOALLOC|SX_NOLONGJMP|SX_NOERROR|SX_COMPLETE);
-#else
          t = extract_command_subst (text, &si, SX_NOALLOC|SX_NOLONGJMP|SX_NOERROR);
-#endif
          i = si + 1;
          no_longjmp_on_fatal_error = o;
          if (i > tlen)
index d78a7ca77c5078c39cf9617ddcc45eca68e63298..d376f948f60d9d80cd9b5332b7cf5f5c0ec525f9 100644 (file)
@@ -363,7 +363,7 @@ rl_callback_sigcleanup (void)
   if (RL_ISSTATE (RL_STATE_ISEARCH))
     _rl_isearch_cleanup (_rl_iscxt, 0);
   else if (RL_ISSTATE (RL_STATE_NSEARCH))
-    _rl_nsearch_cleanup (_rl_nscxt, 0);
+    _rl_nsearch_sigcleanup (_rl_nscxt, 0);
   else if (RL_ISSTATE (RL_STATE_VIMOTION))
     RL_UNSETSTATE (RL_STATE_VIMOTION);
   else if (RL_ISSTATE (RL_STATE_NUMERICARG))
@@ -373,6 +373,9 @@ rl_callback_sigcleanup (void)
     }
   else if (RL_ISSTATE (RL_STATE_MULTIKEY))
     RL_UNSETSTATE (RL_STATE_MULTIKEY);
+  else if (RL_ISSTATE (RL_STATE_READSTR))
+    _rl_readstr_sigcleanup (_rl_rscxt, 0);
+
   if (RL_ISSTATE (RL_STATE_CHARSEARCH))
     RL_UNSETSTATE (RL_STATE_CHARSEARCH);
 
index f8c356e50e191b2c5ce7d4ac763e16ba64f473b7..3224706f72bf7a626f789e03096f07ee1b315fe2 100644 (file)
@@ -914,37 +914,40 @@ extern int rl_persistent_signal_handlers;
 #define MULT_MATCH      2
 
 /* Possible state values for rl_readline_state */
-#define RL_STATE_NONE          0x000000                /* no state; before first call */
-
-#define RL_STATE_INITIALIZING  0x0000001       /* initializing */
-#define RL_STATE_INITIALIZED   0x0000002       /* initialization done */
-#define RL_STATE_TERMPREPPED   0x0000004       /* terminal is prepped */
-#define RL_STATE_READCMD       0x0000008       /* reading a command key */
-#define RL_STATE_METANEXT      0x0000010       /* reading input after ESC */
-#define RL_STATE_DISPATCHING   0x0000020       /* dispatching to a command */
-#define RL_STATE_MOREINPUT     0x0000040       /* reading more input in a command function */
-#define RL_STATE_ISEARCH       0x0000080       /* doing incremental search */
-#define RL_STATE_NSEARCH       0x0000100       /* doing non-inc search */
-#define RL_STATE_SEARCH                0x0000200       /* doing a history search */
-#define RL_STATE_NUMERICARG    0x0000400       /* reading numeric argument */
-#define RL_STATE_MACROINPUT    0x0000800       /* getting input from a macro */
-#define RL_STATE_MACRODEF      0x0001000       /* defining keyboard macro */
-#define RL_STATE_OVERWRITE     0x0002000       /* overwrite mode */
-#define RL_STATE_COMPLETING    0x0004000       /* doing completion */
-#define RL_STATE_SIGHANDLER    0x0008000       /* in readline sighandler */
-#define RL_STATE_UNDOING       0x0010000       /* doing an undo */
-#define RL_STATE_INPUTPENDING  0x0020000       /* rl_execute_next called */
-#define RL_STATE_TTYCSAVED     0x0040000       /* tty special chars saved */
-#define RL_STATE_CALLBACK      0x0080000       /* using the callback interface */
-#define RL_STATE_VIMOTION      0x0100000       /* reading vi motion arg */
-#define RL_STATE_MULTIKEY      0x0200000       /* reading multiple-key command */
-#define RL_STATE_VICMDONCE     0x0400000       /* entered vi command mode at least once */
-#define RL_STATE_CHARSEARCH    0x0800000       /* vi mode char search */
-#define RL_STATE_REDISPLAYING  0x1000000       /* updating terminal display */
-
-#define RL_STATE_DONE          0x2000000       /* done; accepted line */
-#define RL_STATE_TIMEOUT       0x4000000       /* done; timed out */
-#define RL_STATE_EOF           0x8000000       /* done; got eof on read */
+#define RL_STATE_NONE          0x0000000       /* no state; before first call */
+
+#define RL_STATE_INITIALIZING  0x00000001      /* initializing */
+#define RL_STATE_INITIALIZED   0x00000002      /* initialization done */
+#define RL_STATE_TERMPREPPED   0x00000004      /* terminal is prepped */
+#define RL_STATE_READCMD       0x00000008      /* reading a command key */
+#define RL_STATE_METANEXT      0x00000010      /* reading input after ESC */
+#define RL_STATE_DISPATCHING   0x00000020      /* dispatching to a command */
+#define RL_STATE_MOREINPUT     0x00000040      /* reading more input in a command function */
+#define RL_STATE_ISEARCH       0x00000080      /* doing incremental search */
+#define RL_STATE_NSEARCH       0x00000100      /* doing non-inc search */
+#define RL_STATE_SEARCH                0x00000200      /* doing a history search */
+#define RL_STATE_NUMERICARG    0x00000400      /* reading numeric argument */
+#define RL_STATE_MACROINPUT    0x00000800      /* getting input from a macro */
+#define RL_STATE_MACRODEF      0x00001000      /* defining keyboard macro */
+#define RL_STATE_OVERWRITE     0x00002000      /* overwrite mode */
+#define RL_STATE_COMPLETING    0x00004000      /* doing completion */
+#define RL_STATE_SIGHANDLER    0x00008000      /* in readline sighandler */
+#define RL_STATE_UNDOING       0x00010000      /* doing an undo */
+#define RL_STATE_INPUTPENDING  0x00020000      /* rl_execute_next called */
+#define RL_STATE_TTYCSAVED     0x00040000      /* tty special chars saved */
+#define RL_STATE_CALLBACK      0x00080000      /* using the callback interface */
+#define RL_STATE_VIMOTION      0x00100000      /* reading vi motion arg */
+#define RL_STATE_MULTIKEY      0x00200000      /* reading multiple-key command */
+#define RL_STATE_VICMDONCE     0x00400000      /* entered vi command mode at least once */
+#define RL_STATE_CHARSEARCH    0x00800000      /* vi mode char search */
+#define RL_STATE_REDISPLAYING  0x01000000      /* updating terminal display */
+
+#define RL_STATE_DONE          0x02000000      /* done; accepted line */
+#define RL_STATE_TIMEOUT       0x04000000      /* done; timed out */
+#define RL_STATE_EOF           0x08000000      /* done; got eof on read */
+
+/* Rearrange these for next major version */
+#define RL_STATE_READSTR       0x10000000      /* reading a string for M-x */
 
 #define RL_SETSTATE(x)         (rl_readline_state |= (x))
 #define RL_UNSETSTATE(x)       (rl_readline_state &= ~(x))
index 461617c4b691362776db8d6e25bb7fd2d476c0e2..a2ab98bc1487c77777f7ee75f73c79fc2bc281db 100644 (file)
@@ -67,6 +67,7 @@
 #define SF_CHGKMAP             0x08
 #define SF_PATTERN             0x10
 #define SF_NOCASE              0x20            /* unused so far */
+#define SF_FREEPMT             0x40            /* saved prompt separately, need to free it */
 
 typedef struct  __rl_search_context
 {
@@ -111,7 +112,8 @@ typedef struct  __rl_search_context
 } _rl_search_cxt;
 
 /* readstr flags */
-#define RL_READSTR_NOSPACE     0x01    /* don't insert space, use for completion */
+#define READSTR_NOSPACE        0x01    /* don't insert space, use for completion */
+#define READSTR_FREEPMT        0x02    /* called rl_save_prompt, need to free it ourselves */
 
 typedef struct  __rl_readstr_context
 {
@@ -432,6 +434,7 @@ extern int _rl_restore_tty_signals (void);
 /* search.c */
 extern int _rl_nsearch_callback (_rl_search_cxt *);
 extern int _rl_nsearch_cleanup (_rl_search_cxt *, int);
+extern int _rl_nsearch_sigcleanup (_rl_search_cxt *, int);
 
 extern void _rl_free_saved_search_line (void);
 
@@ -443,6 +446,8 @@ extern void _rl_release_sigint (void);
 extern void _rl_block_sigwinch (void);
 extern void _rl_release_sigwinch (void);
 
+extern void _rl_state_sigcleanup (void);
+
 /* terminal.c */
 extern void _rl_get_screen_size (int, int);
 extern void _rl_sigwinch_resize_terminal (void);
@@ -488,6 +493,7 @@ extern void _rl_free_saved_readstr_line (void);
 extern void _rl_unsave_saved_readstr_line (void);
 extern _rl_readstr_cxt *_rl_readstr_init (int, int);
 extern int _rl_readstr_cleanup (_rl_readstr_cxt *, int);
+extern int _rl_readstr_sigcleanup (_rl_readstr_cxt *, int);
 extern void _rl_readstr_restore (_rl_readstr_cxt *);
 extern int _rl_readstr_getchar (_rl_readstr_cxt *);
 extern int _rl_readstr_dispatch (_rl_readstr_cxt *, int);
index 37db052ecc54b47daab724328e99402c8dca2d99..6b078d7c243a2601e10f9ed61fb6631add6ceaff 100644 (file)
@@ -286,6 +286,7 @@ _rl_nsearch_init (int dir, int pchar)
   rl_end = rl_point = 0;
 
   p = _rl_make_prompt_for_search (pchar ? pchar : ':');
+  cxt->sflags |= SF_FREEPMT;
   rl_message ("%s", p);
   xfree (p);
 
@@ -313,13 +314,24 @@ _rl_nsearch_abort (_rl_search_cxt *cxt)
   _rl_unsave_saved_search_line ();
   rl_point = cxt->save_point;
   rl_mark = cxt->save_mark;
-  rl_restore_prompt ();
+  if (cxt->sflags & SF_FREEPMT)
+    rl_restore_prompt ();              /* _rl_make_prompt_for_search saved it */
+  cxt->sflags &= ~SF_FREEPMT;
   rl_clear_message ();
   _rl_fix_point (1);
 
   RL_UNSETSTATE (RL_STATE_NSEARCH);
 }
 
+int
+_rl_nsearch_sigcleanup (_rl_search_cxt *cxt, int r)
+{
+  if (cxt->sflags & SF_FREEPMT)
+    rl_restore_prompt ();              /* _rl_make_prompt_for_search saved it */
+  cxt->sflags &= ~SF_FREEPMT;
+  return (_rl_nsearch_cleanup (cxt, r));
+}
+
 /* Process just-read character C according to search context CXT.  Return -1
    if the caller should abort the search, 0 if we should break out of the
    loop, and 1 if we should continue to read characters. */
@@ -427,7 +439,9 @@ _rl_nsearch_dosearch (_rl_search_cxt *cxt)
        {
          _rl_free_saved_search_line ();
          rl_ding ();
-         rl_restore_prompt ();
+         if (cxt->sflags & SF_FREEPMT)
+           rl_restore_prompt ();
+         cxt->sflags &= ~SF_FREEPMT;
          RL_UNSETSTATE (RL_STATE_NSEARCH);
          return -1;
        }
@@ -452,7 +466,9 @@ _rl_nsearch_dosearch (_rl_search_cxt *cxt)
 #endif
     }
 
-  rl_restore_prompt ();
+  if (cxt->sflags & SF_FREEPMT)
+    rl_restore_prompt ();
+  cxt->sflags &= ~SF_FREEPMT;
   return (noninc_dosearch (noninc_search_string, cxt->direction, cxt->sflags&SF_PATTERN));
 }
 
index 51d746809f3b5e7940dc3f89322663e71ba55af4..92dd2ffc94a4904dbc559d83e36dee1f1df9f07d 100644 (file)
@@ -585,6 +585,19 @@ rl_reset_after_signal (void)
   rl_set_signals ();
 }
 
+/* Similar to rl_callback_sigcleanup, but cleans up operations that allocate
+   state even when not in callback mode. */
+void
+_rl_state_sigcleanup (void)
+{
+  if (RL_ISSTATE (RL_STATE_ISEARCH))           /* incremental search */
+    _rl_isearch_cleanup (_rl_iscxt, 0);
+  else if (RL_ISSTATE (RL_STATE_NSEARCH))      /* non-incremental search */
+    _rl_nsearch_sigcleanup (_rl_nscxt, 0);
+  else if (RL_ISSTATE (RL_STATE_READSTR))      /* reading a string */
+    _rl_readstr_sigcleanup (_rl_rscxt, 0);
+}
+
 /* Free up the readline variable line state for the current line (undo list,
    any partial history entry, any keyboard macros in progress, and any
    numeric arguments in process) after catching a signal, before calling
@@ -594,6 +607,9 @@ rl_free_line_state (void)
 {
   register HIST_ENTRY *entry;
 
+  if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
+    _rl_state_sigcleanup ();
+
   rl_free_undo_list ();
 
   entry = current_history ();
index 25e848492cd3c1b81a4703cdd63a5de273d10d1f..e8bf4506a21494e78ae1d390ae8f903f926f14f8 100644 (file)
@@ -1971,10 +1971,13 @@ _rl_rscxt_dispose (_rl_readstr_cxt *cxt, int flags)
   xfree (cxt);
 }
 
+/* This isn't used yet */
 void
 _rl_free_saved_readstr_line ()
 {
   if (_rl_saved_line_for_readstr)
+    /* This doesn't free any saved undo list, if it needs to,
+       rl_clear_history shows how to do it. */
     _rl_free_saved_line (_rl_saved_line_for_readstr);
   _rl_saved_line_for_readstr = (HIST_ENTRY *)NULL;
 }
@@ -1983,7 +1986,10 @@ void
 _rl_unsave_saved_readstr_line ()
 {
   if (_rl_saved_line_for_readstr)
-    _rl_unsave_line (_rl_saved_line_for_readstr);
+    {
+      _rl_free_undo_list (rl_undo_list);
+      _rl_unsave_line (_rl_saved_line_for_readstr);    /* restores rl_undo_list */
+    }
   _rl_saved_line_for_readstr = (HIST_ENTRY *)NULL;
 }
 
@@ -2004,9 +2010,12 @@ _rl_readstr_init (int pchar, int flags)
   rl_end = rl_point = 0;
 
   p = _rl_make_prompt_for_search (pchar ? pchar : '@');
+  cxt->flags |= READSTR_FREEPMT;
   rl_message ("%s", p);
   xfree (p);
 
+  RL_SETSTATE (RL_STATE_READSTR);
+
   _rl_rscxt = cxt;  
 
   return cxt;
@@ -2018,6 +2027,8 @@ _rl_readstr_cleanup (_rl_readstr_cxt *cxt, int r)
   _rl_rscxt_dispose (cxt, 0);
   _rl_rscxt = 0;
 
+  RL_UNSETSTATE (RL_STATE_READSTR);
+
   return (r != 1);
 }
 
@@ -2027,11 +2038,22 @@ _rl_readstr_restore (_rl_readstr_cxt *cxt)
   _rl_unsave_saved_readstr_line ();    /* restores rl_undo_list */
   rl_point = cxt->save_point;
   rl_mark = cxt->save_mark;
-  rl_restore_prompt ();                /* _rl_make_prompt_for_search saved it */
+  if (cxt->flags & READSTR_FREEPMT)
+    rl_restore_prompt ();              /* _rl_make_prompt_for_search saved it */
+  cxt->flags &= ~READSTR_FREEPMT;
   rl_clear_message ();
   _rl_fix_point (1);
 }
 
+int
+_rl_readstr_sigcleanup (_rl_readstr_cxt *cxt, int r)
+{
+  if (cxt->flags & READSTR_FREEPMT)
+    rl_restore_prompt ();              /* _rl_make_prompt_for_search saved it */
+  cxt->flags &= ~READSTR_FREEPMT;
+  return (_rl_readstr_cleanup (cxt, r));
+}
+  
 int   
 _rl_readstr_getchar (_rl_readstr_cxt *cxt)
 {
@@ -2130,7 +2152,7 @@ _rl_readstr_dispatch (_rl_readstr_cxt *cxt, int c)
       break;
 
     case ' ':
-      if ((cxt->flags & RL_READSTR_NOSPACE) == 0)
+      if ((cxt->flags & READSTR_NOSPACE) == 0)
        {
          _rl_insert_char (1, c);
          break;
@@ -2273,7 +2295,7 @@ _rl_read_command_name ()
   char *ret;
   int c, r;
 
-  cxt = _rl_readstr_init ('!', RL_READSTR_NOSPACE);
+  cxt = _rl_readstr_init ('!', READSTR_NOSPACE);
   cxt->compfunc = _rl_readcmd_complete;
 
   /* skip callback stuff for now */
@@ -2344,5 +2366,6 @@ rl_execute_named_command (int count, int key)
       r = 1;
     }
 
+  free (command);
   return r;
 }