commit bash-20140912 snapshot

This commit is contained in:
Chet Ramey
2014-10-02 10:21:23 -04:00
parent e198129d21
commit 96f3fb6664
25 changed files with 12096 additions and 822 deletions
+110 -2
View File
@@ -6279,6 +6279,11 @@ builtins/read.def
bashline_reset_event_hook. These changes fix bug reported in
https://bugs.launchpad.net/ubuntu/+source/bash/+bug/1317476
bashline.c
- bash_event_hook: make sure we clean up the readline state by calling
rl_cleanup_after_signal if sigalrm_seen is non-zero. The read builtin
sets this when it times out
5/12
----
doc/{bash.1,bashref.texi}
@@ -6684,7 +6689,110 @@ builtins/common.c
builtins/command.def
- use CASE_HELPOPT() to handle --help after calling internal_getopt()
(command)
builtins/{colon,echo,test}.def
- do not recognize --help (:/true/false/echo/test
)
- do not recognize --help (:/true/false/echo/test)
9/8
---
sig.c
- termsig_sighandler: if readline is active now, set the bashline event
hook. Old code just set it for interactive shells. Part of fix for
bug reported by <mickael9@gmail.com>
bashline.c
- bash_event_hook: call rl_cleanup_after_signal if terminating_signal
is non-zero, since check_signals_and_traps() will cause the shell to
exit if it is and we want to clean up the readline state first. Rest
of fix for bug reported by <mickael9@gmail.com>
9/9
---
jobs.c
- waitchld: when running the wait builtin in posix mode, with a trap set
on SIGCHLD, use queue_sigchld_trap instead of trap_handler (SIGCHLD),
otherwise you will lose SIGCHLDs when children_exited > 1. Fixes bug
reported by <crispusfairbairn@gmail.com>
builtins/read.def
- read_builtin: if we are changing the tty settings, call
initialize_terminating_signals so we have a chance to catch all
terminating signals and potentially clean up the terminal before
exiting
- read_builtin: tty_modified: new variable, set to 1 if we change the
terminal attributes and have to call ttyrestore() to restore them
- if one of the `reads' returns -1/EINTR due to a terminating signal,
and we have modified the terminal, call ttyrestore before calling
CHECK_TERMSIG
- ttyrestore: set tty_modified to 0 when called
9/10
----
builtins/read.def
- termsave: now global to file so other functions can use it
- read_tty_cleanup: if tty_modified is non-zero, call ttycleanup to restore
old terminal settings and turn off tty_modified
sig.c
- termsig_handler: call read_tty_cleanup if currently executing read
builtin; it does the right thing. Final piece of fix for bug reported
by Jan Rome <jan.rome@gmail.com>
9/11
----
general.c
- printable_filename: general function to return a printable representation
of a string (presumed to be a filename)
general.h
- extern declaration for printable_filename
execute_cmd.c
- execute_disk_command: use printable_filename
builtins/{bind,cd,enable,hash,source}.def
- use printable_filename as appropriate when printing error messages.
From a suggestion by Vincent Lefevre <vincent@vinc17.net>
builtins/bind.def
- use CASE_HELPOPT() to handle --help after calling internal_getopt()
(bind)
9/12
----
builtins/common.h
- SEVAL_FUNCDEF: new flag for parse_and_execute; it means that we only
accept a single function definition command, as when we are importing
functions from the environment
- SEVAL_ONECMD: new flag for parse_and_execute; for future use
builtins/evalstring.c
- parse_and_execute: if the SEVAL_FUNCDEF flag is set, disallow anything
but a function definition command
variables.c
- initialize_shell_variables: don't allow functions with invalid names
to be imported from the environment, even though we still allow them
to be defined
- initialize_shell_variables: when importing function definitions from
the environment, call parse_and_execute with the SEVAL_FUNCDEF flag
to force the command to be just a function definition
subst.c
- param_expand: when expanding a $name variable expansion, make sure that
the variable is visible and set before following the nameref chain
- param_expand: when expanding a $name variable expansion and following the
nameref chain, make sure the resulting variable is visible and set
before using it
9/13
----
variables.c
- initialize_shell_variables: when importing function definitions from
environment, use SEVAL_ONECMD flag for parse_and_execute
builtins/evalstring.c
- parse_and_execute: if SEVAL_ONECMD flag set, return immediately after
calling execute_command_internal. Final piece for fix for bug
reported by Stephane Chazelas <stephane.chazelas@gmail.com>
+108
View File
@@ -6279,6 +6279,11 @@ builtins/read.def
bashline_reset_event_hook. These changes fix bug reported in
https://bugs.launchpad.net/ubuntu/+source/bash/+bug/1317476
bashline.c
- bash_event_hook: make sure we clean up the readline state by calling
rl_cleanup_after_signal if sigalrm_seen is non-zero. The read builtin
sets this when it times out
5/12
----
doc/{bash.1,bashref.texi}
@@ -6684,6 +6689,109 @@ builtins/common.c
builtins/command.def
- use CASE_HELPOPT() to handle --help after calling internal_getopt()
(command)
builtins/{colon,echo,test}.def
- do not recognize --help (:/true/false/echo/test)
9/8
---
sig.c
- termsig_sighandler: if readline is active now, set the bashline event
hook. Old code just set it for interactive shells. Part of fix for
bug reported by <mickael9@gmail.com>
bashline.c
- bash_event_hook: call rl_cleanup_after_signal if terminating_signal
is non-zero, since check_signals_and_traps() will cause the shell to
exit if it is and we want to clean up the readline state first. Rest
of fix for bug reported by <mickael9@gmail.com>
9/9
---
jobs.c
- waitchld: when running the wait builtin in posix mode, with a trap set
on SIGCHLD, use queue_sigchld_trap instead of trap_handler (SIGCHLD),
otherwise you will lose SIGCHLDs when children_exited > 1. Fixes bug
reported by <crispusfairbairn@gmail.com>
builtins/read.def
- read_builtin: if we are changing the tty settings, call
initialize_terminating_signals so we have a chance to catch all
terminating signals and potentially clean up the terminal before
exiting
- read_builtin: tty_modified: new variable, set to 1 if we change the
terminal attributes and have to call ttyrestore() to restore them
- if one of the `reads' returns -1/EINTR due to a terminating signal,
and we have modified the terminal, call ttyrestore before calling
CHECK_TERMSIG
- ttyrestore: set tty_modified to 0 when called
9/10
----
builtins/read.def
- termsave: now global to file so other functions can use it
- read_tty_cleanup: if tty_modified is non-zero, call ttycleanup to restore
old terminal settings and turn off tty_modified
sig.c
- termsig_handler: call read_tty_cleanup if currently executing read
builtin; it does the right thing. Final piece of fix for bug reported
by Jan Rome <jan.rome@gmail.com>
9/11
----
general.c
- printable_filename: general function to return a printable representation
of a string (presumed to be a filename)
general.h
- extern declaration for printable_filename
execute_cmd.c
- execute_disk_command: use printable_filename
builtins/{bind,cd,enable,hash,source}.def
- use printable_filename as appropriate when printing error messages.
From a suggestion by Vincent Lefevre <vincent@vinc17.net>
builtins/bind.def
- use CASE_HELPOPT() to handle --help after calling internal_getopt()
(bind)
9/12
----
builtins/common.h
- SEVAL_FUNCDEF: new flag for parse_and_execute; it means that we only
accept a single function definition command, as when we are importing
functions from the environment
- SEVAL_ONECMD: new flag for parse_and_execute; for future use
builtins/evalstring.c
- parse_and_execute: if the SEVAL_FUNCDEF flag is set, disallow anything
but a function definition command
variables.c
- initialize_shell_variables: don't allow functions with invalid names
to be imported from the environment, even though we still allow them
to be defined
- initialize_shell_variables: when importing function definitions from
the environment, call parse_and_execute with the SEVAL_FUNCDEF flag
to force the command to be just a function definition
subst.c
- param_expand: when expanding a $name variable expansion, make sure that
the variable is visible and set before following the nameref chain
- param_expand: when expanding a $name variable expansion and following the
nameref chain, make sure the resulting variable is visible and set
before using it
9/13
----
variables.c
- initialize_shell_variables: when importing function definitions from
environment, use SEVAL_ONECMD flag for parse_and_execute
builtins/evalstring.c
- parse_and_execute: if SEVAL_ONECMD flag set, return immediately after
calling execute_command_internal
+1 -1
View File
@@ -4263,7 +4263,7 @@ bash_event_hook ()
check_signals will call QUIT, which will eventually longjmp to top_level,
calling run_interrupt_trap along the way. The check for sigalrm_seen is
to clean up the read builtin's state. */
if (interrupt_state || sigalrm_seen)
if (terminating_signal || interrupt_state || sigalrm_seen)
rl_cleanup_after_signal ();
bashline_reset_event_hook ();
check_signals_and_traps (); /* XXX */
+6 -2
View File
@@ -115,7 +115,7 @@ bind_builtin (list)
int return_code;
Keymap kmap, saved_keymap;
int flags, opt;
char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq, *cmd_seq;
char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq, *cmd_seq, *t;
if (no_line_editing)
{
@@ -193,6 +193,7 @@ bind_builtin (list)
case 'X':
flags |= XXFLAG;
break;
CASE_HELPOPT;
default:
builtin_usage ();
BIND_RETURN (EX_USAGE);
@@ -248,7 +249,10 @@ bind_builtin (list)
{
if (rl_read_init_file (initfile) != 0)
{
builtin_error (_("%s: cannot read: %s"), initfile, strerror (errno));
t = printable_filename (initfile, 0);
builtin_error (_("%s: cannot read: %s"), t, strerror (errno));
if (t != initfile)
free (t);
BIND_RETURN (EXECUTION_FAILURE);
}
}
+4 -1
View File
@@ -436,7 +436,10 @@ cd_builtin (list)
FREE (temp);
}
builtin_error ("%s: %s", dirname, strerror (errno));
temp = printable_filename (dirname, 0);
builtin_error ("%s: %s", temp, strerror (errno));
if (temp != dirname)
free (temp);
return (EXECUTION_FAILURE);
}
+1 -1
View File
@@ -90,7 +90,7 @@ command_builtin (list)
case 'v':
verbose = CDESC_REUSABLE; /* ditto */
break;
CASE_HELPOPT();
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+6 -1
View File
@@ -35,7 +35,7 @@ do { \
} \
} while (0)
#define CASE_HELPOPT() \
#define CASE_HELPOPT \
case GETOPT_HELP: \
builtin_help (); \
return (EX_USAGE)
@@ -48,6 +48,8 @@ do { \
#define SEVAL_RESETLINE 0x010
#define SEVAL_PARSEONLY 0x020
#define SEVAL_NOLONGJMP 0x040
#define SEVAL_FUNCDEF 0x080 /* only allow function definitions */
#define SEVAL_ONECMD 0x100 /* only allow a single command */
/* Flags for describe_command, shared between type.def and command.def */
#define CDESC_ALL 0x001 /* type -a */
@@ -138,6 +140,9 @@ extern void getopts_reset __P((int));
/* Functions from help.def */
extern void builtin_help __P((void));
/* Functions from read.def */
extern void read_tty_cleanup __P((void));
/* Functions from set.def */
extern int minus_o_option_value __P((char *));
extern void list_minus_o_opts __P((int, int));
+8 -2
View File
@@ -309,7 +309,10 @@ dyn_load_builtin (list, flags, filename)
if (handle == 0)
{
builtin_error (_("cannot open shared object %s: %s"), filename, dlerror ());
name = printable_filename (filename, 0);
builtin_error (_("cannot open shared object %s: %s"), name, dlerror ());
if (name != filename)
free (name);
return (EXECUTION_FAILURE);
}
@@ -332,8 +335,11 @@ dyn_load_builtin (list, flags, filename)
b = (struct builtin *)dlsym (handle, struct_name);
if (b == 0)
{
name = printable_filename (filename, 0);
builtin_error (_("cannot find %s in shared object %s: %s"),
struct_name, filename, dlerror ());
struct_name, name, dlerror ());
if (name != filename)
free (name);
free (struct_name);
continue;
}
+11
View File
@@ -312,6 +312,14 @@ parse_and_execute (string, from_file, flags)
{
struct fd_bitmap *bitmap;
if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
{
internal_warning ("%s: ignoring function definition attempt", from_file);
should_jump_to_top_level = 0;
last_result = last_command_exit_value = EX_BADUSAGE;
break;
}
bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
begin_unwind_frame ("pe_dispose");
add_unwind_protect (dispose_fd_bitmap, bitmap);
@@ -372,6 +380,9 @@ parse_and_execute (string, from_file, flags)
dispose_command (command);
dispose_fd_bitmap (bitmap);
discard_unwind_frame ("pe_dispose");
if (flags & SEVAL_ONECMD)
break;
}
}
else
+630
View File
@@ -0,0 +1,630 @@
/* evalstring.c - evaluate a string as one or more shell commands. */
/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include "filecntl.h"
#include "../bashansi.h"
#include "../shell.h"
#include "../jobs.h"
#include "../builtins.h"
#include "../flags.h"
#include "../input.h"
#include "../execute_cmd.h"
#include "../redir.h"
#include "../trap.h"
#include "../bashintl.h"
#include <y.tab.h>
#if defined (HISTORY)
# include "../bashhist.h"
#endif
#include "common.h"
#include "builtext.h"
#if !defined (errno)
extern int errno;
#endif
#define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL)
extern int indirection_level, subshell_environment;
extern int line_number, line_number_for_err_trap;
extern int current_token, shell_eof_token;
extern int last_command_exit_value;
extern int running_trap;
extern int loop_level;
extern int executing_list;
extern int comsub_ignore_return;
extern int posixly_correct;
extern int return_catch_flag, return_catch_value;
extern sh_builtin_func_t *this_shell_builtin;
extern char *the_printed_command_except_trap;
int parse_and_execute_level = 0;
static int cat_file __P((REDIRECT *));
#define PE_TAG "parse_and_execute top"
#define PS_TAG "parse_string top"
#if defined (HISTORY)
static void
set_history_remembering ()
{
remember_on_history = enable_history_list;
}
#endif
static void
restore_lastcom (x)
char *x;
{
FREE (the_printed_command_except_trap);
the_printed_command_except_trap = x;
}
/* How to force parse_and_execute () to clean up after itself. */
void
parse_and_execute_cleanup ()
{
if (running_trap)
{
run_trap_cleanup (running_trap - 1);
unfreeze_jobs_list ();
}
if (have_unwind_protects ())
run_unwind_frame (PE_TAG);
else
parse_and_execute_level = 0; /* XXX */
}
static void
parse_prologue (string, flags, tag)
char *string;
int flags;
char *tag;
{
char *orig_string, *lastcom;
int x;
orig_string = string;
/* Unwind protect this invocation of parse_and_execute (). */
begin_unwind_frame (tag);
unwind_protect_int (parse_and_execute_level);
unwind_protect_jmp_buf (top_level);
unwind_protect_int (indirection_level);
unwind_protect_int (line_number);
unwind_protect_int (line_number_for_err_trap);
unwind_protect_int (loop_level);
unwind_protect_int (executing_list);
unwind_protect_int (comsub_ignore_return);
if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
unwind_protect_int (interactive);
#if defined (HISTORY)
if (parse_and_execute_level == 0)
add_unwind_protect (set_history_remembering, (char *)NULL);
else
unwind_protect_int (remember_on_history); /* can be used in scripts */
# if defined (BANG_HISTORY)
if (interactive_shell)
unwind_protect_int (history_expansion_inhibited);
# endif /* BANG_HISTORY */
#endif /* HISTORY */
if (interactive_shell)
{
x = get_current_prompt_level ();
add_unwind_protect (set_current_prompt_level, x);
}
if (the_printed_command_except_trap)
{
lastcom = savestring (the_printed_command_except_trap);
add_unwind_protect (restore_lastcom, lastcom);
}
add_unwind_protect (pop_stream, (char *)NULL);
if (parser_expanding_alias ())
add_unwind_protect (parser_restore_alias, (char *)NULL);
if (orig_string && ((flags & SEVAL_NOFREE) == 0))
add_unwind_protect (xfree, orig_string);
end_unwind_frame ();
if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
interactive = (flags & SEVAL_NONINT) ? 0 : 1;
#if defined (HISTORY)
if (flags & SEVAL_NOHIST)
bash_history_disable ();
#endif /* HISTORY */
}
/* Parse and execute the commands in STRING. Returns whatever
execute_command () returns. This frees STRING. FLAGS is a
flags word; look in common.h for the possible values. Actions
are:
(flags & SEVAL_NONINT) -> interactive = 0;
(flags & SEVAL_INTERACT) -> interactive = 1;
(flags & SEVAL_NOHIST) -> call bash_history_disable ()
(flags & SEVAL_NOFREE) -> don't free STRING when finished
(flags & SEVAL_RESETLINE) -> reset line_number to 1
*/
int
parse_and_execute (string, from_file, flags)
char *string;
const char *from_file;
int flags;
{
int code, lreset;
volatile int should_jump_to_top_level, last_result;
COMMAND *volatile command;
volatile sigset_t pe_sigmask;
parse_prologue (string, flags, PE_TAG);
parse_and_execute_level++;
lreset = flags & SEVAL_RESETLINE;
#if defined (HAVE_POSIX_SIGNALS)
/* If we longjmp and are going to go on, use this to restore signal mask */
sigemptyset (&pe_sigmask);
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &pe_sigmask);
#endif
/* Reset the line number if the caller wants us to. If we don't reset the
line number, we have to subtract one, because we will add one just
before executing the next command (resetting the line number sets it to
0; the first line number is 1). */
push_stream (lreset);
if (parser_expanding_alias ())
/* push current shell_input_line */
parser_save_alias ();
if (lreset == 0)
line_number--;
indirection_level++;
code = should_jump_to_top_level = 0;
last_result = EXECUTION_SUCCESS;
/* We need to reset enough of the token state so we can start fresh. */
if (current_token == yacc_EOF)
current_token = '\n'; /* reset_parser() ? */
with_input_from_string (string, from_file);
while (*(bash_input.location.string))
{
command = (COMMAND *)NULL;
if (interrupt_state)
{
last_result = EXECUTION_FAILURE;
break;
}
/* Provide a location for functions which `longjmp (top_level)' to
jump to. This prevents errors in substitution from restarting
the reader loop directly, for example. */
code = setjmp_nosigs (top_level);
if (code)
{
should_jump_to_top_level = 0;
switch (code)
{
case ERREXIT:
/* variable_context -> 0 is what eval.c:reader_loop() does in
these circumstances. Don't bother with cleanup here because
we don't want to run the function execution cleanup stuff
that will cause pop_context and other functions to run.
XXX - change that if we want the function context to be
unwound. */
if (exit_immediately_on_error && variable_context)
{
discard_unwind_frame ("pe_dispose");
variable_context = 0; /* not in a function */
}
should_jump_to_top_level = 1;
goto out;
case FORCE_EOF:
case EXITPROG:
if (command)
run_unwind_frame ("pe_dispose");
/* Remember to call longjmp (top_level) after the old
value for it is restored. */
should_jump_to_top_level = 1;
goto out;
case DISCARD:
if (command)
run_unwind_frame ("pe_dispose");
last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */
if (subshell_environment)
{
should_jump_to_top_level = 1;
goto out;
}
else
{
#if 0
dispose_command (command); /* pe_dispose does this */
#endif
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &pe_sigmask, (sigset_t *)NULL);
#endif
continue;
}
default:
command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0);
break;
}
}
if (parse_command () == 0)
{
if ((flags & SEVAL_PARSEONLY) || (interactive_shell == 0 && read_but_dont_execute))
{
last_result = EXECUTION_SUCCESS;
dispose_command (global_command);
global_command = (COMMAND *)NULL;
}
else if (command = global_command)
{
struct fd_bitmap *bitmap;
if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
{
internal_warning ("ignoring function definition attempt `%s'", string);
should_jump_to_top_level = 0;
last_result = last_command_exit_value = EX_BADUSAGE;
break;
}
bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
begin_unwind_frame ("pe_dispose");
add_unwind_protect (dispose_fd_bitmap, bitmap);
add_unwind_protect (dispose_command, command); /* XXX */
global_command = (COMMAND *)NULL;
if ((subshell_environment & SUBSHELL_COMSUB) && comsub_ignore_return)
command->flags |= CMD_IGNORE_RETURN;
#if defined (ONESHOT)
/*
* IF
* we were invoked as `bash -c' (startup_state == 2) AND
* parse_and_execute has not been called recursively AND
* we're not running a trap AND
* we have parsed the full command (string == '\0') AND
* we're not going to run the exit trap AND
* we have a simple command without redirections AND
* the command is not being timed AND
* the command's return status is not being inverted
* THEN
* tell the execution code that we don't need to fork
*/
if (startup_state == 2 && parse_and_execute_level == 1 &&
running_trap == 0 &&
*bash_input.location.string == '\0' &&
command->type == cm_simple &&
signal_is_trapped (EXIT_TRAP) == 0 &&
command->redirects == 0 && command->value.Simple->redirects == 0 &&
((command->flags & CMD_TIME_PIPELINE) == 0) &&
((command->flags & CMD_INVERT_RETURN) == 0))
{
command->flags |= CMD_NO_FORK;
command->value.Simple->flags |= CMD_NO_FORK;
}
#endif /* ONESHOT */
/* See if this is a candidate for $( <file ). */
if (startup_state == 2 &&
(subshell_environment & SUBSHELL_COMSUB) &&
*bash_input.location.string == '\0' &&
command->type == cm_simple && !command->redirects &&
(command->flags & CMD_TIME_PIPELINE) == 0 &&
command->value.Simple->words == 0 &&
command->value.Simple->redirects &&
command->value.Simple->redirects->next == 0 &&
command->value.Simple->redirects->instruction == r_input_direction &&
command->value.Simple->redirects->redirector.dest == 0)
{
int r;
r = cat_file (command->value.Simple->redirects);
last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
}
else
last_result = execute_command_internal
(command, 0, NO_PIPE, NO_PIPE, bitmap);
dispose_command (command);
dispose_fd_bitmap (bitmap);
discard_unwind_frame ("pe_dispose");
if (flags & SEVAL_ONECMD)
break;
}
}
else
{
last_result = EXECUTION_FAILURE;
if (interactive_shell == 0 && this_shell_builtin &&
(this_shell_builtin == source_builtin || this_shell_builtin == eval_builtin) &&
last_command_exit_value == EX_BADSYNTAX && posixly_correct)
{
should_jump_to_top_level = 1;
code = ERREXIT;
last_command_exit_value = EX_BADUSAGE;
}
/* Since we are shell compatible, syntax errors in a script
abort the execution of the script. Right? */
break;
}
}
out:
run_unwind_frame (PE_TAG);
if (interrupt_state && parse_and_execute_level == 0)
{
/* An interrupt during non-interactive execution in an
interactive shell (e.g. via $PROMPT_COMMAND) should
not cause the shell to exit. */
interactive = interactive_shell;
throw_to_top_level ();
}
if (should_jump_to_top_level)
jump_to_top_level (code);
return (last_result);
}
/* Parse a command contained in STRING according to FLAGS and return the
number of characters consumed from the string. If non-NULL, set *ENDP
to the position in the string where the parse ended. Used to validate
command substitutions during parsing to obey Posix rules about finding
the end of the command and balancing parens. */
int
parse_string (string, from_file, flags, endp)
char *string;
const char *from_file;
int flags;
char **endp;
{
int code, nc;
volatile int should_jump_to_top_level;
COMMAND *volatile command, *oglobal;
char *ostring;
volatile sigset_t ps_sigmask;
parse_prologue (string, flags, PS_TAG);
#if defined (HAVE_POSIX_SIGNALS)
/* If we longjmp and are going to go on, use this to restore signal mask */
sigemptyset (&ps_sigmask);
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &ps_sigmask);
#endif
/* itrace("parse_string: `%s'", string); */
/* Reset the line number if the caller wants us to. If we don't reset the
line number, we have to subtract one, because we will add one just
before executing the next command (resetting the line number sets it to
0; the first line number is 1). */
push_stream (0);
if (parser_expanding_alias ())
/* push current shell_input_line */
parser_save_alias ();
code = should_jump_to_top_level = 0;
oglobal = global_command;
ostring = string;
with_input_from_string (string, from_file);
while (*(bash_input.location.string))
{
command = (COMMAND *)NULL;
#if 0
if (interrupt_state)
break;
#endif
/* Provide a location for functions which `longjmp (top_level)' to
jump to. */
code = setjmp_nosigs (top_level);
if (code)
{
#if defined (DEBUG)
itrace("parse_string: longjmp executed: code = %d", code);
#endif
should_jump_to_top_level = 0;
switch (code)
{
case FORCE_EOF:
case ERREXIT:
case EXITPROG:
case DISCARD: /* XXX */
if (command)
dispose_command (command);
/* Remember to call longjmp (top_level) after the old
value for it is restored. */
should_jump_to_top_level = 1;
goto out;
default:
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &ps_sigmask, (sigset_t *)NULL);
#endif
command_error ("parse_string", CMDERR_BADJUMP, code, 0);
break;
}
}
if (parse_command () == 0)
{
dispose_command (global_command);
global_command = (COMMAND *)NULL;
}
else
{
if ((flags & SEVAL_NOLONGJMP) == 0)
{
should_jump_to_top_level = 1;
code = DISCARD;
}
else
reset_parser (); /* XXX - sets token_to_read */
break;
}
if (current_token == yacc_EOF || current_token == shell_eof_token)
break;
}
out:
global_command = oglobal;
nc = bash_input.location.string - ostring;
if (endp)
*endp = bash_input.location.string;
run_unwind_frame (PS_TAG);
if (should_jump_to_top_level)
jump_to_top_level (code);
return (nc);
}
/* Handle a $( < file ) command substitution. This expands the filename,
returning errors as appropriate, then just cats the file to the standard
output. */
static int
cat_file (r)
REDIRECT *r;
{
char *fn;
int fd, rval;
if (r->instruction != r_input_direction)
return -1;
/* Get the filename. */
if (posixly_correct && !interactive_shell)
disallow_filename_globbing++;
fn = redirection_expand (r->redirectee.filename);
if (posixly_correct && !interactive_shell)
disallow_filename_globbing--;
if (fn == 0)
{
redirection_error (r, AMBIGUOUS_REDIRECT);
return -1;
}
fd = open(fn, O_RDONLY);
if (fd < 0)
{
file_error (fn);
free (fn);
return -1;
}
rval = zcatfd (fd, 1, fn);
free (fn);
close (fd);
return (rval);
}
int
evalstring (string, from_file, flags)
char *string;
const char *from_file;
int flags;
{
volatile int r, rflag, rcatch;
rcatch = 0;
rflag = return_catch_flag;
/* If we are in a place where `return' is valid, we have to catch
`eval "... return"' and make sure parse_and_execute cleans up. Then
we can trampoline to the previous saved return_catch location. */
if (rflag)
{
begin_unwind_frame ("evalstring");
unwind_protect_int (return_catch_flag);
unwind_protect_jmp_buf (return_catch);
return_catch_flag++; /* increment so we have a counter */
rcatch = setjmp_nosigs (return_catch);
}
if (rcatch)
{
parse_and_execute_cleanup ();
r = return_catch_value;
}
else
/* Note that parse_and_execute () frees the string it is passed. */
r = parse_and_execute (string, from_file, flags);
if (rflag)
{
run_unwind_frame ("evalstring");
if (rcatch && return_catch_flag)
{
return_catch_value = r;
longjmp (return_catch, 1);
}
}
return (r);
}
+2 -2
View File
@@ -232,8 +232,8 @@ print_portable_hash_info (item)
{
char *fp, *fn;
fp = sh_contains_shell_metas (pathdata(item)->path) ? sh_single_quote (pathdata(item)->path) : pathdata(item)->path;
fn = sh_contains_shell_metas (item->key) ? sh_single_quote (item->key) : item->key;
fp = printable_filename (pathdata(item)->path, 1);
fn = printable_filename (item->key, 1);
printf ("builtin hash -p %s %s\n", fp, fn);
if (fp != pathdata(item)->path)
free (fp);
+20 -3
View File
@@ -140,10 +140,12 @@ static void reset_alarm __P((void));
procenv_t alrmbuf;
int sigalrm_seen;
static int reading;
static int reading, tty_modified;
static SigHandler *old_alrm;
static unsigned char delim;
static struct ttsave termsave;
/* In all cases, SIGALRM just sets a flag that we check periodically. This
avoids problems with the semi-tricky stuff we do with the xfree of
input_string at the top of the unwind-protect list (see below). */
@@ -188,7 +190,6 @@ read_builtin (list)
struct stat tsb;
SHELL_VAR *var;
TTYSTRUCT ttattrs, ttset;
struct ttsave termsave;
#if defined (ARRAY_VARS)
WORD_LIST *alist;
#endif
@@ -221,7 +222,7 @@ read_builtin (list)
USE_VAR(ps2);
USE_VAR(lastsig);
sigalrm_seen = reading = 0;
sigalrm_seen = reading = tty_modified = 0;
i = 0; /* Index into the string that we are reading. */
raw = edit = 0; /* Not reading raw input by default. */
@@ -482,7 +483,10 @@ read_builtin (list)
i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset);
if (i < 0)
sh_ttyerror (1);
tty_modified = 1;
add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
if (interactive_shell == 0)
initialize_terminating_signals ();
}
}
else if (silent) /* turn off echo but leave term in canonical mode */
@@ -497,7 +501,10 @@ read_builtin (list)
if (i < 0)
sh_ttyerror (1);
tty_modified = 1;
add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
if (interactive_shell == 0)
initialize_terminating_signals ();
}
/* This *must* be the top unwind-protect on the stack, so the manipulation
@@ -588,6 +595,8 @@ read_builtin (list)
}
else
lastsig = 0;
if (terminating_signal && tty_modified)
ttyrestore (&termsave); /* fix terminal before exiting */
CHECK_TERMSIG;
eof = 1;
break;
@@ -978,6 +987,14 @@ ttyrestore (ttp)
struct ttsave *ttp;
{
ttsetattr (ttp->fd, ttp->attrs);
tty_modified = 0;
}
void
read_tty_cleanup ()
{
if (tty_modified)
ttyrestore (&termsave);
}
#if defined (READLINE)
+5 -2
View File
@@ -119,7 +119,7 @@ source_builtin (list)
WORD_LIST *list;
{
int result;
char *filename, *debug_trap;
char *filename, *debug_trap, *x;
if (no_options (list))
return (EX_USAGE);
@@ -152,7 +152,10 @@ source_builtin (list)
{
if (source_searches_cwd == 0)
{
builtin_error (_("%s: file not found"), list->word->word);
x = printable_filename (list->word->word, 0);
builtin_error (_("%s: file not found"), x);
if (x != list->word->word)
free (x);
if (posixly_correct && interactive_shell == 0 && executing_command_builtin == 0)
{
last_command_exit_value = 1;
+2
View File
@@ -73,6 +73,7 @@ $END
#include "bashgetopt.h"
extern int wait_signal_received;
extern int last_command_exit_signal;
procenv_t wait_intr_buf;
@@ -133,6 +134,7 @@ wait_builtin (list)
code = setjmp (wait_intr_buf);
if (code)
{
last_command_exit_signal = wait_signal_received;
status = 128 + wait_signal_received;
WAIT_RETURN (status);
}
+780 -772
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -864,10 +864,10 @@ as for pathname expansion (see
.B Pathname Expansion
below).
The \fIword\fP is expanded using tilde
expansion, parameter and variable expansion, arithmetic substitution,
expansion, parameter and variable expansion, arithmetic expansion,
command substitution, process substitution and quote removal.
Each \fIpattern\fP examined is expanded using tilde
expansion, parameter and variable expansion, arithmetic substitution,
expansion, parameter and variable expansion, arithmetic expansion,
command substitution, and process substitution.
If the shell option
.B nocasematch
@@ -1259,7 +1259,7 @@ A variable can be assigned the \fInameref\fP attribute using the
to create a \fInameref\fP, or a reference to another variable.
This allows variables to be manipulated indirectly.
Whenever the nameref variable is referenced, assigned to, unset, or has
its attributes modified (other than the \fInameref\P attribute itself), the
its attributes modified (other than the \fInameref\fP attribute itself), the
operation is actually performed on the variable specified by the nameref
variable's value.
A nameref is commonly used within shell functions to refer to a variable
+10353
View File
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -5058,8 +5058,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
if (hookf == 0)
{
/* Make sure filenames are displayed using printable characters */
if (ansic_shouldquote (pathname))
pathname = ansic_quote (pathname, 0, NULL);
pathname = printable_filename (pathname, 0);
internal_error (_("%s: command not found"), pathname);
exit (EX_NOTFOUND); /* Posix.2 says the exit status is 127 */
}
+21
View File
@@ -777,6 +777,27 @@ trim_pathname (name, maxlen)
return name;
}
/* Return a printable representation of FN without special characters. The
caller is responsible for freeing memory if this returns something other
than its argument. If FLAGS is non-zero, we are printing for portable
re-input and should single-quote filenames appropriately. */
char *
printable_filename (fn, flags)
char *fn;
int flags;
{
char *newf;
if (ansic_shouldquote (fn))
newf = ansic_quote (fn, 0, NULL);
else if (flags && sh_contains_shell_metas (fn))
newf = sh_single_quote (fn);
else
newf = fn;
return newf;
}
/* Given a string containing units of information separated by colons,
return the next one pointed to by (P_INDEX), or NULL if there are no more.
Advance (P_INDEX) to the character after the colon. */
+1
View File
@@ -313,6 +313,7 @@ extern char *base_pathname __P((char *));
extern char *full_pathname __P((char *));
extern char *polite_directory_format __P((char *));
extern char *trim_pathname __P((char *, int));
extern char *printable_filename __P((char *, int));
extern char *extract_colon_unit __P((char *, int *));
+4 -2
View File
@@ -3256,7 +3256,7 @@ if (wpid != -1 && block)
}
#if 0
itrace("waitchld: waitpid returns %d block = %d", pid, block);
itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, block, children_exited);
#endif
/* If waitpid returns 0, there are running children. If it returns -1,
the only other error POSIX says it can return is EINTR. */
@@ -3345,7 +3345,9 @@ itrace("waitchld: waitpid returns %d block = %d", pid, block);
if (posixly_correct && this_shell_builtin && this_shell_builtin == wait_builtin)
{
interrupt_immediately = 0;
trap_handler (SIGCHLD); /* set pending_traps[SIGCHLD] */
/* This was trap_handler (SIGCHLD) but that can lose traps if
children_exited > 1 */
queue_sigchld_trap (children_exited);
wait_signal_received = SIGCHLD;
/* If we're in a signal handler, let CHECK_WAIT_INTR pick it up;
run_pending_traps will call run_sigchld_trap later */
+7 -2
View File
@@ -532,8 +532,10 @@ termsig_sighandler (sig)
#if defined (READLINE)
/* Set the event hook so readline will call it after the signal handlers
finish executing, so if this interrupted character input we can get
quick response. */
if (interactive_shell && interactive && no_line_editing == 0)
quick response. If readline is active or has modified the terminal we
need to set this no matter what the signal is, though the check for
RL_STATE_TERMPREPPED is possibly redundant. */
if (RL_ISSTATE (RL_STATE_SIGHANDLER) || RL_ISSTATE (RL_STATE_TERMPREPPED))
bashline_set_event_hook ();
#endif
@@ -567,6 +569,9 @@ termsig_handler (sig)
maybe_save_shell_history ();
#endif /* HISTORY */
if (this_shell_builtin == read_builtin)
read_tty_cleanup ();
#if defined (JOB_CONTROL)
if (sig == SIGHUP && (interactive || (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB))))
hangup_all_jobs ();
+3 -1
View File
@@ -8117,7 +8117,9 @@ comsub:
goto return0;
}
else if (var = find_variable_last_nameref (temp1))
else if (var && (invisible_p (var) || var_isset (var) == 0))
temp = (char *)NULL;
else if ((var = find_variable_last_nameref (temp1)) && var_isset (var) && invisible_p (var) == 0)
{
temp = nameref_cell (var);
#if defined (ARRAY_VARS)
+5 -11
View File
@@ -363,13 +363,11 @@ initialize_shell_variables (env, privmode)
temp_string[char_index] = ' ';
strcpy (temp_string + char_index + 1, string);
if (posixly_correct == 0 || legal_identifier (name))
parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
/* Ancient backwards compatibility. Old versions of bash exported
functions like name()=() {...} */
if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
name[char_index - 2] = '\0';
/* Don't import function names that are invalid identifiers from the
environment, though we still allow them to be defined as shell
variables. */
if (legal_identifier (name))
parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
if (temp_var = find_function (name))
{
@@ -386,10 +384,6 @@ initialize_shell_variables (env, privmode)
last_command_exit_value = 1;
report_error (_("error importing function definition for `%s'"), name);
}
/* ( */
if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
name[char_index - 2] = '('; /* ) */
}
#if defined (ARRAY_VARS)
# if ARRAY_EXPORT
+4 -12
View File
@@ -363,13 +363,10 @@ initialize_shell_variables (env, privmode)
temp_string[char_index] = ' ';
strcpy (temp_string + char_index + 1, string);
if (posixly_correct == 0 || legal_identifier (name))
parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
/* Ancient backwards compatibility. Old versions of bash exported
functions like name()=() {...} */
if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
name[char_index - 2] = '\0';
/* Don't import function names that are invalid identifiers from the
environment, though we still allow them to be defined. */
if (legal_identifier (name))
parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
if (temp_var = find_function (name))
{
@@ -386,10 +383,6 @@ initialize_shell_variables (env, privmode)
last_command_exit_value = 1;
report_error (_("error importing function definition for `%s'"), name);
}
/* ( */
if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
name[char_index - 2] = '('; /* ) */
}
#if defined (ARRAY_VARS)
# if ARRAY_EXPORT
@@ -2687,7 +2680,6 @@ bind_variable (name, value, flags)
SHELL_VAR *v, *nv;
VAR_CONTEXT *vc, *nvc;
int level;
char *newname;
if (shell_variables == 0)
create_variable_tables ();