mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-28 07:59:50 +02:00
fix comsub inside parameter expansion in here-document; fix readline longjmp botch; posix change for unset non-identifier; posix change for double quotes inside backquote comsub in here-document; add missing posix pieces to umask builtin
This commit is contained in:
@@ -4667,3 +4667,81 @@ subst.c
|
||||
- parameter_brace_expand_length: handle namerefs with values that are
|
||||
valid length expansion expressions but invalid identifiers. From
|
||||
ed7-aspire4925@hotmail.com via https://savannah.gnu.org/support/?110799
|
||||
|
||||
12/13
|
||||
-----
|
||||
subst.c
|
||||
- extract_heredoc_dolbrace_string: fix off-by-one error after calling
|
||||
extract_command_subst and extract_process_subst that caused it to
|
||||
copy one too many parsed characters. Fix for bug reported by
|
||||
Norbert Lange <nolange79@gmail.com>
|
||||
|
||||
12/14
|
||||
-----
|
||||
execute_cmd.c
|
||||
- execute_cond_node: if a regular expression fails to compile, print
|
||||
an error message. Report from Emanuele Torre <torreemanuele6@gmail.com>
|
||||
back on 6/15/2022
|
||||
|
||||
trap.c
|
||||
- trap_variable_context -> trap_return_context, initialize from
|
||||
funcnest + sourcenest instead of variable_context so we handle
|
||||
shell function execution and `./source', both of which can use
|
||||
`return'. Idea from Koichi Murase <myoga.murase@gmail.com>
|
||||
|
||||
builtins/common.c
|
||||
- get_exitstat: compare trap_return_context against funcnest+sourcenest,
|
||||
since that's how it's initialized now
|
||||
|
||||
lib/readline/readline.c
|
||||
- readline_internal_charloop: if we're not using the callback interface,
|
||||
don't restore _rl_top_level from olevel, since we will just be going
|
||||
around the loop again and will potentially need to use it multiple
|
||||
times. Report from Emanuele Torre <torreemanuele6@gmail.com>
|
||||
|
||||
12/15
|
||||
-----
|
||||
shell.h
|
||||
- EX_UTILERROR: new generic special builtin return status to indicate a
|
||||
POSIX utility error that should cause a non-interactive shell to abort
|
||||
|
||||
execute_cmd.c
|
||||
- builtin_status: translate EX_UTILERROR to EXECUTION_FAILURE
|
||||
|
||||
builtins/set.def
|
||||
- unset_builtin: return EX_UTILERROR if posix_utility_error is set;
|
||||
set it when trying to unset a non-identifier (variable) or a
|
||||
non-unsettable or readonly variable
|
||||
|
||||
12/16
|
||||
-----
|
||||
subst.c
|
||||
- de_backslash: now takes a second argument with the current quoting
|
||||
flags
|
||||
- de_backslash: if the quoting flags include Q_HERE_DOCUMENT and the
|
||||
shell is in posix mode, remove backslashes quoting double quotes
|
||||
|
||||
subst.h
|
||||
- de_backslash: update extern declaration
|
||||
|
||||
lib/readline/histexpand.c
|
||||
- history_expand_internal,get_history_word_specifier,get_subst_pattern,
|
||||
hist_error,history_find_word,hist_string_extract_single_quoted:
|
||||
now take const char * string arguments
|
||||
|
||||
lib/readline/mbutil.c
|
||||
- _rl_get_char_len,_rl_adjust_point,_rl_find_next_mbchar_internal,
|
||||
_rl_find_next_mbchar,_rl_find_prev_mbchar,_rl_find_prev_mbchar_internal,
|
||||
_rl_test_nonzero,_rl_find_prev_utf8char,_rl_is_mbchar_matched,
|
||||
_rl_compare_chars,_rl_char_value: take const char * string arguments
|
||||
|
||||
12/17
|
||||
-----
|
||||
builtins/umask.def
|
||||
- parse_symbolic_umask: add missing POSIX pieces:
|
||||
o `action' of ugo, meaning to copy portions of initial mask
|
||||
o multiple `op' specs as part of the action string (`u=r-w')
|
||||
(resets perm)
|
||||
o missing perm characters Xst in action string
|
||||
o default `who' equivalent to `a' instead of fixing up later
|
||||
|
||||
|
||||
@@ -978,6 +978,7 @@ tests/builtins4.sub f
|
||||
tests/builtins5.sub f
|
||||
tests/builtins6.sub f
|
||||
tests/builtins7.sub f
|
||||
tests/builtins8.sub f
|
||||
tests/source1.sub f
|
||||
tests/source2.sub f
|
||||
tests/source3.sub f
|
||||
|
||||
+1
-1
@@ -573,7 +573,7 @@ get_exitstat (list)
|
||||
trap gets to change $?, though, since that is part of its reason for
|
||||
existing, and because the extended debug mode does things with the
|
||||
return value. */
|
||||
if (this_shell_builtin == return_builtin && running_trap > 0 && running_trap != DEBUG_TRAP+1 && variable_context == trap_variable_context)
|
||||
if (this_shell_builtin == return_builtin && running_trap > 0 && running_trap != DEBUG_TRAP+1 && trap_return_context == funcnest + sourcenest)
|
||||
return (trap_saved_exit_value);
|
||||
return (last_command_exit_value);
|
||||
}
|
||||
|
||||
+11
-4
@@ -836,9 +836,11 @@ unset_builtin (list)
|
||||
{
|
||||
int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
|
||||
int global_unset_func, global_unset_var, vflags, base_vflags, valid_id;
|
||||
int posix_utility_error;
|
||||
char *name, *tname;
|
||||
|
||||
unset_function = unset_variable = unset_array = nameref = any_failed = 0;
|
||||
unset_function = unset_variable = unset_array = nameref = 0;
|
||||
posix_utility_error = any_failed = 0;
|
||||
global_unset_func = global_unset_var = 0;
|
||||
|
||||
reset_internal_getopt ();
|
||||
@@ -918,6 +920,7 @@ unset_builtin (list)
|
||||
if (unset_function == 0 && valid_id == 0)
|
||||
{
|
||||
sh_invalidid (name);
|
||||
posix_utility_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
@@ -930,6 +933,7 @@ unset_builtin (list)
|
||||
if (var && unset_function == 0 && non_unsettable_p (var))
|
||||
{
|
||||
builtin_error (_("%s: cannot unset"), name);
|
||||
posix_utility_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
@@ -952,6 +956,7 @@ unset_builtin (list)
|
||||
{
|
||||
builtin_error (_("%s: cannot unset: readonly %s"),
|
||||
var->name, unset_function ? "function" : "variable");
|
||||
posix_utility_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
@@ -1008,8 +1013,10 @@ unset_builtin (list)
|
||||
|
||||
/* This is what Posix.2 says: ``If neither -f nor -v
|
||||
is specified, the name refers to a variable; if a variable by
|
||||
that name does not exist, a function by that name, if any,
|
||||
shall be unset.'' */
|
||||
that name does not exist, it is unspecified whether a function
|
||||
by that name, if any, shall be unset.'' The unspecified part is a
|
||||
recent addition, so we continue to try to unset a shell function if
|
||||
we don't find a variable named NAME. */
|
||||
if (tem == -1 && nameref == 0 && unset_function == 0 && unset_variable == 0)
|
||||
tem = unbind_func (name);
|
||||
|
||||
@@ -1024,5 +1031,5 @@ unset_builtin (list)
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
||||
return (any_failed ? (posix_utility_error ? EX_UTILERROR : EXECUTION_FAILURE) : EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
+102
-36
@@ -1,7 +1,7 @@
|
||||
This file is umask.def, from which is created umask.c.
|
||||
It implements the builtin "umask" in Bash.
|
||||
|
||||
Copyright (C) 1987-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2022 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -186,17 +186,46 @@ print_symbolic_umask (um)
|
||||
printf ("u=%s,g=%s,o=%s\n", ubits, gbits, obits);
|
||||
}
|
||||
|
||||
static inline mode_t
|
||||
copyuser (mask)
|
||||
mode_t mask;
|
||||
{
|
||||
return ((mask & S_IRUSR) ? S_IRUGO : 0) |
|
||||
((mask & S_IWUSR) ? S_IWUGO : 0) |
|
||||
((mask & S_IXUSR) ? S_IXUGO : 0);
|
||||
}
|
||||
|
||||
static inline mode_t
|
||||
copygroup (mask)
|
||||
mode_t mask;
|
||||
{
|
||||
return ((mask & S_IRGRP) ? S_IRUGO : 0) |
|
||||
((mask & S_IWGRP) ? S_IWUGO : 0) |
|
||||
((mask & S_IXGRP) ? S_IXUGO : 0);
|
||||
}
|
||||
|
||||
static inline mode_t
|
||||
copyother (mask)
|
||||
mode_t mask;
|
||||
{
|
||||
return ((mask & S_IROTH) ? S_IRUGO : 0) |
|
||||
((mask & S_IWOTH) ? S_IWUGO : 0) |
|
||||
((mask & S_IXOTH) ? S_IXUGO : 0);
|
||||
}
|
||||
|
||||
int
|
||||
parse_symbolic_mode (mode, initial_bits)
|
||||
char *mode;
|
||||
int initial_bits;
|
||||
mode_t initial_bits;
|
||||
{
|
||||
int who, op, perm, bits, c;
|
||||
char op, c;
|
||||
mode_t who, perm, bits;
|
||||
char *s;
|
||||
|
||||
for (s = mode, bits = initial_bits;;)
|
||||
{
|
||||
who = op = perm = 0;
|
||||
who = 0;
|
||||
op = 0;
|
||||
|
||||
/* Parse the `who' portion of the symbolic mode clause. */
|
||||
while (member (*s, "agou"))
|
||||
@@ -220,7 +249,13 @@ parse_symbolic_mode (mode, initial_bits)
|
||||
}
|
||||
}
|
||||
|
||||
/* default `who' is `a' */
|
||||
if (who == 0)
|
||||
who = S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
|
||||
/* The operation is now sitting in *s. */
|
||||
start_op:
|
||||
perm = 0;
|
||||
op = *s++;
|
||||
switch (op)
|
||||
{
|
||||
@@ -233,57 +268,87 @@ parse_symbolic_mode (mode, initial_bits)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Parse out the `perm' section of the symbolic mode clause. */
|
||||
while (member (*s, "rwx"))
|
||||
/* Parse out the `action' section of the symbolic mode clause. An
|
||||
action can be a set of permissions (rwxXst), a copy specification
|
||||
(ugo), or another op (+-=). */
|
||||
while (member (*s, "rwxXstugo"))
|
||||
{
|
||||
c = *s++;
|
||||
|
||||
switch (c)
|
||||
switch (*s)
|
||||
{
|
||||
/* First the copy specification */
|
||||
case 'u':
|
||||
perm = copyuser (initial_bits);
|
||||
break;
|
||||
case 'g':
|
||||
perm = copygroup (initial_bits);
|
||||
break;
|
||||
case 'o':
|
||||
perm = copyother (initial_bits);
|
||||
break;
|
||||
|
||||
/* Then the permissions. */
|
||||
case 'r':
|
||||
perm |= S_IRUGO;
|
||||
break;
|
||||
case 'w':
|
||||
perm |= S_IWUGO;
|
||||
break;
|
||||
case 'X':
|
||||
/* for chmod, this includes S_ISDIR but that doesn't make sense here */
|
||||
if ((initial_bits & S_IXUGO) == 0)
|
||||
break; /* no-op if original mask doesn't include execute bits */
|
||||
/* FALLTHROUGH */
|
||||
case 'x':
|
||||
perm |= S_IXUGO;
|
||||
break;
|
||||
case 's':
|
||||
#ifdef S_ISUID
|
||||
perm |= S_ISUID | S_ISGID;
|
||||
break;
|
||||
#else
|
||||
goto spec_error;
|
||||
#endif
|
||||
case 't':
|
||||
#ifdef S_ISVTX
|
||||
perm |= S_ISVTX;
|
||||
break;
|
||||
#else
|
||||
goto spec_error;
|
||||
#endif
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
/* Now perform the operation or return an error for a
|
||||
bad permission string. */
|
||||
if (!*s || *s == ',')
|
||||
perm &= who;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
if (who)
|
||||
perm &= who;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case '+':
|
||||
bits |= perm;
|
||||
break;
|
||||
case '-':
|
||||
bits &= ~perm;
|
||||
break;
|
||||
case '=':
|
||||
if (who == 0)
|
||||
who = S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
bits &= ~who;
|
||||
bits |= perm;
|
||||
break;
|
||||
|
||||
/* No other values are possible. */
|
||||
}
|
||||
|
||||
if (*s == '\0')
|
||||
break;
|
||||
else
|
||||
s++; /* skip past ',' */
|
||||
case '+':
|
||||
bits |= perm;
|
||||
break;
|
||||
case '-':
|
||||
bits &= ~perm;
|
||||
break;
|
||||
case '=':
|
||||
bits &= ~who;
|
||||
bits |= perm;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Break if the end of the action string, loop if we're going to parse
|
||||
another `who', go back to parsing another op if we have an op spec
|
||||
(+-=). Return an invalid mode character error for everything else. */
|
||||
if (*s == '\0')
|
||||
break;
|
||||
else if (*s == ',')
|
||||
s++; /* skip past ',' */
|
||||
else if (*s == '+' || *s == '-' || *s == '=')
|
||||
goto start_op;
|
||||
else
|
||||
{
|
||||
spec_error:
|
||||
builtin_error (_("`%c': invalid symbolic mode character"), *s);
|
||||
return (-1);
|
||||
}
|
||||
@@ -299,7 +364,8 @@ static int
|
||||
symbolic_umask (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int um, bits;
|
||||
mode_t um;
|
||||
int bits;
|
||||
|
||||
/* Get the initial umask. Don't change it yet. */
|
||||
um = umask (022);
|
||||
|
||||
@@ -8248,6 +8248,12 @@ the @sc{posix} standard, and include things like passing incorrect options,
|
||||
redirection errors, variable assignment errors for assignments preceding
|
||||
the command name, and so on.
|
||||
|
||||
@item
|
||||
The @code{unset} builtin with the @option{-v} option specified returns a
|
||||
fatal error if it attempts to unset a @code{readonly} or @code{non-unsettable}
|
||||
variable, or encounters a variable name argument that is an invalid identifier,
|
||||
which causes a non-interactive shell to exit.
|
||||
|
||||
@item
|
||||
A non-interactive shell exits with an error status if a variable
|
||||
assignment error occurs when no command name follows the assignment
|
||||
@@ -8434,6 +8440,13 @@ arguments corresponding to floating point conversion specifiers, instead of
|
||||
Bash removes an exited background process's status from the list of such
|
||||
statuses after the @code{wait} builtin is used to obtain it.
|
||||
|
||||
@item
|
||||
A double quote character (@samp{"}) is treated specially when it appears
|
||||
in a backquoted command substitution in the body of a here-document that
|
||||
undergoes expansion.
|
||||
That means, for example, that a backslash preceding a double quote
|
||||
character will escape it and the backslash will be removed.
|
||||
|
||||
@end enumerate
|
||||
|
||||
There is other @sc{posix} behavior that Bash does not implement by
|
||||
|
||||
@@ -4014,6 +4014,8 @@ execute_cond_node (cond)
|
||||
#endif
|
||||
|
||||
result = sh_regmatch (arg1, arg2, mflags);
|
||||
if (result == 2)
|
||||
builtin_error (_("invalid regular expression `%s'"), arg2);
|
||||
}
|
||||
else
|
||||
#endif /* COND_REGEXP */
|
||||
@@ -4869,6 +4871,7 @@ builtin_status (result)
|
||||
case EX_REDIRFAIL:
|
||||
case EX_BADASSIGN:
|
||||
case EX_EXPFAIL:
|
||||
case EX_UTILERROR:
|
||||
r = EXECUTION_FAILURE;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -2732,7 +2732,6 @@ int
|
||||
rl_forced_update_display (void)
|
||||
{
|
||||
register char *temp;
|
||||
register int tlen;
|
||||
|
||||
if (visible_line)
|
||||
memset (visible_line, 0, line_size);
|
||||
|
||||
@@ -70,12 +70,12 @@ static int subst_rhs_len;
|
||||
specifications from word designators. Static for now */
|
||||
static char *history_event_delimiter_chars = HISTORY_EVENT_DELIMITERS;
|
||||
|
||||
static char *get_history_word_specifier (char *, char *, int *);
|
||||
static char *get_history_word_specifier (const char *, char *, int *);
|
||||
static int history_tokenize_word (const char *, int);
|
||||
static char **history_tokenize_internal (const char *, int, int *);
|
||||
static char *history_substring (const char *, int, int);
|
||||
static void freewords (char **, int);
|
||||
static char *history_find_word (char *, int);
|
||||
static char *history_find_word (const char *, int);
|
||||
|
||||
static char *quote_breaks (char *);
|
||||
|
||||
@@ -319,7 +319,7 @@ get_history_event (const char *string, int *caller_index, int delimiting_quote)
|
||||
to the closing single quote. FLAGS currently used to allow backslash
|
||||
to escape a single quote (e.g., for bash $'...'). */
|
||||
static void
|
||||
hist_string_extract_single_quoted (char *string, int *sindex, int flags)
|
||||
hist_string_extract_single_quoted (const char *string, int *sindex, int flags)
|
||||
{
|
||||
register int i;
|
||||
|
||||
@@ -374,7 +374,7 @@ quote_breaks (char *s)
|
||||
}
|
||||
|
||||
static char *
|
||||
hist_error(char *s, int start, int current, int errtype)
|
||||
hist_error(const char *s, int start, int current, int errtype)
|
||||
{
|
||||
char *temp;
|
||||
const char *emsg;
|
||||
@@ -434,7 +434,7 @@ hist_error(char *s, int start, int current, int errtype)
|
||||
subst_rhs is allowed to be set to the empty string. */
|
||||
|
||||
static char *
|
||||
get_subst_pattern (char *str, int *iptr, int delimiter, int is_rhs, int *lenptr)
|
||||
get_subst_pattern (const char *str, int *iptr, int delimiter, int is_rhs, int *lenptr)
|
||||
{
|
||||
register int si, i, j, k;
|
||||
char *s;
|
||||
@@ -527,7 +527,7 @@ postproc_subst_rhs (void)
|
||||
*END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
|
||||
/* need current line for !# */
|
||||
static int
|
||||
history_expand_internal (char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line)
|
||||
history_expand_internal (const char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line)
|
||||
{
|
||||
int i, n, starting_index;
|
||||
int substitute_globally, subst_bywords, want_quotes, print_only;
|
||||
@@ -1303,7 +1303,7 @@ history_expand (char *hstring, char **output)
|
||||
CALLER_INDEX is the offset in SPEC to start looking; it is updated
|
||||
to point to just after the last character parsed. */
|
||||
static char *
|
||||
get_history_word_specifier (char *spec, char *from, int *caller_index)
|
||||
get_history_word_specifier (const char *spec, char *from, int *caller_index)
|
||||
{
|
||||
register int i = *caller_index;
|
||||
int first, last;
|
||||
@@ -1696,7 +1696,7 @@ freewords (char **words, int start)
|
||||
in the history line LINE. Used to save the word matched by the
|
||||
last history !?string? search. */
|
||||
static char *
|
||||
history_find_word (char *line, int ind)
|
||||
history_find_word (const char *line, int ind)
|
||||
{
|
||||
char **words, *s;
|
||||
int i, wind;
|
||||
|
||||
+12
-12
@@ -148,7 +148,7 @@ _rl_utf8_mblen (const char *s, size_t n)
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_zero)
|
||||
_rl_find_next_mbchar_internal (const char *string, int seed, int count, int find_non_zero)
|
||||
{
|
||||
size_t tmp, len;
|
||||
mbstate_t ps;
|
||||
@@ -228,7 +228,7 @@ _rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_z
|
||||
}
|
||||
|
||||
static inline int
|
||||
_rl_test_nonzero (char *string, int ind, int len)
|
||||
_rl_test_nonzero (const char *string, int ind, int len)
|
||||
{
|
||||
size_t tmp;
|
||||
WCHAR_T wc;
|
||||
@@ -242,7 +242,7 @@ _rl_test_nonzero (char *string, int ind, int len)
|
||||
|
||||
/* experimental -- needs to handle zero-width characters better */
|
||||
static int
|
||||
_rl_find_prev_utf8char (char *string, int seed, int find_non_zero)
|
||||
_rl_find_prev_utf8char (const char *string, int seed, int find_non_zero)
|
||||
{
|
||||
char *s;
|
||||
unsigned char b;
|
||||
@@ -288,7 +288,7 @@ _rl_find_prev_utf8char (char *string, int seed, int find_non_zero)
|
||||
}
|
||||
|
||||
/*static*/ int
|
||||
_rl_find_prev_mbchar_internal (char *string, int seed, int find_non_zero)
|
||||
_rl_find_prev_mbchar_internal (const char *string, int seed, int find_non_zero)
|
||||
{
|
||||
mbstate_t ps;
|
||||
int prev, non_zero_prev, point, length;
|
||||
@@ -356,7 +356,7 @@ _rl_find_prev_mbchar_internal (char *string, int seed, int find_non_zero)
|
||||
if an invalid multibyte sequence was encountered. It returns (size_t)(-2)
|
||||
if it couldn't parse a complete multibyte character. */
|
||||
int
|
||||
_rl_get_char_len (char *src, mbstate_t *ps)
|
||||
_rl_get_char_len (const char *src, mbstate_t *ps)
|
||||
{
|
||||
size_t tmp, l;
|
||||
int mb_cur_max;
|
||||
@@ -368,7 +368,7 @@ _rl_get_char_len (char *src, mbstate_t *ps)
|
||||
else
|
||||
{
|
||||
mb_cur_max = MB_CUR_MAX;
|
||||
tmp = mbrlen((const char *)src, (l < mb_cur_max) ? l : mb_cur_max, ps);
|
||||
tmp = mbrlen(src, (l < mb_cur_max) ? l : mb_cur_max, ps);
|
||||
}
|
||||
if (tmp == (size_t)(-2))
|
||||
{
|
||||
@@ -394,7 +394,7 @@ _rl_get_char_len (char *src, mbstate_t *ps)
|
||||
/* compare the specified two characters. If the characters matched,
|
||||
return 1. Otherwise return 0. */
|
||||
int
|
||||
_rl_compare_chars (char *buf1, int pos1, mbstate_t *ps1, char *buf2, int pos2, mbstate_t *ps2)
|
||||
_rl_compare_chars (const char *buf1, int pos1, mbstate_t *ps1, const char *buf2, int pos2, mbstate_t *ps2)
|
||||
{
|
||||
int i, w1, w2;
|
||||
|
||||
@@ -417,7 +417,7 @@ _rl_compare_chars (char *buf1, int pos1, mbstate_t *ps1, char *buf2, int pos2, m
|
||||
if point is invalid (point < 0 || more than string length),
|
||||
it returns -1 */
|
||||
int
|
||||
_rl_adjust_point (char *string, int point, mbstate_t *ps)
|
||||
_rl_adjust_point (const char *string, int point, mbstate_t *ps)
|
||||
{
|
||||
size_t tmp;
|
||||
int length, pos;
|
||||
@@ -457,7 +457,7 @@ _rl_adjust_point (char *string, int point, mbstate_t *ps)
|
||||
}
|
||||
|
||||
int
|
||||
_rl_is_mbchar_matched (char *string, int seed, int end, char *mbchar, int length)
|
||||
_rl_is_mbchar_matched (const char *string, int seed, int end, char *mbchar, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -471,7 +471,7 @@ _rl_is_mbchar_matched (char *string, int seed, int end, char *mbchar, int length
|
||||
}
|
||||
|
||||
WCHAR_T
|
||||
_rl_char_value (char *buf, int ind)
|
||||
_rl_char_value (const char *buf, int ind)
|
||||
{
|
||||
size_t tmp;
|
||||
WCHAR_T wc;
|
||||
@@ -500,7 +500,7 @@ _rl_char_value (char *buf, int ind)
|
||||
characters. */
|
||||
#undef _rl_find_next_mbchar
|
||||
int
|
||||
_rl_find_next_mbchar (char *string, int seed, int count, int flags)
|
||||
_rl_find_next_mbchar (const char *string, int seed, int count, int flags)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
return _rl_find_next_mbchar_internal (string, seed, count, flags);
|
||||
@@ -514,7 +514,7 @@ _rl_find_next_mbchar (char *string, int seed, int count, int flags)
|
||||
we look for non-zero-width multibyte characters. */
|
||||
#undef _rl_find_prev_mbchar
|
||||
int
|
||||
_rl_find_prev_mbchar (char *string, int seed, int flags)
|
||||
_rl_find_prev_mbchar (const char *string, int seed, int flags)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
return _rl_find_prev_mbchar_internal (string, seed, flags);
|
||||
|
||||
@@ -590,7 +590,8 @@ readline_internal_charloop (void)
|
||||
{
|
||||
(*rl_redisplay_function) ();
|
||||
_rl_want_redisplay = 0;
|
||||
memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK))
|
||||
memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
|
||||
|
||||
/* If we longjmped because of a timeout, handle it here. */
|
||||
if (RL_ISSTATE (RL_STATE_TIMEOUT))
|
||||
|
||||
@@ -104,21 +104,21 @@
|
||||
#define MB_FIND_ANY 0x00
|
||||
#define MB_FIND_NONZERO 0x01
|
||||
|
||||
extern int _rl_find_prev_mbchar (char *, int, int);
|
||||
extern int _rl_find_next_mbchar (char *, int, int, int);
|
||||
extern int _rl_find_prev_mbchar (const char *, int, int);
|
||||
extern int _rl_find_next_mbchar (const char *, int, int, int);
|
||||
|
||||
#ifdef HANDLE_MULTIBYTE
|
||||
|
||||
extern int _rl_compare_chars (char *, int, mbstate_t *, char *, int, mbstate_t *);
|
||||
extern int _rl_get_char_len (char *, mbstate_t *);
|
||||
extern int _rl_adjust_point (char *, int, mbstate_t *);
|
||||
extern int _rl_compare_chars (const char *, int, mbstate_t *, const char *, int, mbstate_t *);
|
||||
extern int _rl_get_char_len (const char *, mbstate_t *);
|
||||
extern int _rl_adjust_point (const char *, int, mbstate_t *);
|
||||
|
||||
extern int _rl_read_mbchar (char *, int);
|
||||
extern int _rl_read_mbstring (int, char *, int);
|
||||
|
||||
extern int _rl_is_mbchar_matched (char *, int, int, char *, int);
|
||||
extern int _rl_is_mbchar_matched (const char *, int, int, char *, int);
|
||||
|
||||
extern WCHAR_T _rl_char_value (char *, int);
|
||||
extern WCHAR_T _rl_char_value (const char *, int);
|
||||
extern int _rl_walphabetic (WCHAR_T);
|
||||
|
||||
#define _rl_to_wupper(wc) (iswlower (wc) ? towupper (wc) : (wc))
|
||||
|
||||
@@ -3072,12 +3072,7 @@ alias_expand_token (tokstr)
|
||||
char *expanded;
|
||||
alias_t *ap;
|
||||
|
||||
#if 0
|
||||
if (((parser_state & PST_ALEXPNEXT) || command_token_position (last_read_token)) &&
|
||||
(parser_state & PST_CASEPAT) == 0)
|
||||
#else
|
||||
if ((parser_state & PST_ALEXPNEXT) || assignment_acceptable (last_read_token))
|
||||
#endif
|
||||
{
|
||||
ap = find_alias (tokstr);
|
||||
|
||||
|
||||
+1
-1
@@ -25,6 +25,6 @@
|
||||
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
|
||||
looks for to find the patch level (for the sccs version string). */
|
||||
|
||||
#define PATCHLEVEL 12
|
||||
#define PATCHLEVEL 15
|
||||
|
||||
#endif /* _PATCHLEVEL_H_ */
|
||||
|
||||
@@ -73,6 +73,7 @@ extern int EOF_Reached;
|
||||
#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 */
|
||||
#define EX_UTILERROR 263 /* Posix special builtin utility error */
|
||||
|
||||
/* Flag values that control parameter pattern substitution. */
|
||||
#define MATCH_ANY 0x000
|
||||
|
||||
@@ -85,7 +85,6 @@ extern int errno;
|
||||
|
||||
#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
|
||||
|
||||
|
||||
/* Flags for quoted_strchr */
|
||||
#define ST_BACKSL 0x01
|
||||
#define ST_CTLESC 0x02
|
||||
@@ -1699,7 +1698,7 @@ extract_heredoc_dolbrace_string (string, sindex, quoted, flags)
|
||||
t = extract_command_subst (string, &si, flags);
|
||||
CHECK_STRING_OVERRUN (i, si, slen, c);
|
||||
|
||||
tlen = si - i - 1;
|
||||
tlen = si - i - 2;
|
||||
RESIZE_MALLOCED_BUFFER (result, result_index, tlen + 4, result_size, 64);
|
||||
result[result_index++] = c;
|
||||
result[result_index++] = LPAREN;
|
||||
@@ -1719,7 +1718,7 @@ extract_heredoc_dolbrace_string (string, sindex, quoted, flags)
|
||||
t = extract_process_subst (string, (string[i] == '<' ? "<(" : ">)"), &si, flags);
|
||||
CHECK_STRING_OVERRUN (i, si, slen, c);
|
||||
|
||||
tlen = si - i - 1;
|
||||
tlen = si - i - 2;
|
||||
RESIZE_MALLOCED_BUFFER (result, result_index, tlen + 4, result_size, 64);
|
||||
result[result_index++] = c;
|
||||
result[result_index++] = LPAREN;
|
||||
@@ -2002,8 +2001,9 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
/* Remove backslashes which are quoting backquotes from STRING. Modifies
|
||||
STRING, and returns a pointer to it. */
|
||||
char *
|
||||
de_backslash (string)
|
||||
de_backslash (string, qflags)
|
||||
char *string;
|
||||
int qflags;
|
||||
{
|
||||
register size_t slen;
|
||||
register int i, j, prev_i;
|
||||
@@ -2018,6 +2018,8 @@ de_backslash (string)
|
||||
if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
|
||||
string[i + 1] == '$'))
|
||||
i++;
|
||||
else if (posixly_correct && (qflags & Q_HERE_DOCUMENT) && string[i] == '\\' && string[i + 1] == '"')
|
||||
i++;
|
||||
prev_i = i;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
if (j < prev_i)
|
||||
@@ -11327,7 +11329,7 @@ add_string:
|
||||
temp1 = substring (string, t_index, sindex + 1);
|
||||
else
|
||||
{
|
||||
de_backslash (temp);
|
||||
de_backslash (temp, quoted);
|
||||
tword = command_substitute (temp, quoted, PF_BACKQUOTE);
|
||||
temp1 = tword ? tword->word : (char *)NULL;
|
||||
if (tword)
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
/* Remove backslashes which are quoting backquotes from STRING. Modifies
|
||||
STRING, and returns a pointer to it. */
|
||||
extern char * de_backslash PARAMS((char *));
|
||||
extern char * de_backslash PARAMS((char *, int));
|
||||
|
||||
/* Replace instances of \! in a string with !. */
|
||||
extern void unquote_bang PARAMS((char *));
|
||||
|
||||
+14
-1
@@ -278,4 +278,17 @@ type
|
||||
+ command -p -- command -v type
|
||||
type
|
||||
+ set +x
|
||||
./builtins.tests: line 284: exit: status: numeric argument required
|
||||
u=rw,g=rx,o=rx
|
||||
u=r,g=rx,o=rx
|
||||
u=rwx,g=rwx,o=
|
||||
u=rw,g=wx,o=rx
|
||||
u=rx,g=rx,o=rx
|
||||
u=rwx,g=rx,o=rwx
|
||||
u=rwx,g=rwx,o=rx
|
||||
u=rx,g=rx,o=rx
|
||||
u=rwx,g=rx,o=rx
|
||||
u=rwx,g=rwx,o=rwx
|
||||
u=rwx,g=rwx,o=rwx
|
||||
u=rwx,g=rx,o=rx
|
||||
u=rwx,g=rx,o=rx
|
||||
./builtins.tests: line 287: exit: status: numeric argument required
|
||||
|
||||
@@ -87,7 +87,7 @@ BVAR=xxx eval echo $AVAR
|
||||
|
||||
unset -v AVAR BVAR
|
||||
|
||||
# test umask
|
||||
# basic umask tests
|
||||
mask=$(umask)
|
||||
umask 022
|
||||
umask
|
||||
@@ -280,6 +280,9 @@ ${THIS_SH} ./builtins6.sub
|
||||
# test behavior of command builtin after changing it to a pseudo-keyword
|
||||
${THIS_SH} ./builtins7.sub
|
||||
|
||||
# POSIX complete symbolic umask tests
|
||||
${THIS_SH} ./builtins8.sub
|
||||
|
||||
# this must be last -- it is a fatal error
|
||||
exit status
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
umask 022
|
||||
umask u=r+w
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask u=r-w
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask g+u,o+rwx-u
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask u=r+w,g=wx,o+xr
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask u+w=r+x
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask o=u
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask g=u
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask u=rwx,u-w
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask u=xwr
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask +xwr
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask a+xwr
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask +xr
|
||||
umask -S
|
||||
|
||||
umask 022
|
||||
umask a+xr
|
||||
umask -S
|
||||
|
||||
|
||||
|
||||
@@ -76,6 +76,11 @@ echo $(echo $( echo nested )
|
||||
)
|
||||
)
|
||||
|
||||
BUILDDIR=/builds/test
|
||||
read << EOC
|
||||
Dir: ${BUILDDIR#<(echo a)/}
|
||||
EOC
|
||||
|
||||
${THIS_SH} ./comsub1.sub
|
||||
${THIS_SH} ./comsub2.sub
|
||||
${THIS_SH} ./comsub3.sub
|
||||
|
||||
@@ -76,6 +76,7 @@ match control-a 2
|
||||
match control-a 3
|
||||
match control-a 4
|
||||
match control-a 5
|
||||
./cond-regexp2.sub: line 18: [[: invalid regular expression `[\.'
|
||||
ok 1
|
||||
ok 2
|
||||
ok 3
|
||||
|
||||
+7
-2
@@ -48,7 +48,7 @@ hash: usage: hash [-lr] [-p pathname] [-dt] [name ...]
|
||||
./errors.tests: line 157: umask: `:': invalid symbolic mode operator
|
||||
./errors.tests: line 160: umask: -i: invalid option
|
||||
umask: usage: umask [-p] [-S] [mode]
|
||||
./errors.tests: line 164: umask: `u': invalid symbolic mode character
|
||||
./errors.tests: line 164: umask: `p': invalid symbolic mode character
|
||||
./errors.tests: line 173: VAR: readonly variable
|
||||
./errors.tests: line 176: declare: VAR: readonly variable
|
||||
./errors.tests: line 177: declare: VAR: readonly variable
|
||||
@@ -210,4 +210,9 @@ DEBUG
|
||||
bash: line 1: return: can only `return' from a function or sourced script
|
||||
after return
|
||||
bash: line 1: return: can only `return' from a function or sourced script
|
||||
./errors.tests: line 305: `!!': not a valid identifier
|
||||
sh: line 1: unset: a: cannot unset: readonly variable
|
||||
sh: line 1: unset: `a-b': not a valid identifier
|
||||
sh: line 1: /nosuchfile: No such file or directory
|
||||
sh: line 1: trap: SIGNOSIG: invalid signal specification
|
||||
after trap
|
||||
./errors.tests: line 316: `!!': not a valid identifier
|
||||
|
||||
+12
-1
@@ -161,7 +161,7 @@ umask -i
|
||||
|
||||
# bad assignments shouldn't change the umask
|
||||
mask=$(umask)
|
||||
umask g=u
|
||||
umask g=p
|
||||
mask2=$(umask)
|
||||
if [ "$mask" != "$mask2" ]; then
|
||||
echo "umask errors change process umask"
|
||||
@@ -297,6 +297,17 @@ ${THIS_SH} ./errors9.sub
|
||||
${THIS_SH} -c 'return ; echo after return' bash
|
||||
${THIS_SH} -o posix -c 'return ; echo after return' bash
|
||||
|
||||
# various posix-mode special builtin fatal (or not) errors
|
||||
|
||||
# posix says unsetting readonly variables is a fatal error
|
||||
${THIS_SH} -o posix -c 'readonly a=a ; unset -v a; echo after unset 1' sh
|
||||
# the same with non-identifiers
|
||||
${THIS_SH} -o posix -c 'unset -v a-b; echo after unset 2' sh
|
||||
# and sourcing a non-existent file is fatal too
|
||||
${THIS_SH} -o posix -c '. /nosuchfile ; echo after source' sh
|
||||
# but trap specifying a bad signal nunber is non-fatal
|
||||
${THIS_SH} -o posix -c 'trap "echo bad" SIGNOSIG; echo after trap' sh
|
||||
|
||||
# this must be last!
|
||||
# in posix mode, a function name must be a valid identifier
|
||||
# this can't go in posix2.tests, since it causes the shell to exit
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* trap.c -- Not the trap command, but useful functions for manipulating
|
||||
those objects. The trap command is in builtins/trap.def. */
|
||||
|
||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -113,9 +113,11 @@ int pending_traps[NSIG];
|
||||
trap command (e.g., when `return' is executed in the trap command). */
|
||||
int running_trap;
|
||||
|
||||
/* The variable context (function execution level) when we began running
|
||||
this trap command. */
|
||||
int trap_variable_context;
|
||||
/* The execution context (function/source execution level) when we began
|
||||
running this trap command. This is used to determine whether we have
|
||||
executed any shell functions or sourced files from the trap action, and
|
||||
determines where `return' without arguments gets its return status. */
|
||||
int trap_return_context;
|
||||
|
||||
/* Set to last_command_exit_value before running a trap. */
|
||||
int trap_saved_exit_value;
|
||||
@@ -341,7 +343,7 @@ run_pending_traps ()
|
||||
ps = save_pipestatus_array ();
|
||||
#endif
|
||||
old_running = running_trap;
|
||||
old_context = trap_variable_context;
|
||||
old_context = trap_return_context;
|
||||
|
||||
for (sig = 1; sig < NSIG; sig++)
|
||||
{
|
||||
@@ -351,7 +353,7 @@ run_pending_traps ()
|
||||
{
|
||||
/* XXX - set last_command_exit_value = trap_saved_exit_value here? */
|
||||
running_trap = sig + 1;
|
||||
trap_variable_context = variable_context;
|
||||
trap_return_context = funcnest + sourcenest;
|
||||
|
||||
if (sig == SIGINT)
|
||||
{
|
||||
@@ -477,7 +479,7 @@ run_pending_traps ()
|
||||
if (function_code)
|
||||
{
|
||||
running_trap = old_running; /* XXX */
|
||||
trap_variable_context = old_context;
|
||||
trap_return_context = old_context;
|
||||
/* caller will set last_command_exit_value */
|
||||
sh_longjmp (return_catch, 1);
|
||||
}
|
||||
@@ -486,7 +488,7 @@ run_pending_traps ()
|
||||
|
||||
pending_traps[sig] = 0; /* XXX - move before evalstring? */
|
||||
running_trap = old_running;
|
||||
trap_variable_context = old_context;
|
||||
trap_return_context = old_context;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1006,7 +1008,7 @@ run_exit_trap ()
|
||||
|
||||
retval = trap_saved_exit_value;
|
||||
running_trap = 1;
|
||||
trap_variable_context = variable_context;
|
||||
trap_return_context = funcnest + sourcenest;
|
||||
|
||||
code = setjmp_nosigs (top_level);
|
||||
|
||||
@@ -1091,14 +1093,14 @@ _run_trap_internal (sig, tag)
|
||||
old_trap = trap_list[sig];
|
||||
old_modes = sigmodes[sig];
|
||||
old_running = running_trap;
|
||||
old_context = trap_variable_context;
|
||||
old_context = trap_return_context;
|
||||
|
||||
sigmodes[sig] |= SIG_INPROGRESS;
|
||||
sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
|
||||
trap_command = savestring (old_trap);
|
||||
|
||||
running_trap = sig + 1;
|
||||
trap_variable_context = variable_context;
|
||||
trap_return_context = funcnest + sourcenest;
|
||||
|
||||
old_int = interrupt_state; /* temporarily suppress pending interrupts */
|
||||
CLRINTERRUPT;
|
||||
@@ -1161,7 +1163,7 @@ _run_trap_internal (sig, tag)
|
||||
|
||||
running_trap = old_running;
|
||||
interrupt_state = old_int;
|
||||
trap_variable_context = old_context;
|
||||
trap_return_context = old_context;
|
||||
|
||||
if (sigmodes[sig] & SIG_CHANGED)
|
||||
{
|
||||
|
||||
@@ -63,7 +63,7 @@ extern char *trap_list[];
|
||||
extern int trapped_signal_received;
|
||||
extern int wait_signal_received;
|
||||
extern int running_trap;
|
||||
extern int trap_variable_context;
|
||||
extern int trap_return_context;
|
||||
extern int trap_saved_exit_value;
|
||||
extern int suppress_debug_trap_verbose;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user