- in get_name_for_error, use dollar_vars[0] if the name returned from
looking in $BASH_SOURCE[0] is the empty string as well as if it's
null
+
+ 5/31
+ ----
+arrayfunc.c
+ - change array_value_internal to set *RTYPE to 1 if the reference is
+ array[*] and 2 if the reference is array[@]
+
+subst.c
+ - in parameter_brace_expand_word, set the flags returned by the word
+ desc to include W_HASQUOTEDNULL if array_value returns QUOTED_NULL
+ for an array reference like x[*] and the word is quoted. Fixes bug
+ reported by Christophe Martin <schplurtz@free.fr>
+
+ 6/1
+ ---
+jobs.c
+ - several changes to preserve errno if tcgetpgrp/tcgetattr/tcsetattr
+ fail, for subsequent error messages
+ - change initialize_job_control to turn off job control if the terminal
+ pgrp == -1 or is not equal to shell_pgrp (with an error message)
+ - in initialize_job_control, if the shell has been forced interactive
+ with -i, make sure stderr is hooked to a tty before using it as
+ the controlling terminal. If it's not, try to open /dev/tty and
+ assign it to shell_tty. Fixes problems reported by Derek Fawcus
+ <dfawcus@cisco.com>
+
builtins/help.def
- fix bug in `help' two-column printing to avoid referencing
shell_builtins[num_shell_builtins]
+
+error.c
+ - in get_name_for_error, use dollar_vars[0] if the name returned from
+ looking in $BASH_SOURCE[0] is the empty string as well as if it's
+ null
+
+ 5/31
+ ----
+arrayfunc.c
+ - change array_value_internal to set *RTYPE to 1 if the reference is
+ array[*] and 2 if the reference is array[@]
+
+subst.c
+ - in parameter_brace_expand_word, set the flags returned by the word
+ desc to include W_HASQUOTEDNULL if array_value returns QUOTED_NULL
+ for an array reference like x[*] and the word is quoted. Fixes bug
+ reported by Christophe Martin <schplurtz@free.fr>
+
+ 6/1
+ ---
+jobs.c
+ - several changes to preserve errno if tcgetpgrp/tcgetattr/tcsetattr
+ fail, for subsequent error messages
+ - change initialize_job_control to turn off job control if the terminal
+ pgrp == -1 or is not equal to shell_pgrp (with an error message)
tests/exec5.sub f
tests/exec6.sub f
tests/exec7.sub f
+tests/exec8.sub f
tests/exp.tests f
tests/exp.right f
tests/exp1.sub f
/* Return a string containing the elements in the array and subscript
described by S. If the subscript is * or @, obeys quoting rules akin
to the expansion of $* and $@ including double quoting. If RTYPE
- is non-null it gets 1 if the array reference is name[@] or name[*]
- and 0 otherwise. */
+ is non-null it gets 1 if the array reference is name[*], 2 if the
+ reference is name[@], and 0 otherwise. */
static char *
array_value_internal (s, quoted, allow_all, rtype)
char *s;
if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
{
if (rtype)
- *rtype = 1;
+ *rtype = (t[0] == '*') ? 1 : 2;
if (allow_all == 0)
{
err_badarraysub (s);
if (expok == 0)
{
last_command_exit_value = EXECUTION_FAILURE;
+
+ top_level_cleanup ();
jump_to_top_level (DISCARD);
}
return val;
/* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
a single source file called builtins.def. */
-/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
"/* This file is manufactured by ./mkbuiltins, and should not be",
" edited by hand. See the source to mkbuiltins for details. */",
"",
- "/* Copyright (C) 1987-2002 Free Software Foundation, Inc.",
+ "/* Copyright (C) 1987-2007 Free Software Foundation, Inc.",
"",
" This file is part of GNU Bash, the Bourne Again SHell.",
"",
document_name (builtin));
fprintf
- (structfile, "N_( \"%s\"), (char *)NULL },\n",
+ (structfile, " N_(\"%s\"), (char *)NULL },\n",
builtin->shortdoc ? builtin->shortdoc : builtin->name);
}
$SHORT_DOC variables - Names and meanings of some shell variables
BASH_VERSION Version information for this Bash.
CDPATH A colon-separated list of directories to search
- for directries given as arguments to `cd'.
+ for directories given as arguments to `cd'.
GLOBIGNORE A colon-separated list of patterns describing filenames to
be ignored by pathname expansion.
#if defined (HISTORY)
echo .!(.|) *
A solution that works without extended globbing is given in the Unix Shell
-FAQ, posted periodically to comp.unix.shell.
+FAQ, posted periodically to comp.unix.shell. It's a variant of
+
+ echo .[!.]* ..?* *
+
+(The ..?* catches files with names of three or more characters beginning
+with `..')
Section H: Where do I go from here?
-This is the Bash FAQ, version 3.35, for Bash version 3.2.
+This is the Bash FAQ, version 3.36, for Bash version 3.2.
This document contains a set of frequently-asked questions concerning
Bash, the GNU Bourne-Again Shell. Bash is a freely-available command
notice the change?
E12) Why don't negative offsets in substring expansion work like I expect?
E13) Why does filename completion misbehave if a colon appears in the filename?
+E14) Why does quoting the pattern argument to the regular expression matching
+ conditional operator (=~) cause matching to stop working?
Section F: Things to watch out for on certain Unix versions
You can also quote the colon with a backslash to achieve the same result
temporarily.
+E14) Why does quoting the pattern argument to the regular expression matching
+ conditional operator (=~) cause regexp matching to stop working?
+
+In versions of bash prior to bash-3.2, the effect of quoting the regular
+expression argument to the [[ command's =~ operator was not specified.
+The practical effect was that double-quoting the pattern argument required
+backslashes to quote special pattern characters, which interfered with the
+backslash processing performed by double-quoted word expansion and was
+inconsistent with how the == shell pattern matching operator treated
+quoted characters.
+
+In bash-3.2, the shell was changed to internally quote characters in single-
+and double-quoted string arguments to the =~ operator, which suppresses the
+special meaning of the characters special to regular expression processing
+(`.', `[', `\', `(', `), `*', `+', `?', `{', `|', `^', and `$') and forces
+them to be matched literally. This is consistent with how the `==' pattern
+matching operator treats quoted portions of its pattern argument.
+
+Since the treatment of quoted string arguments was changed, several issues
+have arisen, chief among them the problem of white space in pattern arguments
+and the differing treatment of quoted strings between bash-3.1 and bash-3.2.
+Both problems may be solved by using a shell variable to hold the pattern.
+Since word splitting is not performed when expanding shell variables in all
+operands of the [[ command, this allows users to quote patterns as they wish
+when assigning the variable, then expand the values to a single string that
+may contain whitespace. The first problem may be solved by using backslashes
+or any other quoting mechanism to escape the white space in the patterns.
+
Section F: Things to watch out for on certain Unix versions
F1) Why can't I use command line editing in my `cmdtool'?
have equal precedence, followed by
.B ;
and
-.BR &,
+.BR & ,
which have equal precedence.
.PP
A sequence of one or more newlines may appear in a \fIlist\fP instead
/* Only print an error message if we're really interactive at
this time. */
if (interactive)
- sys_error ("[%ld: %d] tcgetattr", (long)getpid (), shell_level);
+ sys_error ("[%ld: %d (%d)] tcgetattr", (long)getpid (), shell_level, tty);
#endif
return -1;
}
/* Only print an error message if we're really interactive at
this time. */
if (interactive)
- sys_error ("[%ld: %d] tcsetattr", (long)getpid (), shell_level);
+ sys_error ("[%ld: %d (%d)] tcsetattr", (long)getpid (), shell_level, tty);
return -1;
}
#endif /* TERMIOS_TTY_DRIVER */
initialize_job_control (force)
int force;
{
+ pid_t t;
+ int t_errno;
+
+ t_errno = -1;
shell_pgrp = getpgid (0);
if (shell_pgrp == -1)
}
else
{
+ shell_tty = -1;
+
+ /* If forced_interactive is set, we skip the normal check that stderr
+ is attached to a tty, so we need to check here. If it's not, we
+ need to see whether we have a controlling tty by opening /dev/tty,
+ since trying to use job control tty pgrp manipulations on a non-tty
+ is going to fail. */
+ if (forced_interactive && isatty (fileno (stderr)) == 0)
+ shell_tty = open ("/dev/tty", O_RDWR|O_NONBLOCK);
+
/* Get our controlling terminal. If job_control is set, or
interactive is set, then this is an interactive shell no
matter where fd 2 is directed. */
- shell_tty = dup (fileno (stderr)); /* fd 2 */
+ if (shell_tty == -1)
+ shell_tty = dup (fileno (stderr)); /* fd 2 */
shell_tty = move_to_high_fd (shell_tty, 1, -1);
break;
}
+ if (terminal_pgrp == -1)
+ t_errno = errno;
+
/* Make sure that we are using the new line discipline. */
if (set_new_line_discipline (shell_tty) < 0)
{
{
if (give_terminal_to (shell_pgrp, 0) < 0)
{
+ t_errno = errno;
setpgid (0, original_pgrp);
shell_pgrp = original_pgrp;
job_control = 0;
}
}
+
+ if (job_control && ((t = tcgetpgrp (shell_tty)) == -1 || t != shell_pgrp))
+ {
+ if (t_errno != -1)
+ errno = t_errno;
+ sys_error (_("cannot set terminal process group (%d)"), t);
+ job_control = 0;
+ }
}
if (job_control == 0)
internal_error (_("no job control in this shell"));
int force;
{
sigset_t set, oset;
- int r;
+ int r, e;
r = 0;
if (job_control || force)
shell_tty, (long)getpid(), (long)pgrp);
#endif
r = -1;
+ e = errno;
}
else
terminal_pgrp = pgrp;
sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
}
+ if (r == -1)
+ errno = e;
return r;
}
/* The number of additional slots to allocate when we run out. */
#define JOB_SLOTS 8
+#define CTTYFD 2
+
typedef int sh_job_map_func_t __P((JOB *, int, int, int));
/* Variables used here but defined in other files. */
/* Only print an error message if we're really interactive at
this time. */
if (interactive)
- sys_error ("[%ld: %d] tcgetattr", (long)getpid (), shell_level);
+ sys_error ("[%ld: %d (%d)] tcgetattr", (long)getpid (), shell_level, tty);
#endif
return -1;
}
/* Only print an error message if we're really interactive at
this time. */
if (interactive)
- sys_error ("[%ld: %d] tcsetattr", (long)getpid (), shell_level);
+ sys_error ("[%ld: %d (%d)] tcsetattr", (long)getpid (), shell_level, tty);
return -1;
}
#endif /* TERMIOS_TTY_DRIVER */
initialize_job_control (force)
int force;
{
+ pid_t t;
+ int t_errno;
+
+ t_errno = -1;
shell_pgrp = getpgid (0);
if (shell_pgrp == -1)
}
else
{
+ shell_tty = -1;
+ if (forced_interactive && isatty (fileno (stderr)) == 0)
+ shell_tty = open ("/dev/tty", O_RDWR|O_NONBLOCK);
+
/* Get our controlling terminal. If job_control is set, or
interactive is set, then this is an interactive shell no
matter where fd 2 is directed. */
- shell_tty = dup (fileno (stderr)); /* fd 2 */
+ if (shell_tty == -1)
+ shell_tty = dup (fileno (stderr)); /* fd 2 */
shell_tty = move_to_high_fd (shell_tty, 1, -1);
break;
}
+ if (terminal_pgrp == -1)
+ t_errno = errno;
+
/* Make sure that we are using the new line discipline. */
if (set_new_line_discipline (shell_tty) < 0)
{
{
if (give_terminal_to (shell_pgrp, 0) < 0)
{
+ t_errno = errno;
setpgid (0, original_pgrp);
shell_pgrp = original_pgrp;
job_control = 0;
-internal_error ("cannot set terminal pgrp to %d: %s", shell_pgrp, strerror (errno));
}
}
+
+ if (job_control && ((t = tcgetpgrp (shell_tty)) == -1 || t != shell_pgrp))
+ {
+ if (t_errno != -1)
+ errno = t_errno;
+ sys_error (_("cannot set terminal process group (%d)"), t);
+ job_control = 0;
+ }
}
if (job_control == 0)
internal_error (_("no job control in this shell"));
int force;
{
sigset_t set, oset;
- int r;
+ int r, e;
r = 0;
if (job_control || force)
shell_tty, (long)getpid(), (long)pgrp);
#endif
r = -1;
+ e = errno;
}
else
terminal_pgrp = pgrp;
sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
}
+ if (r == -1)
+ errno = e;
return r;
}
char *temp, *tt;
intmax_t arg_index;
SHELL_VAR *var;
- int atype;
+ int atype, rflags;
ret = 0;
temp = 0;
+ rflags = 0;
/* Handle multiple digit arguments, as in ${11}. */
if (legal_number (name, &arg_index))
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
? quote_string (temp)
: quote_escapes (temp);
+ else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ rflags |= W_HASQUOTEDNULL;
}
#endif
else if (var = find_variable (name))
{
ret = alloc_word_desc ();
ret->word = temp;
+ ret->flags |= rflags;
}
return ret;
}
static char *dequote_escapes __P((char *));
static char *make_quoted_char __P((int));
static WORD_LIST *quote_list __P((WORD_LIST *));
-/*static*/ char *remove_quoted_escapes __P((char *));
static char *remove_quoted_nulls __P((char *));
static int unquoted_substring __P((char *, char *));
/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
string. */
-/*static*/ char *
+char *
remove_quoted_escapes (string)
char *string;
{
char *temp, *tt;
intmax_t arg_index;
SHELL_VAR *var;
- int atype;
+ int atype, rflags;
ret = 0;
temp = 0;
+ rflags = 0;
/* Handle multiple digit arguments, as in ${11}. */
if (legal_number (name, &arg_index))
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
? quote_string (temp)
: quote_escapes (temp);
+ else if (atype == 1 && temp && *temp == 0 && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ rflags |= W_HASQUOTEDNULL;
}
#endif
else if (var = find_variable (name))
{
ret = alloc_word_desc ();
ret->word = temp;
+ ret->flags |= rflags;
}
return ret;
}
-BUILD_DIR=/usr/local/build/bash/bash-current
+BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR