]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20101001 snapshot
authorChet Ramey <chet.ramey@case.edu>
Tue, 13 Dec 2011 03:07:35 +0000 (22:07 -0500)
committerChet Ramey <chet.ramey@case.edu>
Tue, 13 Dec 2011 03:07:35 +0000 (22:07 -0500)
17 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
bashline.c
bashline.c~
builtins/evalfile.c
builtins/evalfile.c~ [new file with mode: 0644]
builtins/exec.def
builtins/exec.def~
builtins/printf.def
builtins/printf.def~
builtins/source.def
builtins/source.def~ [new file with mode: 0644]
execute_cmd.c
execute_cmd.c~
findcmd.c
lib/sh/strtrans.c
lib/sh/strtrans.c~

index 5d003ff499e39a97ed54609942550e93085cf6dc..dbbd5bb884bf09326744eb08a8aaecaabb586ccd 100644 (file)
@@ -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 <vapier@gentoo.org>
+
+                                  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 <eblake@redhat.com>
+         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 <jilles@stack.nl>
+
+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'
+
index 66240427d357f441a167226998ad9625573190b5..e6490f70da4cf3f76bff963759188718339c40d6 100644 (file)
@@ -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 <vapier@gentoo.org>
+
+                                  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 <eblake@redhat.com>
+         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 <jilles@stack.nl>
+
+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
index 7fee50d2979391dc78cef20914fa61dbbcb9e6c3..a0b0d709eba91fa12509b14e371c514bcc8645a4 100644 (file)
@@ -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
index 575a0e2570e3a40a2c661cb74ab61345e5c9352d..7fee50d2979391dc78cef20914fa61dbbcb9e6c3 100644 (file)
@@ -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;
index 972d03932989600fa3f06cd8db57b011d67165fc..3a48641b58b74ded86c3576317b6e3186b9b2592 100644 (file)
@@ -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 (file)
index 0000000..7c6c8bd
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "../bashtypes.h"
+#include "posixstat.h"
+#include "filecntl.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#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 <typemax.h>
+
+#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;
+}
index 140407e439d53bddc70a00741a99ce26299a0003..abbeda9eded97c87f32ca1749df577b6bc35785d 100644 (file)
@@ -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;
     }
 
index 9a1185e88295c86ff300c5dc67964402334865a3..f29e5a3361726e0d0d70bba750373ec022b5411c 100644 (file)
@@ -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;
     }
 
index ec2d575eeb147bbeb819e2403665de90a192747a..5971d9bb2dc6f25d14e614cfef0567cb6c2661c0 100644 (file)
@@ -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;
index bc70d506f6d3f74c7b81241b5a626f33e7dda201..ec2d575eeb147bbeb819e2403665de90a192747a 100644 (file)
@@ -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.
 
index 72627db3a4451f7bb043b641c77c668e6f1f25f4..71908b8bf579b7ad44d61747366cbc021da8ce2d 100644 (file)
@@ -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 (file)
index 0000000..899ff11
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+$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 <config.h>
+
+#include "../bashtypes.h"
+#include "posixstat.h"
+#include "filecntl.h"
+#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
+#  include <sys/file.h>
+#endif
+#include <errno.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#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);
+}
index af556fa9175415255480230b15ccdbfaad27267f..2f76d1107f083a69ee421f4437deef7fe89b07c0 100644 (file)
@@ -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;
index 131c8301c8dce2033a0643536b3f4386d81e4ac4..c28335f75736465ca60880d62c718c98929433aa 100644 (file)
@@ -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;
index 557f8b5445d058916d044663eb2aec7f8f630022..330e39544d5529cbb0bba2c91621a27acf408482 100644 (file)
--- a/findcmd.c
+++ b/findcmd.c
@@ -32,6 +32,7 @@
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
 #endif
+#include <errno.h>
 
 #include "bashansi.h"
 
 #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));
 }
 
index 3400eb8f07aca09eb05a58becdbe59a08385dc1f..c742ef874c0b51d73ab800612f78f89cfa22f5c7 100644 (file)
@@ -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;
index 2a981356fc690fe666bcf635128e9078ea52642c..3400eb8f07aca09eb05a58becdbe59a08385dc1f 100644 (file)
@@ -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.