mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-29 16:39:53 +02:00
commit bash-20160429 snapshot
This commit is contained in:
@@ -10714,3 +10714,87 @@ lib/readline/complete.c
|
||||
or equal to the length of the string to be printed (print_len), make
|
||||
sure to set the prefix length to 0 so the entire string is printed.
|
||||
From a report from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
4/25
|
||||
----
|
||||
subst.c
|
||||
- command_substitute: update the conditions under which we give the
|
||||
terminal to pipeline_pgrp with give_terminal_to to the same ones
|
||||
where wait_for uses to decide whether to give the terminal back to
|
||||
shell_pgrp. This code exists to undo the work wait_for does; it
|
||||
has to give the terminal back to pipeline_pgrp only under those
|
||||
conditions when wait_for gives it back to the shell pgrp. Fix for
|
||||
bug reported by Paulo Bardes <bardes0022@gmail.com>
|
||||
|
||||
4/26
|
||||
----
|
||||
bashline.c
|
||||
- bash_filename_stat_hook: temporarily disable the `nounset' shell
|
||||
option around calls to expand_prompt_string so we don't get error
|
||||
messages during completion. Fixes issue reported by Eric Pruitt
|
||||
<eric.pruitt@gmail.com>
|
||||
|
||||
4/27
|
||||
----
|
||||
doc/{bash.1,bashref.texi}
|
||||
- extdebug: clarify that having this option enabled at shell startup
|
||||
acts identically to --debugger. From a report from Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
|
||||
jobs.[ch]
|
||||
- wait_for_single_pid: now takes additional `int flags' argument
|
||||
|
||||
{jobs,execute_cmd}.c,builtins/wait.def
|
||||
- wait_for_single_pid: changed callers to add extra argument
|
||||
|
||||
jobs.c
|
||||
- wait_for_single_pid: if (flags & 1) == 0, don't print the error message
|
||||
if PID isn't found; changed execute_pipeline call when lastpipe is
|
||||
set
|
||||
|
||||
4/28
|
||||
----
|
||||
general.c
|
||||
- bash_tilde_expand: try not setting interrupt_immediately or
|
||||
terminate_immediately; see what happens with networked password
|
||||
databases
|
||||
|
||||
4/29
|
||||
----
|
||||
subst.c
|
||||
- parameter_brace_expand, parameter_brace_expand_rhs: now take an
|
||||
additional `pflags' argument from its caller so we can pass
|
||||
state
|
||||
- parameter_brace_expand_rhs: if expand_string_for_rhs returns a
|
||||
quoted null, but l_hasdollat is set to 1, meaning we saw a quoted
|
||||
"$@" of some form, we need to turn off special handling of "$@"
|
||||
so something like "${@-${@-$@}}" expands to an empty string like
|
||||
Posix says it should. Fixes bug reported by Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
|
||||
5/1
|
||||
---
|
||||
variables.c
|
||||
- bind_variable_internal: if we have a nameref variable with a valid
|
||||
array reference that is invalid for assignment (e.g., a[*]), and
|
||||
assign_array_element returns NULL, short-circuit and return NULL.
|
||||
Fixes bug reported by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
general.[ch]
|
||||
- valid_nameref_value: new function, return 1 if passed argument is
|
||||
a valid variable name argument for a nameref variable: a valid
|
||||
identifier, a valid array reference, or a valid positional
|
||||
parameter. Second argument indicates whether the value is to be
|
||||
used for an assignment; in this case, return an error if the name
|
||||
consists of all digits
|
||||
|
||||
builtins/declare.def
|
||||
- declare_internal: disallow values for nameref variables that don't
|
||||
pass the tests in valid_nameref_value. Part of fix for bug
|
||||
reported by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
variables.c
|
||||
- bind_variable_internal: if trying to assign a value to a nameref
|
||||
variable, throw an error if valid_nameref_value fails (with a second
|
||||
argument of 1). More fixes for bug reported by Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
|
||||
@@ -1061,6 +1061,7 @@ tests/jobs.right f
|
||||
tests/lastpipe.right f
|
||||
tests/lastpipe.tests f
|
||||
tests/lastpipe1.sub f
|
||||
tests/lastpipe2.sub f
|
||||
tests/mapfile.data f
|
||||
tests/mapfile.right f
|
||||
tests/mapfile.tests f
|
||||
|
||||
+12
@@ -54,6 +54,7 @@
|
||||
#include "pathexp.h"
|
||||
#include "shmbutil.h"
|
||||
#include "trap.h"
|
||||
#include "flags.h"
|
||||
|
||||
#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
|
||||
# include <mbstr.h> /* mbschr */
|
||||
@@ -1648,6 +1649,11 @@ bash_default_completion (text, start, end, qc, compflags)
|
||||
else
|
||||
{
|
||||
matches = rl_completion_matches (text, variable_completion_function);
|
||||
/* If a single match, see if it expands to a directory name and append
|
||||
a slash if it does. This requires us to expand the variable name,
|
||||
so we don't want to display errors if the variable is unset. This
|
||||
can happen with dynamic variables whose value has never been
|
||||
requested. */
|
||||
if (matches && matches[0] && matches[1] == 0)
|
||||
{
|
||||
t = savestring (matches[0]);
|
||||
@@ -3124,6 +3130,7 @@ bash_filename_stat_hook (dirname)
|
||||
{
|
||||
char *local_dirname, *new_dirname, *t;
|
||||
int should_expand_dirname, return_value;
|
||||
int global_nounset;
|
||||
WORD_LIST *wl;
|
||||
struct stat sb;
|
||||
|
||||
@@ -3140,7 +3147,12 @@ bash_filename_stat_hook (dirname)
|
||||
if (should_expand_dirname)
|
||||
{
|
||||
new_dirname = savestring (local_dirname);
|
||||
/* no error messages, and expand_prompt_string doesn't longjmp so we don't
|
||||
have to worry about restoring this setting. */
|
||||
global_nounset = unbound_vars_is_error;
|
||||
unbound_vars_is_error = 0;
|
||||
wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB); /* does the right thing */
|
||||
unbound_vars_is_error = global_nounset;
|
||||
if (wl)
|
||||
{
|
||||
free (new_dirname);
|
||||
|
||||
+10
-4
@@ -341,8 +341,8 @@ declare_internal (list, local_var)
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
#if 0
|
||||
if (value && *value && legal_identifier (value) == 0)
|
||||
#if 1
|
||||
if (value && *value && valid_nameref_value (value, 0) == 0)
|
||||
{
|
||||
builtin_error (_("%s: invalid variable name for name reference"), value);
|
||||
assign_error++;
|
||||
@@ -402,6 +402,12 @@ declare_internal (list, local_var)
|
||||
var = make_local_array_variable (name, making_array_special);
|
||||
else
|
||||
#endif
|
||||
if (offset == 0 && (flags_on & att_nameref))
|
||||
{
|
||||
refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
|
||||
var = 0;
|
||||
}
|
||||
else
|
||||
var = make_local_variable (name); /* sets att_invisible for new vars */
|
||||
if (var == 0)
|
||||
{
|
||||
@@ -570,8 +576,8 @@ declare_internal (list, local_var)
|
||||
}
|
||||
else if (flags_on & att_nameref)
|
||||
{
|
||||
#if 0
|
||||
if (nameref_p (var) == 0 && var_isset (var) && var_isnull (var) == 0 && legal_identifier (value_cell (var)) == 0)
|
||||
#if 1
|
||||
if (nameref_p (var) == 0 && var_isset (var) && var_isnull (var) == 0 && valid_nameref_value (value_cell (var), 0) == 0)
|
||||
{
|
||||
builtin_error (_("%s: invalid variable name for name reference"), value_cell (var));
|
||||
any_failed++;
|
||||
|
||||
+1
-1
@@ -179,7 +179,7 @@ wait_builtin (list)
|
||||
if (legal_number (w, &pid_value) && pid_value == (pid_t)pid_value)
|
||||
{
|
||||
pid = (pid_t)pid_value;
|
||||
status = wait_for_single_pid (pid);
|
||||
status = wait_for_single_pid (pid, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+5
-3
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet.ramey@case.edu
|
||||
.\"
|
||||
.\" Last Change: Mon Feb 8 10:15:48 EST 2016
|
||||
.\" Last Change: Wed Apr 27 09:19:58 EDT 2016
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2016 February 8" "GNU Bash 4.4"
|
||||
.TH BASH 1 "2016 April 27" "GNU Bash 4.4"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -9627,7 +9627,9 @@ If set, aliases are expanded as described above under
|
||||
This option is enabled by default for interactive shells.
|
||||
.TP 8
|
||||
.B extdebug
|
||||
If set, behavior intended for use by debuggers is enabled:
|
||||
If set at shell invocation, arrange to execute the debugger profile
|
||||
before the shell starts, identical to the \fB\-\-debugger\fP option.
|
||||
If set after invocation, behavior intended for use by debuggers is enabled:
|
||||
.RS
|
||||
.TP
|
||||
.B 1.
|
||||
|
||||
+4
-2
@@ -1513,7 +1513,7 @@ When applied to a string-valued variable, @var{value} is expanded and
|
||||
appended to the variable's value.
|
||||
|
||||
A variable can be assigned the @var{nameref} attribute using the
|
||||
@option{-n} option to the \fBdeclare\fP or \fBlocal\fP builtin commands
|
||||
@option{-n} option to the @code{declare} or @code{local} builtin commands
|
||||
(@pxref{Bash Builtins})
|
||||
to create a @var{nameref}, or a reference to another variable.
|
||||
This allows variables to be manipulated indirectly.
|
||||
@@ -5143,7 +5143,9 @@ If set, aliases are expanded as described below under Aliases,
|
||||
This option is enabled by default for interactive shells.
|
||||
|
||||
@item extdebug
|
||||
If set, behavior intended for use by debuggers is enabled:
|
||||
If set at shell invocation, arrange to execute the debugger profile
|
||||
before the shell starts, identical to the @option{--debugger} option.
|
||||
If set after invocation, behavior intended for use by debuggers is enabled:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
|
||||
+3
-3
@@ -2,10 +2,10 @@
|
||||
Copyright (C) 1988-2016 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Sun Feb 28 15:32:09 EST 2016
|
||||
@set LASTCHANGE Wed Apr 27 09:19:38 EDT 2016
|
||||
|
||||
@set EDITION 4.4
|
||||
@set VERSION 4.4
|
||||
|
||||
@set UPDATED 28 February 2016
|
||||
@set UPDATED-MONTH February 2016
|
||||
@set UPDATED 27 April 2016
|
||||
@set UPDATED-MONTH April 2016
|
||||
|
||||
+1
-1
@@ -2486,7 +2486,7 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
lstdin = wait_for (lastpid);
|
||||
}
|
||||
else
|
||||
lstdin = wait_for_single_pid (lastpid); /* checks bgpids list */
|
||||
lstdin = wait_for_single_pid (lastpid, 0); /* checks bgpids list */
|
||||
#else
|
||||
lstdin = wait_for (lastpid);
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* general.c -- Stuff that is used by all files. */
|
||||
|
||||
/* Copyright (C) 1987-2015 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -227,6 +227,24 @@ legal_identifier (name)
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
valid_nameref_value (name, for_assignment)
|
||||
char *name;
|
||||
int for_assignment;
|
||||
{
|
||||
intmax_t r;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (legal_identifier (name) || valid_array_reference (name, 0))
|
||||
#else
|
||||
if (legal_identifier (name))
|
||||
#endif
|
||||
return 1;
|
||||
if (for_assignment == 0 && legal_number (name, &r))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure that WORD is a valid shell identifier, i.e.
|
||||
does not contain a dollar sign, nor is quoted in any way. Nor
|
||||
does it consist of all digits. If CHECK_WORD is non-zero,
|
||||
@@ -1039,6 +1057,7 @@ bash_tilde_expand (s, assign_p)
|
||||
int old_immed, old_term, r;
|
||||
char *ret;
|
||||
|
||||
#if 0
|
||||
old_immed = interrupt_immediately;
|
||||
old_term = terminate_immediately;
|
||||
/* We want to be able to interrupt tilde expansion. Ordinarily, we can just
|
||||
@@ -1048,6 +1067,7 @@ bash_tilde_expand (s, assign_p)
|
||||
if (any_signals_trapped () < 0)
|
||||
interrupt_immediately = 1;
|
||||
terminate_immediately = 1;
|
||||
#endif
|
||||
|
||||
tilde_additional_prefixes = assign_p == 0 ? (char **)0
|
||||
: (assign_p == 2 ? bash_tilde_prefixes2 : bash_tilde_prefixes);
|
||||
@@ -1057,8 +1077,10 @@ bash_tilde_expand (s, assign_p)
|
||||
r = (*s == '~') ? unquoted_tilde_word (s) : 1;
|
||||
ret = r ? tilde_expand (s) : savestring (s);
|
||||
|
||||
#if 0
|
||||
interrupt_immediately = old_immed;
|
||||
terminate_immediately = old_term;
|
||||
#endif
|
||||
|
||||
QUIT;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* general.h -- defines that everybody likes to use. */
|
||||
|
||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -289,6 +289,7 @@ extern int legal_identifier __P((char *));
|
||||
extern int importable_function_name __P((char *, size_t));
|
||||
extern int exportable_function_name __P((char *));
|
||||
extern int check_identifier __P((WORD_DESC *, int));
|
||||
extern int valid_nameref_value __P((char *, int));
|
||||
extern int legal_alias_name __P((char *, int));
|
||||
extern int assignment __P((const char *, int));
|
||||
|
||||
|
||||
@@ -2313,10 +2313,13 @@ find_last_pid (job, block)
|
||||
This low-level function prints an error message if PID is not
|
||||
a child of this shell. It returns -1 if it fails, or whatever
|
||||
wait_for returns otherwise. If the child is not found in the
|
||||
jobs table, it returns 127. */
|
||||
jobs table, it returns 127. If FLAGS doesn't include 1, we
|
||||
suppress the error message if PID isn't found. */
|
||||
|
||||
int
|
||||
wait_for_single_pid (pid)
|
||||
wait_for_single_pid (pid, flags)
|
||||
pid_t pid;
|
||||
int flags;
|
||||
{
|
||||
register PROCESS *child;
|
||||
sigset_t set, oset;
|
||||
@@ -2335,7 +2338,8 @@ wait_for_single_pid (pid)
|
||||
|
||||
if (child == 0)
|
||||
{
|
||||
internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
|
||||
if (flags & 1)
|
||||
internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
|
||||
return (127);
|
||||
}
|
||||
|
||||
@@ -2395,7 +2399,7 @@ wait_for_background_pids ()
|
||||
UNBLOCK_CHILD (oset);
|
||||
QUIT;
|
||||
errno = 0; /* XXX */
|
||||
r = wait_for_single_pid (pid);
|
||||
r = wait_for_single_pid (pid, 1);
|
||||
if (r == -1)
|
||||
{
|
||||
/* If we're mistaken about job state, compensate. */
|
||||
@@ -2789,7 +2793,11 @@ itrace("wait_for: blocking wait for %d returns %d child = %p", (int)pid, r, chil
|
||||
if (job == NO_JOB)
|
||||
itrace("wait_for: job == NO_JOB, giving the terminal to shell_pgrp (%ld)", (long)shell_pgrp);
|
||||
#endif
|
||||
/* Don't modify terminal pgrp if we are running in background or a subshell */
|
||||
/* Don't modify terminal pgrp if we are running in background or a
|
||||
subshell. Make sure subst.c:command_substitute uses the same
|
||||
conditions to determine whether or not it should undo this and
|
||||
give the terminal to pipeline_pgrp. */
|
||||
|
||||
if (running_in_background == 0 && (subshell_environment&(SUBSHELL_ASYNC|SUBSHELL_PIPE)) == 0)
|
||||
give_terminal_to (shell_pgrp, 0);
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ extern int set_tty_state __P((void));
|
||||
extern int job_exit_status __P((int));
|
||||
extern int job_exit_signal __P((int));
|
||||
|
||||
extern int wait_for_single_pid __P((pid_t));
|
||||
extern int wait_for_single_pid __P((pid_t, int));
|
||||
extern void wait_for_background_pids __P((void));
|
||||
extern int wait_for __P((pid_t));
|
||||
extern int wait_for_job __P((int));
|
||||
|
||||
@@ -1435,12 +1435,16 @@ It understands the EOF character or "exit" to exit the program.
|
||||
@example
|
||||
/* Standard include files. stdio.h is required. */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
|
||||
/* Used for select(2) */
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Standard readline include files. */
|
||||
@@ -1448,10 +1452,20 @@ It understands the EOF character or "exit" to exit the program.
|
||||
#include <readline/history.h>
|
||||
|
||||
static void cb_linehandler (char *);
|
||||
static void sighandler (int);
|
||||
|
||||
int running;
|
||||
int sigwinch_received;
|
||||
const char *prompt = "rltest$ ";
|
||||
|
||||
/* Handle SIGWINCH and window size changes when readline is not active and
|
||||
reading a character. */
|
||||
static void
|
||||
sighandler (int sig)
|
||||
@{
|
||||
sigwinch_received = 1;
|
||||
@}
|
||||
|
||||
/* Callback function called for each line when accept-line executed, EOF
|
||||
seen, or EOF character read. This sets a flag and returns; it could
|
||||
also call exit(3). */
|
||||
@@ -1486,6 +1500,13 @@ main (int c, char **v)
|
||||
fd_set fds;
|
||||
int r;
|
||||
|
||||
/* Set the default locale values according to environment variables. */
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
/* Handle window size changes when readline is not active and reading
|
||||
characters. */
|
||||
signal (SIGWINCH, sighandler);
|
||||
|
||||
/* Install the line handler. */
|
||||
rl_callback_handler_install (prompt, cb_linehandler);
|
||||
|
||||
@@ -1500,12 +1521,19 @@ main (int c, char **v)
|
||||
FD_SET (fileno (rl_instream), &fds);
|
||||
|
||||
r = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
if (r < 0 && errno != EINTR)
|
||||
@{
|
||||
perror ("rltest: select");
|
||||
rl_callback_handler_remove ();
|
||||
break;
|
||||
@}
|
||||
if (sigwinch_received)
|
||||
@{
|
||||
rl_resize_terminal ();
|
||||
sigwinch_received = 0;
|
||||
}@
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET (fileno (rl_instream), &fds))
|
||||
rl_callback_read_char ();
|
||||
|
||||
+5
-1
@@ -236,7 +236,11 @@ tilde_expand (string)
|
||||
string += end;
|
||||
|
||||
expansion = tilde_expand_word (tilde_word);
|
||||
xfree (tilde_word);
|
||||
|
||||
if (expansion == 0)
|
||||
expansion = tilde_word;
|
||||
else
|
||||
xfree (tilde_word);
|
||||
|
||||
len = strlen (expansion);
|
||||
#ifdef __CYGWIN__
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2015 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -170,9 +170,9 @@ int no_longjmp_on_fatal_error = 0;
|
||||
|
||||
/* Extern functions and variables from different files. */
|
||||
extern int last_command_exit_value, last_command_exit_signal;
|
||||
extern int subshell_environment, line_number;
|
||||
extern int subshell_environment, running_in_background;
|
||||
extern int subshell_level, parse_and_execute_level, sourcelevel;
|
||||
extern int eof_encountered;
|
||||
extern int eof_encountered, line_number;
|
||||
extern int return_catch_flag, return_catch_value;
|
||||
extern pid_t dollar_dollar_pid;
|
||||
extern int posixly_correct;
|
||||
@@ -310,7 +310,7 @@ static int chk_arithsub __P((const char *, int));
|
||||
static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int, arrayind_t *));
|
||||
static char *parameter_brace_find_indir __P((char *, int, int, int));
|
||||
static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
|
||||
static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
|
||||
static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int, int *, int *));
|
||||
static void parameter_brace_expand_error __P((char *, char *));
|
||||
|
||||
static int valid_length_expression __P((char *));
|
||||
@@ -3728,9 +3728,9 @@ expand_string_leave_quoted (string, quoted)
|
||||
/* This does not perform word splitting or dequote the WORD_LIST
|
||||
it returns. */
|
||||
static WORD_LIST *
|
||||
expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
|
||||
expand_string_for_rhs (string, quoted, dollar_at_p, expanded_p)
|
||||
char *string;
|
||||
int quoted, *dollar_at_p, *has_dollar_at;
|
||||
int quoted, *dollar_at_p, *expanded_p;
|
||||
{
|
||||
WORD_DESC td;
|
||||
WORD_LIST *tresult;
|
||||
@@ -3741,7 +3741,7 @@ expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
|
||||
expand_no_split_dollar_star = 1;
|
||||
td.flags = W_NOSPLIT2; /* no splitting, remove "" and '' */
|
||||
td.word = string;
|
||||
tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
|
||||
tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, expanded_p);
|
||||
expand_no_split_dollar_star = 0;
|
||||
|
||||
return (tresult);
|
||||
@@ -6174,8 +6174,13 @@ command_substitute (string, quoted)
|
||||
pipeline_pgrp is non-zero only while we are constructing a
|
||||
pipeline, so what we are concerned about is whether or not that
|
||||
pipeline was started in the background. A pipeline started in
|
||||
the background should never get the tty back here. */
|
||||
if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
|
||||
the background should never get the tty back here. We duplicate
|
||||
the conditions that wait_for tests to make sure we only give
|
||||
the terminal back to pipeline_pgrp under the conditions that wait_for
|
||||
gave it to shell_pgrp. If wait_for doesn't mess with the terminal
|
||||
pgrp, we should not either. */
|
||||
if (interactive && pipeline_pgrp != (pid_t)0 && running_in_background == 0 &&
|
||||
(subshell_environment & (SUBSHELL_ASYNC|SUBSHELL_PIPE)) == 0)
|
||||
give_terminal_to (pipeline_pgrp, 0);
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
@@ -6579,45 +6584,49 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
|
||||
"-", "+", or "=". QUOTED is true if the entire brace expression occurs
|
||||
between double quotes. */
|
||||
static WORD_DESC *
|
||||
parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
|
||||
parameter_brace_expand_rhs (name, value, c, quoted, pflags, qdollaratp, hasdollarat)
|
||||
char *name, *value;
|
||||
int c, quoted, *qdollaratp, *hasdollarat;
|
||||
int c, quoted, pflags, *qdollaratp, *hasdollarat;
|
||||
{
|
||||
WORD_DESC *w;
|
||||
WORD_LIST *l;
|
||||
char *t, *t1, *temp, *vname;
|
||||
int hasdol;
|
||||
int l_hasdollat, sindex;
|
||||
|
||||
/*itrace("parameter_brace_expand_rhs: %s:%s pflags = %d", name, value, pflags);*/
|
||||
/* If the entire expression is between double quotes, we want to treat
|
||||
the value as a double-quoted string, with the exception that we strip
|
||||
embedded unescaped double quotes (for sh backwards compatibility). */
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
|
||||
{
|
||||
hasdol = 0;
|
||||
temp = string_extract_double_quoted (value, &hasdol, 1);
|
||||
sindex = 0;
|
||||
temp = string_extract_double_quoted (value, &sindex, 1);
|
||||
}
|
||||
else
|
||||
temp = value;
|
||||
|
||||
w = alloc_word_desc ();
|
||||
hasdol = 0;
|
||||
l_hasdollat = 0;
|
||||
/* XXX was 0 not quoted */
|
||||
l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
|
||||
l = *temp ? expand_string_for_rhs (temp, quoted, &l_hasdollat, (int *)NULL)
|
||||
: (WORD_LIST *)0;
|
||||
if (hasdollarat)
|
||||
*hasdollarat = hasdol || (l && l->next);
|
||||
*hasdollarat = l_hasdollat || (l && l->next);
|
||||
if (temp != value)
|
||||
free (temp);
|
||||
if (l)
|
||||
{
|
||||
/* If l->next is not null, we know that TEMP contained "$@", since that
|
||||
is the only expansion that creates more than one word. */
|
||||
if (qdollaratp && ((hasdol && quoted) || l->next))
|
||||
*qdollaratp = 1;
|
||||
if (qdollaratp && ((l_hasdollat && quoted) || l->next))
|
||||
{
|
||||
/*itrace("parameter_brace_expand_rhs: %s:%s: l != NULL, set *qdollaratp", name, value);*/
|
||||
*qdollaratp = 1;
|
||||
}
|
||||
|
||||
/* The expansion of TEMP returned something. We need to treat things
|
||||
slightly differently if HASDOL is non-zero. If we have "$@", the
|
||||
individual words have already been quoted. We need to turn them
|
||||
slightly differently if L_HASDOLLAT is non-zero. If we have "$@",
|
||||
the individual words have already been quoted. We need to turn them
|
||||
into a string with the words separated by the first character of
|
||||
$IFS without any additional quoting, so string_list_dollar_at won't
|
||||
do the right thing. If IFS is null, we want "$@" to split into
|
||||
@@ -6630,7 +6639,7 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
|
||||
w->flags |= W_SPLITSPACE;
|
||||
}
|
||||
else
|
||||
temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
|
||||
temp = (l_hasdollat || l->next) ? string_list_dollar_star (l) : string_list (l);
|
||||
|
||||
/* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
|
||||
a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
|
||||
@@ -6641,24 +6650,32 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
|
||||
if (l->next == 0 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp) && QUOTED_NULL (l->word->word) && (l->word->flags & W_HASQUOTEDNULL))
|
||||
{
|
||||
w->flags |= W_HASQUOTEDNULL;
|
||||
/*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null, turning off qdollaratp", name, value);*/
|
||||
/* If we return a quoted null with L_HASDOLLARAT, we either have a
|
||||
construct like "${@-$@}" or "${@-${@-$@}}" with no positional
|
||||
parameters or a quoted expansion of "$@" with $1 == ''. In either
|
||||
case, we don't want to enable special handling of $@. */
|
||||
if (qdollaratp && l_hasdollat)
|
||||
*qdollaratp = 0;
|
||||
}
|
||||
dispose_words (l);
|
||||
}
|
||||
else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
|
||||
else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && l_hasdollat)
|
||||
{
|
||||
/* Posix interp 221 changed the rules on this. The idea is that
|
||||
something like "$xxx$@" should expand the same as "${foo-$xxx$@}"
|
||||
when foo and xxx are unset. The problem is that it's not in any
|
||||
way backwards compatible and few other shells do it. We're eventually
|
||||
going to try and split the difference (heh) a little bit here. */
|
||||
/* hasdol == 1 means we saw a quoted dollar at. */
|
||||
/* l_hasdollat == 1 means we saw a quoted dollar at. */
|
||||
|
||||
/* The brace expansion occurred between double quotes and there was
|
||||
a $@ in TEMP. It does not matter if the $@ is quoted, as long as
|
||||
it does not expand to anything. In this case, we want to return
|
||||
a quoted empty string. */
|
||||
a quoted empty string. Posix interp 888 */
|
||||
temp = make_quoted_char ('\0');
|
||||
w->flags |= W_HASQUOTEDNULL;
|
||||
/*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null", name, value);*/
|
||||
}
|
||||
else
|
||||
temp = (char *)NULL;
|
||||
@@ -7795,7 +7812,7 @@ chk_arithsub (s, len)
|
||||
static WORD_DESC *
|
||||
parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, contains_dollar_at)
|
||||
char *string;
|
||||
int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at, pflags;
|
||||
int *indexp, quoted, pflags, *quoted_dollar_atp, *contains_dollar_at;
|
||||
{
|
||||
int check_nullness, var_is_set, var_is_null, var_is_special;
|
||||
int want_substring, want_indir, want_patsub, want_casemod;
|
||||
@@ -8299,6 +8316,7 @@ bad_substitution:
|
||||
quoted |= Q_DOLBRACE;
|
||||
ret = parameter_brace_expand_rhs (name, value, c,
|
||||
quoted,
|
||||
pflags,
|
||||
quoted_dollar_atp,
|
||||
contains_dollar_at);
|
||||
/* XXX - fix up later, esp. noting presence of
|
||||
@@ -8346,7 +8364,7 @@ bad_substitution:
|
||||
removed. */
|
||||
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
quoted |= Q_DOLBRACE;
|
||||
ret = parameter_brace_expand_rhs (name, value, c, quoted,
|
||||
ret = parameter_brace_expand_rhs (name, value, c, quoted, pflags,
|
||||
quoted_dollar_atp,
|
||||
contains_dollar_at);
|
||||
/* XXX - fix up later, esp. noting presence of
|
||||
@@ -8388,6 +8406,7 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
WORD_DESC *tdesc, *ret;
|
||||
int tflag;
|
||||
|
||||
/*itrace("param_expand: `%s' pflags = %d", string+*sindex, pflags);*/
|
||||
zindex = *sindex;
|
||||
c = string[++zindex];
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
BUILD_DIR=/usr/local/build/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
|
||||
+2
-1
@@ -129,7 +129,8 @@ ok 2
|
||||
ok 3
|
||||
echo shopt a
|
||||
shopt a
|
||||
echo a b c d 2 > /dev/null
|
||||
echo a b c d 2> /dev/null
|
||||
a b c d
|
||||
!
|
||||
!
|
||||
!
|
||||
|
||||
@@ -123,6 +123,8 @@ echo ${!var2}
|
||||
# history_comment_char
|
||||
echo ok 3 # !1200
|
||||
|
||||
# bash versions through bash-4.3 fail this; they make the digit preceding the
|
||||
# > into a separate word, changing the meaning of the redirection
|
||||
shopt a b c d 2>/dev/null
|
||||
echo !shopt-1
|
||||
|
||||
|
||||
@@ -8,3 +8,12 @@ last = c
|
||||
1 -- 0 0 1
|
||||
1 -- 0 1 0
|
||||
lastpipe1.sub returns 14
|
||||
A1
|
||||
A2
|
||||
B1
|
||||
B2
|
||||
HI
|
||||
A1
|
||||
A2
|
||||
B1
|
||||
B2
|
||||
|
||||
@@ -56,3 +56,6 @@ set +o pipefail
|
||||
|
||||
${THIS_SH} ./lastpipe1.sub
|
||||
echo lastpipe1.sub returns $?
|
||||
|
||||
${THIS_SH} ./lastpipe2.sub
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
shopt -s lastpipe
|
||||
echo -e 'A\nB' | while read letter; do
|
||||
echo -e '1\n2' | while read digit; do
|
||||
echo $letter$digit
|
||||
done
|
||||
done
|
||||
|
||||
myPipefunc()
|
||||
{
|
||||
cat | tee $TMPDIR/outfile
|
||||
}
|
||||
echo HI | myPipefunc
|
||||
|
||||
echo -e 'A\nB' | while read letter; do
|
||||
echo -e '1\n2' | while read digit; do
|
||||
echo $letter$digit | myPipefunc
|
||||
done
|
||||
done
|
||||
|
||||
rm -f $TMPDIR/outfile
|
||||
@@ -0,0 +1 @@
|
||||
B2
|
||||
+14
-3
@@ -2629,15 +2629,26 @@ bind_variable_internal (name, value, table, hflags, aflags)
|
||||
|
||||
/* The first clause handles `declare -n ref; ref=x;' */
|
||||
if (entry && invisible_p (entry) && nameref_p (entry))
|
||||
goto assign_value;
|
||||
{
|
||||
if (valid_nameref_value (value, 1) == 0)
|
||||
{
|
||||
sh_invalidid (value);
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
goto assign_value;
|
||||
}
|
||||
else if (entry && nameref_p (entry))
|
||||
{
|
||||
newval = nameref_cell (entry);
|
||||
#if defined (ARRAY_VARS)
|
||||
/* declare -n foo=x[2] */
|
||||
if (valid_array_reference (newval, 0))
|
||||
/* XXX - should it be aflags? */
|
||||
entry = assign_array_element (newval, make_variable_value (entry, value, 0), aflags);
|
||||
{
|
||||
/* XXX - should it be aflags? */
|
||||
entry = assign_array_element (newval, make_variable_value (entry, value, 0), aflags);
|
||||
if (entry == 0)
|
||||
return entry;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user