From aad3dfa27a72b04541419962aa56a22eb621e58c Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 12 Dec 2011 22:07:35 -0500 Subject: [PATCH] commit bash-20101001 snapshot --- CWRU/CWRU.chlog | 33 +++- CWRU/CWRU.chlog~ | 33 +++- bashline.c | 4 +- bashline.c~ | 5 +- builtins/evalfile.c | 3 +- builtins/evalfile.c~ | 351 +++++++++++++++++++++++++++++++++++++++++++ builtins/exec.def | 16 +- builtins/exec.def~ | 14 +- builtins/printf.def | 11 +- builtins/printf.def~ | 2 +- builtins/source.def | 7 + builtins/source.def~ | 196 ++++++++++++++++++++++++ execute_cmd.c | 12 +- execute_cmd.c~ | 14 +- findcmd.c | 9 ++ lib/sh/strtrans.c | 7 +- lib/sh/strtrans.c~ | 2 +- 17 files changed, 690 insertions(+), 29 deletions(-) create mode 100644 builtins/evalfile.c~ create mode 100644 builtins/source.def~ diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 5d003ff49..dbbd5bb88 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9751,7 +9751,7 @@ lib/readline/complete.c lib/readline/bind.c - new bindable variable: completion-display-width, controls the - number of columns used when displaying completionsm with new + number of columns used when displaying completions with new sv_compwidth function to call when value is set or unset lib/readline/doc/{readline.3,rltech.texi} @@ -10415,3 +10415,34 @@ doc/{bash.1,bashref.texi},lib/readline/doc/{readline.3,rluser.texi} configure.in - remove AM_PATH_LISPDIR call since we don't use that bash debugger any more. Suggested by Mike Frysinger + + 10/6 + ---- +findcmd.c + - change executable_file to set errno to EISDIR if the passed name + is a directory + +builtins/exec.def + - change exec_builtin to report appropriate error message if the + file argument is a directory. Noted by Eric Blake + in a message to austin-group + +builtins/source.def + - change source_builtin to make sure the shell exits if the file is + not found when in a non-interactive shell running in posix mode + and source_searches_cwd == 0 (as posix mode makes it by default). + Pointed out in http://thread.gmane.org/gmane.comp.shells.dash/291/focus=392 + by Jilles Tjoelker + +execute_cmd.c + - set executing_command_builtin in execute_builtin if the builtin is + command_builtin. Unwind-protected in execute_function_or_builtin + (like executing_builtin variable). Available for rest of shell + +builtins/{source.def,evalfile.c} + - make sure that non-interactive posix mode shells exit if the file + argument to `.' is not found only if they are not being executed + by the command builtin (executing_command_builtin == 0). This is + how `command' can cancel effects of special builtin exit properties + in the case of `dot file not found' + diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 66240427d..e6490f70d 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -9751,7 +9751,7 @@ lib/readline/complete.c lib/readline/bind.c - new bindable variable: completion-display-width, controls the - number of columns used when displaying completionsm with new + number of columns used when displaying completions with new sv_compwidth function to call when value is set or unset lib/readline/doc/{readline.3,rltech.texi} @@ -10406,4 +10406,35 @@ lib/readline/bind.c - new bindable readline variable, "menu-complete-display-prefix", controls setting of _rl_menu_complete_prefix_first +doc/{bash.1,bashref.texi},lib/readline/doc/{readline.3,rluser.texi} + - added description of menu-complete-display-prefix bindable + readline variable + 9/17 + ---- +configure.in + - remove AM_PATH_LISPDIR call since we don't use that bash debugger + any more. Suggested by Mike Frysinger + + 10/6 + ---- +findcmd.c + - change executable_file to set errno to EISDIR if the passed name + is a directory + +builtins/exec.def + - change exec_builtin to report appropriate error message if the + file argument is a directory. Noted by Eric Blake + in a message to austin-group + +builtins/source.def + - change source_builtin to make sure the shell exits if the file is + not found when in a non-interactive shell running in posix mode + and source_searches_cwd == 0 (as posix mode makes it by default). + Pointed out in http://thread.gmane.org/gmane.comp.shells.dash/291/focus=392 + by Jilles Tjoelker + +execute_cmd.c + - set executing_command_builtin in execute_builtin if the builtin is + command_builtin. Unwind-protected in execute_function_or_builtin + (like executing_builtin variable). Available for rest of shell diff --git a/bashline.c b/bashline.c index 7fee50d29..a0b0d709e 100644 --- a/bashline.c +++ b/bashline.c @@ -1400,12 +1400,12 @@ bash_default_completion (text, start, end, qc, compflags) /* If the word starts in `~', and there is no slash in the word, then try completing this word as a username. */ - if (matches ==0 && *text == '~' && mbschr (text, '/') == 0) + if (matches == 0 && *text == '~' && mbschr (text, '/') == 0) matches = rl_completion_matches (text, rl_username_completion_function); /* Another one. Why not? If the word starts in '@', then look through the world of known hostnames for completion first. */ - if (!matches && perform_hostname_completion && *text == '@') + if (matches == 0 && perform_hostname_completion && *text == '@') matches = rl_completion_matches (text, hostname_completion_function); /* And last, (but not least) if this word is in a command position, then diff --git a/bashline.c~ b/bashline.c~ index 575a0e257..7fee50d29 100644 --- a/bashline.c~ +++ b/bashline.c~ @@ -529,11 +529,8 @@ initialize_readline () enable_hostname_completion (perform_hostname_completion); /* characters that need to be quoted when appearing in filenames. */ -#if 0 - rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{"; /*}*/ -#else rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/ -#endif + rl_filename_quoting_function = bash_quote_filename; rl_filename_dequoting_function = bash_dequote_filename; rl_char_is_quoted_p = char_is_quoted; diff --git a/builtins/evalfile.c b/builtins/evalfile.c index 972d03932..3a48641b5 100644 --- a/builtins/evalfile.c +++ b/builtins/evalfile.c @@ -70,6 +70,7 @@ extern int posixly_correct; extern int indirection_level, subshell_environment; extern int return_catch_flag, return_catch_value; extern int last_command_exit_value; +extern int executing_command_builtin; /* How many `levels' of sourced files we have. */ int sourcelevel = 0; @@ -342,7 +343,7 @@ source_file (filename, sflags) if (sflags) flags |= FEVAL_NOPUSHARGS; /* POSIX shells exit if non-interactive and file error. */ - if (posixly_correct && !interactive_shell) + if (posixly_correct && interactive_shell == 0 && executing_command_builtin == 0) flags |= FEVAL_LONGJMP; rval = _evalfile (filename, flags); diff --git a/builtins/evalfile.c~ b/builtins/evalfile.c~ new file mode 100644 index 000000000..7c6c8bdf9 --- /dev/null +++ b/builtins/evalfile.c~ @@ -0,0 +1,351 @@ +/* evalfile.c - read and evaluate commands from a file or file descriptor */ + +/* Copyright (C) 1996-2009 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 . +*/ + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "../bashtypes.h" +#include "posixstat.h" +#include "filecntl.h" + +#include +#include +#include + +#include "../bashansi.h" +#include "../bashintl.h" + +#include "../shell.h" +#include "../jobs.h" +#include "../builtins.h" +#include "../flags.h" +#include "../input.h" +#include "../execute_cmd.h" +#include "../trap.h" + +#if defined (HISTORY) +# include "../bashhist.h" +#endif + +#include + +#include "common.h" + +#if !defined (errno) +extern int errno; +#endif + +/* Flags for _evalfile() */ +#define FEVAL_ENOENTOK 0x001 +#define FEVAL_BUILTIN 0x002 +#define FEVAL_UNWINDPROT 0x004 +#define FEVAL_NONINT 0x008 +#define FEVAL_LONGJMP 0x010 +#define FEVAL_HISTORY 0x020 +#define FEVAL_CHECKBINARY 0x040 +#define FEVAL_REGFILE 0x080 +#define FEVAL_NOPUSHARGS 0x100 + +extern int posixly_correct; +extern int indirection_level, subshell_environment; +extern int return_catch_flag, return_catch_value; +extern int last_command_exit_value; + +/* How many `levels' of sourced files we have. */ +int sourcelevel = 0; + +static int +_evalfile (filename, flags) + const char *filename; + int flags; +{ + volatile int old_interactive; + procenv_t old_return_catch; + int return_val, fd, result, pflags, i, nnull; + ssize_t nr; /* return value from read(2) */ + char *string; + struct stat finfo; + size_t file_size; + sh_vmsg_func_t *errfunc; +#if defined (ARRAY_VARS) + SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v; + ARRAY *funcname_a, *bash_source_a, *bash_lineno_a; +# if defined (DEBUGGER) + SHELL_VAR *bash_argv_v, *bash_argc_v; + ARRAY *bash_argv_a, *bash_argc_a; +# endif + char *t, tt[2]; +#endif + + USE_VAR(pflags); + +#if defined (ARRAY_VARS) + GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a); + GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a); + GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a); +# if defined (DEBUGGER) + GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a); + GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a); +# endif +#endif + + fd = open (filename, O_RDONLY); + + if (fd < 0 || (fstat (fd, &finfo) == -1)) + { +file_error_and_exit: + if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT) + file_error (filename); + + if (flags & FEVAL_LONGJMP) + { + last_command_exit_value = 1; + jump_to_top_level (EXITPROG); + } + + return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE + : ((errno == ENOENT) ? 0 : -1)); + } + + errfunc = ((flags & FEVAL_BUILTIN) ? builtin_error : internal_error); + + if (S_ISDIR (finfo.st_mode)) + { + (*errfunc) (_("%s: is a directory"), filename); + return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1); + } + else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0) + { + (*errfunc) (_("%s: not a regular file"), filename); + return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1); + } + + file_size = (size_t)finfo.st_size; + /* Check for overflow with large files. */ + if (file_size != finfo.st_size || file_size + 1 < file_size) + { + (*errfunc) (_("%s: file is too large"), filename); + return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1); + } + +#if defined (__CYGWIN__) && defined (O_TEXT) + setmode (fd, O_TEXT); +#endif + + if (S_ISREG (finfo.st_mode) && file_size <= SSIZE_MAX) + { + string = (char *)xmalloc (1 + file_size); + nr = read (fd, string, file_size); + if (nr >= 0) + string[nr] = '\0'; + } + else + nr = zmapfd (fd, &string, 0); + + return_val = errno; + close (fd); + errno = return_val; + + if (nr < 0) /* XXX was != file_size, not < 0 */ + { + free (string); + goto file_error_and_exit; + } + + if (nr == 0) + { + free (string); + return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1); + } + + if ((flags & FEVAL_CHECKBINARY) && + check_binary_file (string, (nr > 80) ? 80 : nr)) + { + free (string); + (*errfunc) (_("%s: cannot execute binary file"), filename); + return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1); + } + + i = strlen (string); + if (i < nr) + { + for (nnull = i = 0; i < nr; i++) + if (string[i] == '\0') + { + memmove (string+i, string+i+1, nr - i); + nr--; + /* Even if the `check binary' flag is not set, we want to avoid + sourcing files with more than 256 null characters -- that + probably indicates a binary file. */ + if ((flags & FEVAL_BUILTIN) && ++nnull > 256) + { + free (string); + (*errfunc) (_("%s: cannot execute binary file"), filename); + return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1); + } + } + } + + if (flags & FEVAL_UNWINDPROT) + { + begin_unwind_frame ("_evalfile"); + + unwind_protect_int (return_catch_flag); + unwind_protect_jmp_buf (return_catch); + if (flags & FEVAL_NONINT) + unwind_protect_int (interactive); + unwind_protect_int (sourcelevel); + } + else + { + COPY_PROCENV (return_catch, old_return_catch); + if (flags & FEVAL_NONINT) + old_interactive = interactive; + } + + if (flags & FEVAL_NONINT) + interactive = 0; + + return_catch_flag++; + sourcelevel++; + +#if defined (ARRAY_VARS) + array_push (bash_source_a, (char *)filename); + t = itos (executing_line_number ()); + array_push (bash_lineno_a, t); + free (t); + array_push (funcname_a, "source"); /* not exactly right */ +# if defined (DEBUGGER) + /* Have to figure out a better way to do this when `source' is supplied + arguments */ + if ((flags & FEVAL_NOPUSHARGS) == 0) + { + array_push (bash_argv_a, (char *)filename); + tt[0] = '1'; tt[1] = '\0'; + array_push (bash_argc_a, tt); + } +# endif +#endif + + /* set the flags to be passed to parse_and_execute */ + pflags = SEVAL_RESETLINE; + pflags |= (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST; + + if (flags & FEVAL_BUILTIN) + result = EXECUTION_SUCCESS; + + return_val = setjmp (return_catch); + + /* If `return' was seen outside of a function, but in the script, then + force parse_and_execute () to clean up. */ + if (return_val) + { + parse_and_execute_cleanup (); + result = return_catch_value; + } + else + result = parse_and_execute (string, filename, pflags); + + if (flags & FEVAL_UNWINDPROT) + run_unwind_frame ("_evalfile"); + else + { + if (flags & FEVAL_NONINT) + interactive = old_interactive; + return_catch_flag--; + sourcelevel--; + COPY_PROCENV (old_return_catch, return_catch); + } + +#if defined (ARRAY_VARS) + /* These two variables cannot be unset, and cannot be affected by the + sourced file. */ + array_pop (bash_source_a); + array_pop (bash_lineno_a); + + /* FUNCNAME can be unset, and so can potentially be changed by the + sourced file. */ + GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a); + if (nfv == funcname_v) + array_pop (funcname_a); +# if defined (DEBUGGER) + if ((flags & FEVAL_NOPUSHARGS) == 0) + { + array_pop (bash_argc_a); + array_pop (bash_argv_a); + } +# endif +#endif + + return ((flags & FEVAL_BUILTIN) ? result : 1); +} + +int +maybe_execute_file (fname, force_noninteractive) + const char *fname; + int force_noninteractive; +{ + char *filename; + int result, flags; + + filename = bash_tilde_expand (fname, 0); + flags = FEVAL_ENOENTOK; + if (force_noninteractive) + flags |= FEVAL_NONINT; + result = _evalfile (filename, flags); + free (filename); + return result; +} + +#if defined (HISTORY) +int +fc_execute_file (filename) + const char *filename; +{ + int flags; + + /* We want these commands to show up in the history list if + remember_on_history is set. */ + flags = FEVAL_ENOENTOK|FEVAL_HISTORY|FEVAL_REGFILE; + return (_evalfile (filename, flags)); +} +#endif /* HISTORY */ + +int +source_file (filename, sflags) + const char *filename; + int sflags; +{ + int flags, rval; + + flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT; + if (sflags) + flags |= FEVAL_NOPUSHARGS; + /* POSIX shells exit if non-interactive and file error. */ + if (posixly_correct && interactive_shell == 0) + flags |= FEVAL_LONGJMP; + rval = _evalfile (filename, flags); + + run_return_trap (); + return rval; +} diff --git a/builtins/exec.def b/builtins/exec.def index 140407e43..abbeda9ed 100644 --- a/builtins/exec.def +++ b/builtins/exec.def @@ -148,8 +148,20 @@ exec_builtin (list) if (command == 0) { - sh_notfound (args[0]); - exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ + if (file_isdir (args[0])) + { +#if defined (EISDIR) + builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR)); +#else + builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno)); +#endif + exit_value = EX_NOEXEC; + } + else + { + sh_notfound (args[0]); + exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ + } goto failed_exec; } diff --git a/builtins/exec.def~ b/builtins/exec.def~ index 9a1185e88..f29e5a336 100644 --- a/builtins/exec.def~ +++ b/builtins/exec.def~ @@ -1,7 +1,7 @@ This file is exec.def, from which is created exec.c. It implements the builtin "exec" in Bash. -Copyright (C) 1987-2009 Free Software Foundation, Inc. +Copyright (C) 1987-2010 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -148,8 +148,16 @@ exec_builtin (list) if (command == 0) { - sh_notfound (args[0]); - exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ + if (file_isdir (args[0])) + { + builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno)); + exit_value = EX_NOEXEC; + } + else + { + sh_notfound (args[0]); + exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ + } goto failed_exec; } diff --git a/builtins/printf.def b/builtins/printf.def index ec2d575ee..5971d9bb2 100644 --- a/builtins/printf.def +++ b/builtins/printf.def @@ -788,6 +788,7 @@ tescape (estart, cp, lenp, sawc) { register char *p; int temp, c, evalue; + unsigned long uvalue; p = estart; if (lenp) @@ -845,19 +846,19 @@ tescape (estart, cp, lenp, sawc) case 'u': case 'U': temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */ - for (evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++) - evalue = (evalue * 16) + HEXVALUE (*p); + for (uvalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++) + uvalue = (uvalue * 16) + HEXVALUE (*p); if (p == estart + 1) { builtin_error (_("missing unicode digit for \\%c"), c); *cp = '\\'; return 0; } - if (evalue <= UCHAR_MAX) - *cp = evalue; + if (uvalue <= UCHAR_MAX) + *cp = uvalue; else { - temp = u32cconv (evalue, cp); + temp = u32cconv (uvalue, cp); cp[temp] = '\0'; if (lenp) *lenp = temp; diff --git a/builtins/printf.def~ b/builtins/printf.def~ index bc70d506f..ec2d575ee 100644 --- a/builtins/printf.def~ +++ b/builtins/printf.def~ @@ -1,7 +1,7 @@ This file is printf.def, from which is created printf.c. It implements the builtin "printf" in Bash. -Copyright (C) 1997-2009 Free Software Foundation, Inc. +Copyright (C) 1997-2010 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. diff --git a/builtins/source.def b/builtins/source.def index 72627db3a..71908b8bf 100644 --- a/builtins/source.def +++ b/builtins/source.def @@ -80,6 +80,8 @@ extern int errno; #endif /* !errno */ extern int posixly_correct; +extern int last_command_exit_value; +extern int executing_command_builtin; static void maybe_pop_dollar_vars __P((void)); @@ -151,6 +153,11 @@ source_builtin (list) if (source_searches_cwd == 0) { builtin_error (_("%s: file not found"), list->word->word); + if (posixly_correct && interactive_shell == 0 && executing_command_builtin == 0) + { + last_command_exit_value = 1; + jump_to_top_level (EXITPROG); + } return (EXECUTION_FAILURE); } else diff --git a/builtins/source.def~ b/builtins/source.def~ new file mode 100644 index 000000000..899ff1139 --- /dev/null +++ b/builtins/source.def~ @@ -0,0 +1,196 @@ +This file is source.def, from which is created source.c. +It implements the builtins "." and "source" in Bash. + +Copyright (C) 1987-2009 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 . + +$PRODUCES source.c + +$BUILTIN source +$FUNCTION source_builtin +$SHORT_DOC source filename [arguments] +Execute commands from a file in the current shell. + +Read and execute commands from FILENAME in the current shell. The +entries in $PATH are used to find the directory containing FILENAME. +If any ARGUMENTS are supplied, they become the positional parameters +when FILENAME is executed. + +Exit Status: +Returns the status of the last command executed in FILENAME; fails if +FILENAME cannot be read. +$END + +$BUILTIN . +$DOCNAME dot +$FUNCTION source_builtin +$SHORT_DOC . filename [arguments] +Execute commands from a file in the current shell. + +Read and execute commands from FILENAME in the current shell. The +entries in $PATH are used to find the directory containing FILENAME. +If any ARGUMENTS are supplied, they become the positional parameters +when FILENAME is executed. + +Exit Status: +Returns the status of the last command executed in FILENAME; fails if +FILENAME cannot be read. +$END + +#include + +#include "../bashtypes.h" +#include "posixstat.h" +#include "filecntl.h" +#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H) +# include +#endif +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "../bashansi.h" +#include "../bashintl.h" + +#include "../shell.h" +#include "../flags.h" +#include "../findcmd.h" +#include "common.h" +#include "bashgetopt.h" +#include "../trap.h" + +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +extern int posixly_correct; +extern int last_command_exit_value; + +static void maybe_pop_dollar_vars __P((void)); + +/* If non-zero, `.' uses $PATH to look up the script to be sourced. */ +int source_uses_path = 1; + +/* If non-zero, `.' looks in the current directory if the filename argument + is not found in the $PATH. */ +int source_searches_cwd = 1; + +/* If this . script is supplied arguments, we save the dollar vars and + replace them with the script arguments for the duration of the script's + execution. If the script does not change the dollar vars, we restore + what we saved. If the dollar vars are changed in the script, and we are + not executing a shell function, we leave the new values alone and free + the saved values. */ +static void +maybe_pop_dollar_vars () +{ + if (variable_context == 0 && (dollar_vars_changed () & ARGS_SETBLTIN)) + dispose_saved_dollar_vars (); + else + pop_dollar_vars (); + if (debugging_mode) + pop_args (); /* restore BASH_ARGC and BASH_ARGV */ + set_dollar_vars_unchanged (); +} + +/* Read and execute commands from the file passed as argument. Guess what. + This cannot be done in a subshell, since things like variable assignments + take place in there. So, I open the file, place it into a large string, + close the file, and then execute the string. */ +int +source_builtin (list) + WORD_LIST *list; +{ + int result; + char *filename, *debug_trap; + + if (no_options (list)) + return (EX_USAGE); + list = loptend; + + if (list == 0) + { + builtin_error (_("filename argument required")); + builtin_usage (); + return (EX_USAGE); + } + +#if defined (RESTRICTED_SHELL) + if (restricted && strchr (list->word->word, '/')) + { + sh_restricted (list->word->word); + return (EXECUTION_FAILURE); + } +#endif + + filename = (char *)NULL; + /* XXX -- should this be absolute_pathname? */ + if (posixly_correct && strchr (list->word->word, '/')) + filename = savestring (list->word->word); + else if (absolute_pathname (list->word->word)) + filename = savestring (list->word->word); + else if (source_uses_path) + filename = find_path_file (list->word->word); + if (filename == 0) + { + if (source_searches_cwd == 0) + { + builtin_error (_("%s: file not found"), list->word->word); + if (posixly_correct && interactive_shell == 0) + { + last_command_exit_value = 1; + jump_to_top_level (EXITPROG); + } + return (EXECUTION_FAILURE); + } + else + filename = savestring (list->word->word); + } + + begin_unwind_frame ("source"); + add_unwind_protect ((Function *)xfree, filename); + + if (list->next) + { + push_dollar_vars (); + add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL); + remember_args (list->next, 1); + if (debugging_mode) + push_args (list->next); /* Update BASH_ARGV and BASH_ARGC */ + } + set_dollar_vars_unchanged (); + + /* Don't inherit the DEBUG trap unless function_trace_mode (overloaded) + is set. XXX - should sourced files inherit the RETURN trap? Functions + don't. */ + debug_trap = TRAP_STRING (DEBUG_TRAP); + if (debug_trap && function_trace_mode == 0) + { + debug_trap = savestring (debug_trap); + add_unwind_protect (xfree, debug_trap); + add_unwind_protect (set_debug_trap, debug_trap); + restore_default_signal (DEBUG_TRAP); + } + + result = source_file (filename, (list && list->next)); + + run_unwind_frame ("source"); + + return (result); +} diff --git a/execute_cmd.c b/execute_cmd.c index af556fa91..2f76d1107 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -256,6 +256,8 @@ SHELL_VAR *this_shell_function; /* If non-zero, matches in case and [[ ... ]] are case-insensitive */ int match_ignore_case = 0; +int executing_command_builtin = 0; + struct stat SB; /* used for debugging */ static int special_builtin_failed; @@ -3889,7 +3891,10 @@ run_builtin: if (builtin || func) { if (builtin) - unwind_protect_int (executing_builtin); /* modified in execute_builtin */ + { + unwind_protect_int (executing_builtin); /* modified in execute_builtin */ + unwind_protect_int (executing_command_builtin); /* ditto */ + } if (already_forked) { /* reset_terminating_signals (); */ /* XXX */ @@ -4076,6 +4081,7 @@ execute_builtin (builtin, words, flags, subshell) } executing_builtin++; + executing_command_builtin |= builtin == command_builtin; result = ((*builtin) (words->next)); /* This shouldn't happen, but in case `return' comes back instead of @@ -4928,7 +4934,11 @@ shell_execve (command, args, env) if (i != ENOEXEC) { if (file_isdir (command)) +#if defined (EISDIR) + internal_error (_("%s: %s"), command, strerror (EISDIR)); +#else internal_error (_("%s: is a directory"), command); +#endif else if (executable_file (command) == 0) { errno = i; diff --git a/execute_cmd.c~ b/execute_cmd.c~ index 131c8301c..c28335f75 100644 --- a/execute_cmd.c~ +++ b/execute_cmd.c~ @@ -256,6 +256,8 @@ SHELL_VAR *this_shell_function; /* If non-zero, matches in case and [[ ... ]] are case-insensitive */ int match_ignore_case = 0; +int executing_command_builtin = 0; + struct stat SB; /* used for debugging */ static int special_builtin_failed; @@ -735,7 +737,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, execute_simple_command (command->value.Simple, pipe_in, pipe_out, asynchronous, fds_to_close); line_number = save_line_number; -itrace("execute_simple_command (%s) returns %d", command->value.Simple->words->word->word, exec_result); + /* The temporary environment should be used for only the simple command immediately following its definition. */ dispose_used_env_vars (); @@ -3889,7 +3891,10 @@ run_builtin: if (builtin || func) { if (builtin) - unwind_protect_int (executing_builtin); /* modified in execute_builtin */ + { + unwind_protect_int (executing_builtin); /* modified in execute_builtin */ + unwind_protect_int (executing_command_builtin); /* ditto */ + } if (already_forked) { /* reset_terminating_signals (); */ /* XXX */ @@ -4076,6 +4081,7 @@ execute_builtin (builtin, words, flags, subshell) } executing_builtin++; + executing_command_builtin = builtin == command_builtin; result = ((*builtin) (words->next)); /* This shouldn't happen, but in case `return' comes back instead of @@ -4928,7 +4934,11 @@ shell_execve (command, args, env) if (i != ENOEXEC) { if (file_isdir (command)) +#if defined (EISDIR) + internal_error (_("%s: %s"), command, strerror (EISDIR)); +#else internal_error (_("%s: is a directory"), command); +#endif else if (executable_file (command) == 0) { errno = i; diff --git a/findcmd.c b/findcmd.c index 557f8b544..330e39544 100644 --- a/findcmd.c +++ b/findcmd.c @@ -32,6 +32,7 @@ #if defined (HAVE_UNISTD_H) # include #endif +#include #include "bashansi.h" @@ -43,6 +44,10 @@ #include "hashcmd.h" #include "findcmd.h" /* matching prototypes and declarations */ +#if !defined (errno) +extern int errno; +#endif + extern int posixly_correct; /* Static functions defined and used in this file. */ @@ -172,6 +177,10 @@ executable_file (file) int s; s = file_status (file); +#if defined EISDIR + if (s & FS_DIRECTORY) + errno = EISDIR; /* let's see if we can improve error messages */ +#endif return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0)); } diff --git a/lib/sh/strtrans.c b/lib/sh/strtrans.c index 3400eb8f0..c742ef874 100644 --- a/lib/sh/strtrans.c +++ b/lib/sh/strtrans.c @@ -49,11 +49,9 @@ ansicstr (string, len, flags, sawc, rlen) char *string; int len, flags, *sawc, *rlen; { - int c, temp, v; + int c, temp; char *ret, *r, *s; -#if defined (HANDLE_MULTIBYTE) - char mbch[25]; /* 25 > MB_LEN_MAX, plus can handle 4-byte UTF-8 and large Unicode characters*/ -#endif + unsigned long v; if (string == 0 || *string == '\0') return ((char *)NULL); @@ -153,7 +151,6 @@ ansicstr (string, len, flags, sawc, rlen) } else { - memset (mbch, '\0', sizeof (mbch)); temp = u32cconv (v, r); r += temp; continue; diff --git a/lib/sh/strtrans.c~ b/lib/sh/strtrans.c~ index 2a981356f..3400eb8f0 100644 --- a/lib/sh/strtrans.c~ +++ b/lib/sh/strtrans.c~ @@ -1,6 +1,6 @@ /* strtrans.c - Translate and untranslate strings with ANSI-C escape sequences. */ -/* Copyright (C) 2000 Free Software Foundation, Inc. +/* Copyright (C) 2000-2010 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. -- 2.39.5