mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-28 07:59:50 +02:00
fix off by one error when dequoting completed filenames; initial cut at readline identifying ANSI terminals; print coproc commands without coproc name if the coproc is a simple command
This commit is contained in:
@@ -8141,3 +8141,34 @@ parse.y
|
||||
parse.y,make_cmd.c
|
||||
- read_a_line,make_here_document: if we're using shell_getc to read
|
||||
the body of a here-document, let it manage line_number
|
||||
|
||||
12/8
|
||||
----
|
||||
bashline.c
|
||||
- bash_dequote_filename: fix an off-by-one error that didn't remove a
|
||||
closing single quote in a filename if it was backslash-escaped.
|
||||
Report by Ole Tange <ota@prosa.dk>, fix from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
lib/readline/terminal.c
|
||||
- _rl_check_ansi_terminal: check whether or not rl_terminal_name
|
||||
appears to be an ANSI/ECMA-48 terminal. Check some common terminal
|
||||
types and then check whether some common terminal capabilities
|
||||
(ce, nd, ho, up) begin with CSI (ESC-[) and then have a correct
|
||||
subsequent character
|
||||
- _rl_term_isansi: new variable, holds readline's idea about whether
|
||||
the value of rl_terminal_name is an ANSI/ECMA-48 terminal. Initialized
|
||||
to RL_ANSI_TERM_DEFAULT; set to the result of _rl_check_ansi_terminal
|
||||
if initialized to 0 and on a `non-dumb' terminal
|
||||
From an idea by John Tsiombikas <nuclear@mutantstargoat.com> in 11/2023
|
||||
|
||||
lib/readline/rlconf.h
|
||||
- RL_ANSI_TERM_DEFAULT: define to 1 (yes) or 0 (no) to tell readline
|
||||
whether or not to assume it's running on an ANSI/ECMA-48 terminal.
|
||||
The default is 1 (yes)
|
||||
|
||||
12/11
|
||||
-----
|
||||
print_cmd.c
|
||||
- make_command_string_internal: when printing a coproc, print the
|
||||
coproc name only if the coproc command is not a simple command.
|
||||
Report from Albert Akchurin <ackbeat@gmail.com>
|
||||
|
||||
+2
-1
@@ -180,7 +180,8 @@ GCC_LINT_FLAGS = -O -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wno-parentheses
|
||||
-Wmissing-braces -Wuninitialized \
|
||||
-Wmissing-declarations -Winline \
|
||||
-Wmissing-prototypes -Wredundant-decls \
|
||||
-Wformat-security -pedantic
|
||||
-Wformat-security -pedantic \
|
||||
-Werror=incompatible-pointer-types
|
||||
|
||||
GCC_LINT_CFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(GCC_LINT_FLAGS)
|
||||
|
||||
|
||||
+4
-6
@@ -4077,15 +4077,13 @@ bash_dequote_filename (char *text, int quote_char)
|
||||
ret = (char *)xmalloc (l + 1);
|
||||
for (quoted = quote_char, p = text, r = ret; p && *p; p++)
|
||||
{
|
||||
/* Allow backslash-escaped characters to pass through unscathed. */
|
||||
if (*p == '\\')
|
||||
/* Allow backslash-escaped characters to pass through unscathed. Backslashes
|
||||
aren't special in single quotes. */
|
||||
if (quoted != '\'' && *p == '\\')
|
||||
{
|
||||
/* Backslashes are preserved within single quotes. */
|
||||
if (quoted == '\'')
|
||||
*r++ = *p;
|
||||
/* Backslashes are preserved within double quotes unless the
|
||||
character is one that is defined to be escaped */
|
||||
else if (quoted == '"' && ((sh_syntaxtab[(unsigned char)p[1]] & CBSDQUOTE) == 0))
|
||||
if (quoted == '"' && ((sh_syntaxtab[(unsigned char)p[1]] & CBSDQUOTE) == 0))
|
||||
*r++ = *p;
|
||||
|
||||
*r++ = *++p;
|
||||
|
||||
@@ -76,4 +76,9 @@
|
||||
#define RL_VI_CMD_MODESTR_DEFAULT "(cmd)"
|
||||
#define RL_VI_CMD_MODESTR_DEFLEN 5
|
||||
|
||||
/* Do you want readline to assume it's running in an ANSI-compatible terminal
|
||||
by default? If set to 0, readline tries to check and verify whether or not
|
||||
it is. */
|
||||
#define RL_ANSI_TERM_DEFAULT 1 /* for now */
|
||||
|
||||
#endif /* _RLCONF_H_ */
|
||||
|
||||
+77
-4
@@ -1,6 +1,6 @@
|
||||
/* terminal.c -- controlling the terminal with termcap. */
|
||||
|
||||
/* Copyright (C) 1996-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -113,6 +113,7 @@ char PC, *BC, *UP;
|
||||
char *_rl_term_clreol;
|
||||
char *_rl_term_clrpag;
|
||||
char *_rl_term_clrscroll;
|
||||
char *_rl_term_ho;
|
||||
char *_rl_term_cr;
|
||||
char *_rl_term_backspace;
|
||||
char *_rl_term_goto;
|
||||
@@ -220,6 +221,9 @@ int _rl_enable_keypad;
|
||||
/* Non-zero means the user wants to enable a meta key. */
|
||||
int _rl_enable_meta = 1;
|
||||
|
||||
/* Non-zero means this is an ANSI-compatible terminal; assume it is. */
|
||||
int _rl_term_isansi = RL_ANSI_TERM_DEFAULT;
|
||||
|
||||
#if defined (__EMX__)
|
||||
static void
|
||||
_emx_get_screensize (int *swp, int *shp)
|
||||
@@ -433,6 +437,7 @@ static const struct _tc_string tc_strings[] =
|
||||
{ "cr", &_rl_term_cr },
|
||||
{ "dc", &_rl_term_dc },
|
||||
{ "ei", &_rl_term_ei },
|
||||
{ "ho", &_rl_term_ho },
|
||||
{ "ic", &_rl_term_ic },
|
||||
{ "im", &_rl_term_im },
|
||||
{ "kD", &_rl_term_kD }, /* delete */
|
||||
@@ -476,6 +481,63 @@ get_term_capabilities (char **bp)
|
||||
tcap_initialized = 1;
|
||||
}
|
||||
|
||||
struct _term_name {
|
||||
const char * const name;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/* Non-exhaustive list of ANSI/ECMA terminals. */
|
||||
static const struct _term_name ansiterms[] =
|
||||
{
|
||||
{ "xterm", 5 },
|
||||
{ "rxvt", 4 },
|
||||
{ "eterm", 5 },
|
||||
{ "screen", 6 },
|
||||
{ "tmux", 4 },
|
||||
{ "vt100", 5 },
|
||||
{ "vt102", 5 },
|
||||
{ "vt220", 5 },
|
||||
{ "vt320", 5 },
|
||||
{ "ansi", 4 },
|
||||
{ "scoansi", 7 },
|
||||
{ "cygwin", 6 },
|
||||
{ "linux", 5 },
|
||||
{ "konsole", 7 },
|
||||
{ "bvterm", 6 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static inline int
|
||||
iscsi (const char *s)
|
||||
{
|
||||
return ((s[0] == ESC && s[1] == '[') ? 2
|
||||
: ((unsigned char)s[0] == 0x9b) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_check_ansi_terminal (const char *terminal_name)
|
||||
{
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
for (i = 0; ansiterms[i].name; i++)
|
||||
if (STREQN (terminal_name, ansiterms[i].name, ansiterms[i].len))
|
||||
return 1;
|
||||
|
||||
if (_rl_term_clreol == 0 || _rl_term_forward_char == 0 ||
|
||||
_rl_term_ho == 0 || _rl_term_up == 0)
|
||||
return 0;
|
||||
|
||||
/* check some common capabilities */
|
||||
if (((len = iscsi (_rl_term_clreol)) && _rl_term_clreol[len] == 'K') && /* ce */
|
||||
((len = iscsi (_rl_term_forward_char)) && _rl_term_forward_char[len] == 'C') && /* nd */
|
||||
((len = iscsi (_rl_term_ho)) && _rl_term_ho[len] == 'H') && /* ho */
|
||||
((len = iscsi (_rl_term_up)) && _rl_term_up[len] == 'A')) /* up */
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_rl_init_terminal_io (const char *terminal_name)
|
||||
{
|
||||
@@ -490,7 +552,10 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
if (term == 0)
|
||||
term = "dumb";
|
||||
|
||||
dumbterm = STREQ (term, "dumb");
|
||||
_rl_term_isansi = RL_ANSI_TERM_DEFAULT;
|
||||
dumbterm = STREQ (term, "dumb") || STREQ (term, "vt52") || STREQ (term, "adm3a");
|
||||
if (dumbterm)
|
||||
_rl_term_isansi = 0;
|
||||
|
||||
reset_region_colors = 1;
|
||||
|
||||
@@ -502,6 +567,7 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
_rl_terminal_can_insert = term_has_meta = _rl_term_autowrap = 0;
|
||||
_rl_term_cr = "\r";
|
||||
_rl_term_backspace = (char *)NULL;
|
||||
_rl_term_ho = (char *)NULL;
|
||||
_rl_term_goto = _rl_term_pc = _rl_term_ip = (char *)NULL;
|
||||
_rl_term_ks = _rl_term_ke =_rl_term_vs = _rl_term_ve = (char *)NULL;
|
||||
_rl_term_kh = _rl_term_kH = _rl_term_at7 = _rl_term_kI = (char *)NULL;
|
||||
@@ -564,6 +630,7 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
/* Everything below here is used by the redisplay code (tputs). */
|
||||
_rl_screenchars = _rl_screenwidth * _rl_screenheight;
|
||||
_rl_term_cr = "\r";
|
||||
_rl_term_ho = (char *)NULL;
|
||||
_rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
|
||||
_rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
|
||||
_rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
|
||||
@@ -576,6 +643,8 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
_rl_term_so = _rl_term_se = (char *)NULL;
|
||||
_rl_terminal_can_insert = term_has_meta = 0;
|
||||
|
||||
_rl_term_isansi = 0; /* not an ANSI terminal */
|
||||
|
||||
/* Assume generic unknown terminal can't handle the enable/disable
|
||||
escape sequences */
|
||||
_rl_term_BD = _rl_term_BE = _rl_term_PE = _rl_term_PS = (char *)NULL;
|
||||
@@ -637,9 +706,13 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
bind_termcap_arrow_keys (vi_insertion_keymap);
|
||||
#endif /* VI_MODE */
|
||||
|
||||
if (dumbterm == 0 && _rl_term_isansi == 0)
|
||||
_rl_term_isansi = _rl_check_ansi_terminal (terminal_name);
|
||||
|
||||
/* There's no way to determine whether or not a given terminal supports
|
||||
bracketed paste mode, so we assume a terminal named "dumb" does not. */
|
||||
if (dumbterm)
|
||||
bracketed paste mode, so we assume a non-ANSI terminal (as best as we
|
||||
can determine) does not. */
|
||||
if (_rl_term_isansi == 0)
|
||||
_rl_enable_bracketed_paste = _rl_enable_active_region = 0;
|
||||
|
||||
if (reset_region_colors)
|
||||
|
||||
+3
-1
@@ -355,7 +355,9 @@ make_command_string_internal (COMMAND *command)
|
||||
break;
|
||||
|
||||
case cm_coproc:
|
||||
cprintf ("coproc %s ", command->value.Coproc->name);
|
||||
cprintf ("coproc ");
|
||||
if (command->value.Coproc->command->type != cm_simple)
|
||||
cprintf ("%s ", command->value.Coproc->name);
|
||||
skip_this_indent++;
|
||||
make_command_string_internal (command->value.Coproc->command);
|
||||
break;
|
||||
|
||||
@@ -157,6 +157,8 @@ hello
|
||||
world
|
||||
hello
|
||||
world
|
||||
here-doc line 1
|
||||
here-doc line 2
|
||||
here-document
|
||||
here-document
|
||||
comsub here-string
|
||||
|
||||
+19
-9
@@ -16,30 +16,40 @@
|
||||
shopt -s expand_aliases
|
||||
|
||||
# single alias definition contains entire here-document
|
||||
alias 'foo=cat <<EOF
|
||||
alias 'heredoc=cat <<EOF
|
||||
hello
|
||||
world
|
||||
EOF'
|
||||
foo
|
||||
heredoc
|
||||
|
||||
# here-document body continues after alias definition
|
||||
alias 'foo=cat <<EOF
|
||||
alias 'headplus=cat <<EOF
|
||||
hello'
|
||||
foo
|
||||
headplus
|
||||
world
|
||||
EOF
|
||||
|
||||
unalias heredoc headplus
|
||||
|
||||
alias head='cat <<END'
|
||||
|
||||
head
|
||||
here-doc line 1
|
||||
here-doc line 2
|
||||
END
|
||||
|
||||
# here-document delimiter in one alias, body in another
|
||||
shopt -s expand_aliases
|
||||
alias c='cat <<\END' d='c
|
||||
alias head='cat <<\END' body='head
|
||||
here-document
|
||||
END'
|
||||
d
|
||||
body
|
||||
|
||||
# make sure delimiter is recognized whether the alias ends with a newline or not
|
||||
shopt -s expand_aliases
|
||||
alias c='cat <<\END' d='c
|
||||
alias head='cat <<\END' body='head
|
||||
here-document
|
||||
END
|
||||
'
|
||||
d
|
||||
body
|
||||
|
||||
unalias head body
|
||||
|
||||
@@ -134,6 +134,11 @@ EOF
|
||||
);
|
||||
echo "coprocs created"
|
||||
}
|
||||
mkcoprocs is a function
|
||||
mkcoprocs ()
|
||||
{
|
||||
coproc cat -u - & read -u ${COPROC[0]} msg
|
||||
}
|
||||
cat is /bin/cat
|
||||
cat is aliased to `echo cat'
|
||||
/bin/cat
|
||||
|
||||
@@ -54,3 +54,13 @@ echo "coprocs created"
|
||||
}
|
||||
|
||||
type mkcoprocs
|
||||
|
||||
unset -f mkcoprocs
|
||||
|
||||
# make sure that simple commands are printed without the coproc name
|
||||
mkcoprocs ()
|
||||
{
|
||||
coproc cat -u - &
|
||||
read -u ${COPROC[0]} msg
|
||||
}
|
||||
type mkcoprocs
|
||||
|
||||
Reference in New Issue
Block a user