Blame SOURCES/bash-requires.patch

bb9a7e
diff --git a/builtins.h b/builtins.h
bb9a7e
index dac95fd..5b7e811 100644
bb9a7e
--- a/builtins.h
bb9a7e
+++ b/builtins.h
bb9a7e
@@ -45,6 +45,7 @@
bb9a7e
 #define ASSIGNMENT_BUILTIN 0x10	/* This builtin takes assignment statements. */
bb9a7e
 #define POSIX_BUILTIN	0x20	/* This builtins is special in the Posix command search order. */
bb9a7e
 #define LOCALVAR_BUILTIN   0x40	/* This builtin creates local variables */
bb9a7e
+#define REQUIRES_BUILTIN 0x80  /* This builtin requires other files. */
bb9a7e
 
bb9a7e
 #define BASE_INDENT	4
bb9a7e
 
bb9a7e
diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c
bb9a7e
index e243021..0a7a0e5 100644
bb9a7e
--- a/builtins/mkbuiltins.c
bb9a7e
+++ b/builtins/mkbuiltins.c
bb9a7e
@@ -69,10 +69,15 @@ extern char *strcpy ();
bb9a7e
 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
bb9a7e
 
bb9a7e
 /* Flag values that builtins can have. */
bb9a7e
+/*  These flags are for the C code generator,
bb9a7e
+    the C which is produced (./builtin.c)
bb9a7e
+    includes the flags definitions found
bb9a7e
+    in ../builtins.h */
bb9a7e
 #define BUILTIN_FLAG_SPECIAL	0x01
bb9a7e
 #define BUILTIN_FLAG_ASSIGNMENT 0x02
bb9a7e
 #define BUILTIN_FLAG_LOCALVAR	0x04
bb9a7e
 #define BUILTIN_FLAG_POSIX_BUILTIN 0x08
bb9a7e
+#define BUILTIN_FLAG_REQUIRES  0x10
bb9a7e
 
bb9a7e
 #define BASE_INDENT	4
bb9a7e
 
bb9a7e
@@ -173,11 +178,19 @@ char *posix_builtins[] =
bb9a7e
   (char *)NULL
bb9a7e
 };
bb9a7e
 
bb9a7e
+/* The builtin commands that cause requirements on other files. */
bb9a7e
+static char *requires_builtins[] =
bb9a7e
+{
bb9a7e
+  ".", "command", "exec", "source", "inlib",
bb9a7e
+  (char *)NULL
bb9a7e
+};
bb9a7e
+
bb9a7e
 /* Forward declarations. */
bb9a7e
 static int is_special_builtin ();
bb9a7e
 static int is_assignment_builtin ();
bb9a7e
 static int is_localvar_builtin ();
bb9a7e
 static int is_posix_builtin ();
bb9a7e
+static int is_requires_builtin ();
bb9a7e
 
bb9a7e
 #if !defined (HAVE_RENAME)
bb9a7e
 static int rename ();
bb9a7e
@@ -831,6 +844,8 @@ builtin_handler (self, defs, arg)
bb9a7e
     new->flags |= BUILTIN_FLAG_LOCALVAR;
bb9a7e
   if (is_posix_builtin (name))
bb9a7e
     new->flags |= BUILTIN_FLAG_POSIX_BUILTIN;
bb9a7e
+  if (is_requires_builtin (name))
bb9a7e
+    new->flags |= BUILTIN_FLAG_REQUIRES;
bb9a7e
 
bb9a7e
   array_add ((char *)new, defs->builtins);
bb9a7e
   building_builtin = 1;
bb9a7e
@@ -1250,12 +1265,13 @@ write_builtins (defs, structfile, externfile)
bb9a7e
 		  else
bb9a7e
 		    fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
bb9a7e
 
bb9a7e
-		  fprintf (structfile, "%s%s%s%s%s, %s_doc,\n",
bb9a7e
+		  fprintf (structfile, "%s%s%s%s%s%s, %s_doc,\n",
bb9a7e
 		    "BUILTIN_ENABLED | STATIC_BUILTIN",
bb9a7e
 		    (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
bb9a7e
 		    (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
bb9a7e
 		    (builtin->flags & BUILTIN_FLAG_LOCALVAR) ? " | LOCALVAR_BUILTIN" : "",
bb9a7e
 		    (builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "",
bb9a7e
+		    (builtin->flags & BUILTIN_FLAG_REQUIRES) ? " | REQUIRES_BUILTIN" : "",
bb9a7e
 		    document_name (builtin));
bb9a7e
 
bb9a7e
 		  /* Don't translate short document summaries that are identical
bb9a7e
@@ -1645,6 +1661,13 @@ is_posix_builtin (name)
bb9a7e
   return (_find_in_table (name, posix_builtins));
bb9a7e
 }
bb9a7e
 
bb9a7e
+static int
bb9a7e
+is_requires_builtin (name)
bb9a7e
+     char *name;
bb9a7e
+{
bb9a7e
+  return (_find_in_table (name, requires_builtins));
bb9a7e
+}
bb9a7e
+
bb9a7e
 #if !defined (HAVE_RENAME)
bb9a7e
 static int
bb9a7e
 rename (from, to)
bb9a7e
diff --git a/doc/bash.1 b/doc/bash.1
bb9a7e
index 5af7d42..7539368 100644
bb9a7e
--- a/doc/bash.1
bb9a7e
+++ b/doc/bash.1
bb9a7e
@@ -239,6 +239,14 @@ The shell becomes restricted (see
bb9a7e
 .B "RESTRICTED SHELL"
bb9a7e
 below).
bb9a7e
 .TP
bb9a7e
+.B \-\-rpm-requires
bb9a7e
+Produce the list of files that are required for the
bb9a7e
+shell script to run.  This implies '-n' and is subject
bb9a7e
+to the same limitations as compile time error checking checking;
bb9a7e
+Command substitutions, Conditional expressions and
bb9a7e
+.BR eval
bb9a7e
+builtin are not parsed so some dependencies may be missed.
bb9a7e
+.TP
bb9a7e
 .B \-\-verbose
bb9a7e
 Equivalent to \fB\-v\fP.
bb9a7e
 .TP
bb9a7e
diff --git a/doc/bashref.texi b/doc/bashref.texi
bb9a7e
index 9e23f58..d02151e 100644
bb9a7e
--- a/doc/bashref.texi
bb9a7e
+++ b/doc/bashref.texi
bb9a7e
@@ -6554,6 +6554,13 @@ standard.  @xref{Bash POSIX Mode}, for a description of the Bash
bb9a7e
 @item --restricted
bb9a7e
 Make the shell a restricted shell (@pxref{The Restricted Shell}).
bb9a7e
 
bb9a7e
+@item --rpm-requires
bb9a7e
+Produce the list of files that are required for the
bb9a7e
+shell script to run.  This implies '-n' and is subject
bb9a7e
+to the same limitations as compile time error checking checking;
bb9a7e
+Command substitutions, Conditional expressions and @command{eval}
bb9a7e
+are not parsed so some dependencies may be missed.
bb9a7e
+
bb9a7e
 @item --verbose
bb9a7e
 Equivalent to @option{-v}.  Print shell input lines as they're read.
bb9a7e
 
bb9a7e
diff --git a/eval.c b/eval.c
bb9a7e
index 1d967da..f197033 100644
bb9a7e
--- a/eval.c
bb9a7e
+++ b/eval.c
bb9a7e
@@ -137,7 +137,8 @@ reader_loop ()
bb9a7e
 
bb9a7e
       if (read_command () == 0)
bb9a7e
 	{
bb9a7e
-	  if (interactive_shell == 0 && read_but_dont_execute)
bb9a7e
+
bb9a7e
+	  if (interactive_shell == 0 && (read_but_dont_execute && !rpm_requires))
bb9a7e
 	    {
bb9a7e
 	      set_exit_status (EXECUTION_SUCCESS);
bb9a7e
 	      dispose_command (global_command);
bb9a7e
diff --git a/execute_cmd.c b/execute_cmd.c
bb9a7e
index d2555ad..397e283 100644
bb9a7e
--- a/execute_cmd.c
bb9a7e
+++ b/execute_cmd.c
bb9a7e
@@ -543,6 +543,8 @@ async_redirect_stdin ()
bb9a7e
 
bb9a7e
 #define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0)
bb9a7e
 
bb9a7e
+extern int rpm_requires;
bb9a7e
+
bb9a7e
 /* Execute the command passed in COMMAND, perhaps doing it asynchronously.
bb9a7e
    COMMAND is exactly what read_command () places into GLOBAL_COMMAND.
bb9a7e
    ASYNCHRONOUS, if non-zero, says to do this command in the background.
bb9a7e
@@ -574,7 +576,13 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
bb9a7e
 
bb9a7e
   if (breaking || continuing)
bb9a7e
     return (last_command_exit_value);
bb9a7e
-  if (command == 0 || read_but_dont_execute)
bb9a7e
+  if (command == 0 || (read_but_dont_execute && !rpm_requires))
bb9a7e
+    return (EXECUTION_SUCCESS);
bb9a7e
+  if (rpm_requires && command->type == cm_function_def)
bb9a7e
+    return last_command_exit_value =
bb9a7e
+      execute_intern_function (command->value.Function_def->name,
bb9a7e
+                              command->value.Function_def);
bb9a7e
+  if (read_but_dont_execute)
bb9a7e
     return (EXECUTION_SUCCESS);
bb9a7e
 
bb9a7e
   QUIT;
bb9a7e
@@ -2836,7 +2844,7 @@ execute_for_command (for_command)
bb9a7e
   save_line_number = line_number;
bb9a7e
   if (check_identifier (for_command->name, 1) == 0)
bb9a7e
     {
bb9a7e
-      if (posixly_correct && interactive_shell == 0)
bb9a7e
+      if (posixly_correct && interactive_shell == 0 && rpm_requires == 0)
bb9a7e
 	{
bb9a7e
 	  last_command_exit_value = EX_BADUSAGE;
bb9a7e
 	  jump_to_top_level (ERREXIT);
bb9a7e
diff --git a/execute_cmd.h b/execute_cmd.h
bb9a7e
index 465030a..9c7fd1c 100644
bb9a7e
--- a/execute_cmd.h
bb9a7e
+++ b/execute_cmd.h
bb9a7e
@@ -22,6 +22,9 @@
bb9a7e
 #define _EXECUTE_CMD_H_
bb9a7e
 
bb9a7e
 #include "stdc.h"
bb9a7e
+#include "variables.h"
bb9a7e
+#include "command.h"
bb9a7e
+
bb9a7e
 
bb9a7e
 #if defined (ARRAY_VARS)
bb9a7e
 struct func_array_state
bb9a7e
diff --git a/make_cmd.c b/make_cmd.c
bb9a7e
index 2d7ac96..ac53526 100644
bb9a7e
--- a/make_cmd.c
bb9a7e
+++ b/make_cmd.c
bb9a7e
@@ -35,6 +35,8 @@
bb9a7e
 #include "bashintl.h"
bb9a7e
 
bb9a7e
 #include "shell.h"
bb9a7e
+#include "builtins.h"
bb9a7e
+#include "builtins/common.h"
bb9a7e
 #include "execute_cmd.h"
bb9a7e
 #include "parser.h"
bb9a7e
 #include "flags.h"
bb9a7e
@@ -828,6 +830,30 @@ make_coproc_command (name, command)
bb9a7e
   return (make_command (cm_coproc, (SIMPLE_COM *)temp));
bb9a7e
 }
bb9a7e
 
bb9a7e
+static void
bb9a7e
+output_requirement (deptype, filename)
bb9a7e
+const char *deptype;
bb9a7e
+char *filename;
bb9a7e
+{
bb9a7e
+  static char *alphabet_set = "abcdefghijklmnopqrstuvwxyz"
bb9a7e
+                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
bb9a7e
+
bb9a7e
+  if (strchr(filename, '$') || (filename[0] != '/' && strchr(filename, '/')))
bb9a7e
+    return;
bb9a7e
+
bb9a7e
+  /*
bb9a7e
+      if the executable is called via variable substitution we can
bb9a7e
+      not dermine what it is at compile time.
bb9a7e
+
bb9a7e
+      if the executable consists only of characters not in the
bb9a7e
+      alphabet we do not consider it a dependency just an artifact
bb9a7e
+      of shell parsing (ex "exec < ${infile}").
bb9a7e
+  */
bb9a7e
+
bb9a7e
+  if (strpbrk(filename, alphabet_set))
bb9a7e
+    printf ("%s(%s)\n", deptype, filename);
bb9a7e
+}
bb9a7e
+
bb9a7e
 /* Reverse the word list and redirection list in the simple command
bb9a7e
    has just been parsed.  It seems simpler to do this here the one
bb9a7e
    time then by any other method that I can think of. */
bb9a7e
@@ -845,6 +871,28 @@ clean_simple_command (command)
bb9a7e
 	REVERSE_LIST (command->value.Simple->redirects, REDIRECT *);
bb9a7e
     }
bb9a7e
 
bb9a7e
+  if (rpm_requires && command->value.Simple->words)
bb9a7e
+    {
bb9a7e
+      char *cmd0;
bb9a7e
+      char *cmd1;
bb9a7e
+      struct builtin *b;
bb9a7e
+
bb9a7e
+      cmd0 = command->value.Simple->words->word->word;
bb9a7e
+      b = builtin_address_internal (cmd0, 0);
bb9a7e
+      cmd1 = 0;
bb9a7e
+      if (command->value.Simple->words->next)
bb9a7e
+        cmd1 = command->value.Simple->words->next->word->word;
bb9a7e
+
bb9a7e
+      if (b) {
bb9a7e
+        if ( (b->flags & REQUIRES_BUILTIN) && cmd1)
bb9a7e
+          output_requirement ("executable", cmd1);
bb9a7e
+      } else {
bb9a7e
+        if (!assignment(cmd0, 0))
bb9a7e
+          output_requirement (find_function(cmd0) ? "function" : "executable", cmd0);
bb9a7e
+      }
bb9a7e
+    } /*rpm_requires*/
bb9a7e
+
bb9a7e
+
bb9a7e
   parser_state &= ~PST_REDIRLIST;
bb9a7e
   return (command);
bb9a7e
 }
bb9a7e
diff --git a/shell.c b/shell.c
bb9a7e
index ce8087f..7dcd000 100644
bb9a7e
--- a/shell.c
bb9a7e
+++ b/shell.c
bb9a7e
@@ -194,6 +194,9 @@ int have_devfd = 0;
bb9a7e
 /* The name of the .(shell)rc file. */
bb9a7e
 static char *bashrc_file = DEFAULT_BASHRC;
bb9a7e
 
bb9a7e
+/* Non-zero if we are finding the scripts requirements. */
bb9a7e
+int rpm_requires;
bb9a7e
+
bb9a7e
 /* Non-zero means to act more like the Bourne shell on startup. */
bb9a7e
 static int act_like_sh;
bb9a7e
 
bb9a7e
@@ -260,6 +263,7 @@ static const struct {
bb9a7e
   { "protected", Int, &protected_mode, (char **)0x0 },
bb9a7e
 #endif
bb9a7e
   { "rcfile", Charp, (int *)0x0, &bashrc_file },
bb9a7e
+  { "rpm-requires", Int, &rpm_requires, (char **)0x0 },
bb9a7e
 #if defined (RESTRICTED_SHELL)
bb9a7e
   { "restricted", Int, &restricted, (char **)0x0 },
bb9a7e
 #endif
bb9a7e
@@ -502,6 +506,12 @@ main (argc, argv, env)
bb9a7e
   if (dump_translatable_strings)
bb9a7e
     read_but_dont_execute = 1;
bb9a7e
 
bb9a7e
+  if (rpm_requires)
bb9a7e
+    {
bb9a7e
+      read_but_dont_execute = 1;
bb9a7e
+      initialize_shell_builtins ();
bb9a7e
+    }
bb9a7e
+
bb9a7e
   if (running_setuid && privileged_mode == 0)
bb9a7e
     disable_priv_mode ();
bb9a7e
 
bb9a7e
diff --git a/shell.h b/shell.h
bb9a7e
index 8b41792..29b0efb 100644
bb9a7e
--- a/shell.h
bb9a7e
+++ b/shell.h
bb9a7e
@@ -99,6 +99,7 @@ extern int interactive, interactive_shell;
bb9a7e
 extern int startup_state;
bb9a7e
 extern int reading_shell_script;
bb9a7e
 extern int shell_initialized;
bb9a7e
+extern int rpm_requires;
bb9a7e
 extern int bash_argv_initialized;
bb9a7e
 extern int subshell_environment;
bb9a7e
 extern int current_command_number;