mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 23:53:18 +02:00
commit bash-20161104 snapshot
This commit is contained in:
+60
-1
@@ -12105,7 +12105,7 @@ examples/loadables/rm.c
|
||||
<tim.ruehsen@gmx.de>, heavily rewritten for inclusion as loadable
|
||||
|
||||
examples/loadables/Makefile.in
|
||||
- rm: add rules to build rm as one of the standard targets
|
||||
- rm: add rules to build rm as one of the `other' targets
|
||||
|
||||
examples/loadables/stat.c
|
||||
- stat: new loadable builtin that takes a filename and loads the info
|
||||
@@ -12140,3 +12140,62 @@ subst.c
|
||||
- process_substitute: call discard_last_procsub_child instead of
|
||||
calling discard_pipeline directly. Fixes bug reported by
|
||||
Christian Weisgerber <naddy@mips.inka.de>
|
||||
|
||||
11/3
|
||||
----
|
||||
shell.h
|
||||
- EX_DISKFALLBACK: new special return status available to builtins;
|
||||
means to attempt to execute a disk command with the same name as
|
||||
the builtin
|
||||
|
||||
examples/loadables/rm.c
|
||||
- if we see the -i option, return EX_DISKFALLBACK
|
||||
|
||||
execute_cmd.c
|
||||
- execute_simple_command: if executing a builtin returns EX_DISKFALLBACK,
|
||||
try running execute_disk_command instead
|
||||
|
||||
bashline.c
|
||||
- shell_expand_line: use expand_word to expand the readline line
|
||||
buffer, which allows us to pass flags with the word. If a numeric
|
||||
argument is supplied, do not perform quote removal (pass
|
||||
Q_HERE_DOCUMENT since here-doc quoting does the right thing) and
|
||||
do not perform command or process subsitution. From a suggestion
|
||||
by Dabrien 'Dabe' Murphy <dabe@dabe.com> based on an old bug-bash
|
||||
discussion
|
||||
|
||||
subst.c
|
||||
- expand_word_internal: note that we have added a quoted IFS char to
|
||||
istring by setting sentinel has_quoted_ifs. Usually we only add
|
||||
one if we are not going to be performing word splitting, but we
|
||||
will not perform word splitting if there's no expansion, so we need
|
||||
to take care of that case
|
||||
- expand_word_internal: when performing final word split, if there are
|
||||
no expansions but has_quoted_ifs is non-zero, call remove_quoted_ifs()
|
||||
to remove any quoted ifs characters we added while processing
|
||||
- remove_quoted_ifs: new function, removes CTLESC chars preceding
|
||||
(single-byte) chars in IFS. Used when we are not performing word
|
||||
splitting. Fixes bug reported by Martijn Dekker <martijn@inlv.org>
|
||||
|
||||
11/4
|
||||
----
|
||||
lib/readline/macro.c
|
||||
- _rl_peek_macro_key: return the next character from the current
|
||||
keyboard macro; the next character from the `next' keyboard macro,
|
||||
if there is one, if at the end of the current macro; or 0 to
|
||||
indicate that we are at the end of a keyboard macro sequence
|
||||
|
||||
lib/readline/rlprivate.h
|
||||
- _rl_peek_macro_key: extern declaration
|
||||
|
||||
lib/readline/readline.c
|
||||
- _rl_dispatch_subseq: add test for ESC at the end of a keyboard macro,
|
||||
which should cause the keyboard timeout for ESC to kick in. The
|
||||
previous test didn't run the timeout code if executing from a macro,
|
||||
even if we had read the last character of the macro. Fixes bug
|
||||
reported by Clark Wang <clarkw@vmware.com>
|
||||
|
||||
lib/glob/sm_loop.c
|
||||
- GMATCH: allow trailing backslash in pattern to explicitly match a
|
||||
backslash that is the last character in the string. Bug report from
|
||||
Stephane Chazelas <stephane.chazelas@gmail.com>
|
||||
|
||||
+11
@@ -2704,6 +2704,7 @@ shell_expand_line (count, ignore)
|
||||
{
|
||||
char *new_line;
|
||||
WORD_LIST *expanded_string;
|
||||
WORD_DESC *w;
|
||||
|
||||
new_line = 0;
|
||||
#if defined (BANG_HISTORY)
|
||||
@@ -2733,9 +2734,19 @@ shell_expand_line (count, ignore)
|
||||
|
||||
/* If there is variable expansion to perform, do that as a separate
|
||||
operation to be undone. */
|
||||
|
||||
#if 1
|
||||
w = alloc_word_desc ();
|
||||
w->word = savestring (rl_line_buffer);
|
||||
w->flags = rl_explicit_arg ? (W_NOPROCSUB|W_NOCOMSUB) : 0;
|
||||
expanded_string = expand_word (w, rl_explicit_arg ? Q_HERE_DOCUMENT : 0);
|
||||
dispose_word (w);
|
||||
#else
|
||||
new_line = savestring (rl_line_buffer);
|
||||
expanded_string = expand_string (new_line, 0);
|
||||
FREE (new_line);
|
||||
#endif
|
||||
|
||||
if (expanded_string == 0)
|
||||
{
|
||||
new_line = (char *)xmalloc (1);
|
||||
|
||||
@@ -122,7 +122,7 @@ rm_builtin (list)
|
||||
rval = EXECUTION_SUCCESS;
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "Rrf")) != -1)
|
||||
while ((opt = internal_getopt (list, "Rrfi")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
@@ -133,6 +133,8 @@ rm_builtin (list)
|
||||
case 'f':
|
||||
force = 1;
|
||||
break;
|
||||
case 'i':
|
||||
return (EX_DISKFALLBACK);
|
||||
CASE_HELPOPT;
|
||||
default:
|
||||
builtin_usage ();
|
||||
|
||||
+24
-1
@@ -4096,13 +4096,15 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
||||
|
||||
if (dofork)
|
||||
{
|
||||
char *p;
|
||||
|
||||
/* Do this now, because execute_disk_command will do it anyway in the
|
||||
vast majority of cases. */
|
||||
maybe_make_export_env ();
|
||||
|
||||
/* Don't let a DEBUG trap overwrite the command string to be saved with
|
||||
the process/job associated with this child. */
|
||||
if (make_child (savestring (the_printed_command_except_trap), async) == 0)
|
||||
if (make_child (p = savestring (the_printed_command_except_trap), async) == 0)
|
||||
{
|
||||
already_forked = 1;
|
||||
simple_command->flags |= CMD_NO_FORK;
|
||||
@@ -4135,6 +4137,8 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
||||
|
||||
if (async)
|
||||
subshell_level++; /* not for pipes yet */
|
||||
|
||||
FREE (p);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4356,6 +4360,15 @@ run_builtin:
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
jump_to_top_level (ERREXIT);
|
||||
}
|
||||
break;
|
||||
case EX_DISKFALLBACK:
|
||||
/* XXX - experimental */
|
||||
itrace("execute_simple_command: fallback to file system");
|
||||
executing_builtin = old_builtin;
|
||||
executing_command_builtin = old_command_builtin;
|
||||
builtin = 0;
|
||||
/* XXX - redirections will have to be performed again */
|
||||
goto execute_from_filesystem;
|
||||
}
|
||||
result = builtin_status (result);
|
||||
if (builtin_is_special)
|
||||
@@ -4390,6 +4403,7 @@ run_builtin:
|
||||
goto run_builtin;
|
||||
}
|
||||
|
||||
execute_from_filesystem:
|
||||
if (command_line == 0)
|
||||
command_line = savestring (the_printed_command_except_trap ? the_printed_command_except_trap : "");
|
||||
|
||||
@@ -4958,6 +4972,15 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var,
|
||||
fflush (stdout);
|
||||
if (r == EX_USAGE)
|
||||
r = EX_BADUSAGE;
|
||||
/* XXX - experimental */
|
||||
else if (r == EX_DISKFALLBACK)
|
||||
{
|
||||
char *command_line;
|
||||
itrace("execute_subshell_builtin_or_function: fall back to disk command");
|
||||
command_line = savestring (the_printed_command_except_trap ? the_printed_command_except_trap : "");
|
||||
r = execute_disk_command (words, (REDIRECT *)0, command_line,
|
||||
-1, -1, async, (struct fd_bitmap *)0, flags|CMD_NO_FORK);
|
||||
}
|
||||
sh_exit (r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1961,6 +1961,9 @@ make_child (command, async_p)
|
||||
signals to the default state for a new process. */
|
||||
pid_t mypid;
|
||||
|
||||
/* If this ends up being changed to modify or use `command' in the
|
||||
child process, go back and change callers who free `command' in
|
||||
the child process when this returns. */
|
||||
mypid = getpid ();
|
||||
#if defined (BUFFERED_INPUT)
|
||||
/* Close default_buffered_input if it's > 0. We don't close it if it's
|
||||
|
||||
@@ -103,6 +103,9 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
|
||||
break;
|
||||
|
||||
case L('\\'): /* backslash escape removes special meaning */
|
||||
if (p == pe && sc == '\\' && (n+1 == se))
|
||||
break;
|
||||
|
||||
if (p == pe)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
|
||||
+5
-1
@@ -81,7 +81,7 @@
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Define getpagesize () if the system does not. */
|
||||
@@ -246,6 +246,10 @@ static const unsigned long binsizes[NBUCKETS] = {
|
||||
/* binsizes[x] == (1 << ((x) + 3)) */
|
||||
#define binsize(x) binsizes[(x)]
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
/* Declarations for internal functions */
|
||||
static PTR_T internal_malloc __P((size_t, const char *, int, int));
|
||||
static PTR_T internal_realloc __P((PTR_T, size_t, const char *, int, int));
|
||||
|
||||
+18
-1
@@ -100,7 +100,10 @@ _rl_with_macro_input (string)
|
||||
return;
|
||||
}
|
||||
|
||||
_rl_push_executing_macro ();
|
||||
#if 0
|
||||
if (rl_executing_macro) /* XXX - later */
|
||||
#endif
|
||||
_rl_push_executing_macro ();
|
||||
rl_executing_macro = string;
|
||||
executing_macro_index = 0;
|
||||
RL_SETSTATE(RL_STATE_MACROINPUT);
|
||||
@@ -128,10 +131,24 @@ _rl_next_macro_key ()
|
||||
_rl_pop_executing_macro ();
|
||||
return c;
|
||||
#else
|
||||
/* XXX - consider doing the same as the callback code, just not testing
|
||||
whether we're running in callback mode */
|
||||
return (rl_executing_macro[executing_macro_index++]);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
_rl_peek_macro_key ()
|
||||
{
|
||||
if (rl_executing_macro == 0)
|
||||
return (0);
|
||||
if (rl_executing_macro[executing_macro_index] == 0 && (macro_list == 0 || macro_list->string == 0))
|
||||
return (0);
|
||||
if (rl_executing_macro[executing_macro_index] == 0 && macro_list && macro_list->string)
|
||||
return (macro_list->string[0]);
|
||||
return (rl_executing_macro[executing_macro_index]);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_prev_macro_key ()
|
||||
{
|
||||
|
||||
@@ -920,6 +920,15 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
||||
_rl_pushed_input_available () == 0 &&
|
||||
_rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0)
|
||||
return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
|
||||
/* This is a very specific test. It can possibly be generalized in
|
||||
the future, but for now it handles a specific case of ESC being
|
||||
the last character in a keyboard macro. */
|
||||
if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap &&
|
||||
(RL_ISSTATE (RL_STATE_INPUTPENDING) == 0) &&
|
||||
(RL_ISSTATE (RL_STATE_MACROINPUT) && _rl_peek_macro_key () == 0) &&
|
||||
_rl_pushed_input_available () == 0 &&
|
||||
_rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0)
|
||||
return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
|
||||
#endif
|
||||
|
||||
RESIZE_KEYSEQ_BUFFER ();
|
||||
|
||||
@@ -413,6 +413,7 @@ extern void rl_deprep_terminal PARAMS((void));
|
||||
extern void rl_tty_set_default_bindings PARAMS((Keymap));
|
||||
extern void rl_tty_unset_default_bindings PARAMS((Keymap));
|
||||
|
||||
extern int rl_tty_set_echoing PARAMS((int));
|
||||
extern int rl_reset_terminal PARAMS((const char *));
|
||||
extern void rl_resize_terminal PARAMS((void));
|
||||
extern void rl_set_screen_size PARAMS((int, int));
|
||||
|
||||
@@ -309,6 +309,7 @@ extern int _rl_search_getchar PARAMS((_rl_search_cxt *));
|
||||
|
||||
/* macro.c */
|
||||
extern void _rl_with_macro_input PARAMS((char *));
|
||||
extern int _rl_peek_macro_key PARAMS((void));
|
||||
extern int _rl_next_macro_key PARAMS((void));
|
||||
extern int _rl_prev_macro_key PARAMS((void));
|
||||
extern void _rl_push_executing_macro PARAMS((void));
|
||||
|
||||
@@ -72,6 +72,7 @@ extern int EOF_Reached;
|
||||
#define EX_REDIRFAIL 259 /* redirection failed */
|
||||
#define EX_BADASSIGN 260 /* variable assignment error */
|
||||
#define EX_EXPFAIL 261 /* word expansion failed */
|
||||
#define EX_DISKFALLBACK 262 /* fall back to disk command from builtin */
|
||||
|
||||
/* Flag values that control parameter pattern substitution. */
|
||||
#define MATCH_ANY 0x000
|
||||
|
||||
@@ -4149,11 +4149,43 @@ remove_quoted_escapes (string)
|
||||
return (string);
|
||||
}
|
||||
|
||||
/* Perform quoted null character removal on STRING. We don't allow any
|
||||
quoted null characters in the middle or at the ends of strings because
|
||||
of how expand_word_internal works. remove_quoted_nulls () turns
|
||||
STRING into an empty string iff it only consists of a quoted null,
|
||||
and removes all unquoted CTLNUL characters. */
|
||||
/* Remove quoted $IFS characters from STRING. Quoted IFS characters are
|
||||
added to protect them from word splitting, but we need to remove them
|
||||
if no word splitting takes place. This returns newly-allocated memory,
|
||||
so callers can use it to replace savestring(). */
|
||||
char *
|
||||
remove_quoted_ifs (string)
|
||||
char *string;
|
||||
{
|
||||
register size_t slen;
|
||||
register int i, j, prev_i;
|
||||
char *ret, *send;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
i = j = 0;
|
||||
ret = (char *)xmalloc (slen + 1);
|
||||
|
||||
while (i < slen)
|
||||
{
|
||||
if (string[i] == CTLESC)
|
||||
{
|
||||
i++;
|
||||
if (string[i] == 0 || isifs (string[i]) == 0)
|
||||
ret[j++] = CTLESC;
|
||||
if (i == slen)
|
||||
break;
|
||||
}
|
||||
|
||||
COPY_CHAR_I (ret, j, string, send, i);
|
||||
}
|
||||
ret[j] = '\0';
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
char *
|
||||
remove_quoted_nulls (string)
|
||||
char *string;
|
||||
@@ -9084,8 +9116,10 @@ expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_somethin
|
||||
|
||||
/* State flags */
|
||||
int had_quoted_null;
|
||||
int has_quoted_ifs; /* did we add a quoted $IFS character here? */
|
||||
int has_dollar_at, temp_has_dollar_at;
|
||||
int split_on_spaces;
|
||||
int local_expanded;
|
||||
int tflag;
|
||||
int pflags; /* flags passed to param_expand */
|
||||
int mb_cur_max;
|
||||
@@ -9119,6 +9153,7 @@ expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_somethin
|
||||
istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
|
||||
istring[istring_index = 0] = '\0';
|
||||
quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
|
||||
has_quoted_ifs = 0;
|
||||
split_on_spaces = 0;
|
||||
quoted_state = UNQUOTED;
|
||||
|
||||
@@ -9247,7 +9282,10 @@ add_string:
|
||||
word->flags |= W_ASSIGNRHS; /* affects $@ */
|
||||
|
||||
if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
|
||||
goto add_ifs_character;
|
||||
{
|
||||
has_quoted_ifs++;
|
||||
goto add_ifs_character;
|
||||
}
|
||||
else
|
||||
goto add_character;
|
||||
|
||||
@@ -9320,6 +9358,7 @@ add_string:
|
||||
case '$':
|
||||
if (expanded_something)
|
||||
*expanded_something = 1;
|
||||
local_expanded = 1;
|
||||
|
||||
temp_has_dollar_at = 0;
|
||||
pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0;
|
||||
@@ -9386,6 +9425,7 @@ add_string:
|
||||
|
||||
if (expanded_something)
|
||||
*expanded_something = 1;
|
||||
local_expanded = 1;
|
||||
|
||||
if (word->flags & W_NOCOMSUB)
|
||||
/* sindex + 1 because string[sindex] == '`' */
|
||||
@@ -9536,6 +9576,7 @@ add_twochars:
|
||||
*contains_dollar_at = 1;
|
||||
if (expanded_something)
|
||||
*expanded_something = 1;
|
||||
local_expanded = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -9663,6 +9704,8 @@ add_twochars:
|
||||
add_ifs_character:
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c) && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0))
|
||||
{
|
||||
if ((quoted&(Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)
|
||||
has_quoted_ifs++;
|
||||
if (string[sindex]) /* from old goto dollar_add_string */
|
||||
sindex++;
|
||||
if (c == 0)
|
||||
@@ -9840,7 +9883,19 @@ finished_with_string:
|
||||
list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
|
||||
else
|
||||
{
|
||||
tword = make_bare_word (istring);
|
||||
#if 0
|
||||
/* XXX might want to use *expanded_something == 0 instead of
|
||||
local_expanded here */
|
||||
if (local_expanded == 0 && has_quoted_ifs)
|
||||
#else
|
||||
if (expanded_something && *expanded_something == 0 && has_quoted_ifs)
|
||||
#endif
|
||||
{
|
||||
tword = alloc_word_desc ();
|
||||
tword->word = remove_quoted_ifs (istring);
|
||||
}
|
||||
else
|
||||
tword = make_bare_word (istring);
|
||||
set_word_flags:
|
||||
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
|
||||
tword->flags |= W_QUOTED;
|
||||
|
||||
Reference in New Issue
Block a user