462fb2
diff -up bash-4.1/builtins.h.requires bash-4.1/builtins.h
462fb2
--- bash-4.1/builtins.h.requires	2009-01-04 20:32:23.000000000 +0100
462fb2
+++ bash-4.1/builtins.h	2010-08-02 17:42:41.000000000 +0200
462fb2
@@ -41,6 +41,8 @@
462fb2
 #define SPECIAL_BUILTIN 0x08	/* This is a Posix `special' builtin. */
462fb2
 #define ASSIGNMENT_BUILTIN 0x10	/* This builtin takes assignment statements. */
462fb2
 #define POSIX_BUILTIN	0x20	/* This builtins is special in the Posix command search order. */
462fb2
+#define REQUIRES_BUILTIN 0x40	/* This builtin requires other files. */
462fb2
+
462fb2
 
462fb2
 #define BASE_INDENT	4
462fb2
 
462fb2
diff -up bash-4.1/builtins/mkbuiltins.c.requires bash-4.1/builtins/mkbuiltins.c
462fb2
--- bash-4.1/builtins/mkbuiltins.c.requires	2009-01-04 20:32:23.000000000 +0100
462fb2
+++ bash-4.1/builtins/mkbuiltins.c	2010-08-02 17:42:41.000000000 +0200
462fb2
@@ -69,9 +69,15 @@ extern char *strcpy ();
462fb2
 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
462fb2
 
462fb2
 /* Flag values that builtins can have. */
462fb2
+/*  These flags are for the C code generator, 
462fb2
+    the C which is produced (./builtin.c)
462fb2
+    includes the flags definitions found 
462fb2
+    in ../builtins.h */
462fb2
 #define BUILTIN_FLAG_SPECIAL	0x01
462fb2
 #define BUILTIN_FLAG_ASSIGNMENT 0x02
462fb2
 #define BUILTIN_FLAG_POSIX_BUILTIN 0x04
462fb2
+#define BUILTIN_FLAG_REQUIRES	0x08
462fb2
+
462fb2
 
462fb2
 #define BASE_INDENT	4
462fb2
 
462fb2
@@ -163,10 +169,18 @@ char *posix_builtins[] =
462fb2
   (char *)NULL
462fb2
 };
462fb2
 
462fb2
+/* The builtin commands that cause requirements on other files. */
462fb2
+static char *requires_builtins[] =
462fb2
+{
462fb2
+  ".", "command", "exec", "source", "inlib",
462fb2
+  (char *)NULL
462fb2
+};
462fb2
+
462fb2
 /* Forward declarations. */
462fb2
 static int is_special_builtin ();
462fb2
 static int is_assignment_builtin ();
462fb2
 static int is_posix_builtin ();
462fb2
+static int is_requires_builtin ();
462fb2
 
462fb2
 #if !defined (HAVE_RENAME)
462fb2
 static int rename ();
462fb2
@@ -812,6 +826,9 @@ builtin_handler (self, defs, arg)
462fb2
     new->flags |= BUILTIN_FLAG_ASSIGNMENT;
462fb2
   if (is_posix_builtin (name))
462fb2
     new->flags |= BUILTIN_FLAG_POSIX_BUILTIN;
462fb2
+  if (is_requires_builtin (name))
462fb2
+    new->flags |= BUILTIN_FLAG_REQUIRES;
462fb2
+
462fb2
 
462fb2
   array_add ((char *)new, defs->builtins);
462fb2
   building_builtin = 1;
462fb2
@@ -1229,11 +1246,12 @@ write_builtins (defs, structfile, extern
462fb2
 		  else
462fb2
 		    fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
462fb2
 
462fb2
-		  fprintf (structfile, "%s%s%s%s, %s_doc,\n",
462fb2
+		  fprintf (structfile, "%s%s%s%s%s, %s_doc,\n",
462fb2
 		    "BUILTIN_ENABLED | STATIC_BUILTIN",
462fb2
 		    (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
462fb2
 		    (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
462fb2
 		    (builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "",
462fb2
+		    (builtin->flags & BUILTIN_FLAG_REQUIRES) ? " | REQUIRES_BUILTIN" : "",
462fb2
 		    document_name (builtin));
462fb2
 
462fb2
 		  fprintf
462fb2
@@ -1581,6 +1599,13 @@ is_posix_builtin (name)
462fb2
   return (_find_in_table (name, posix_builtins));
462fb2
 }
462fb2
 
462fb2
+static int
462fb2
+is_requires_builtin (name)
462fb2
+     char *name;
462fb2
+{
462fb2
+  return (_find_in_table (name, requires_builtins));
462fb2
+}
462fb2
+
462fb2
 #if !defined (HAVE_RENAME)
462fb2
 static int
462fb2
 rename (from, to)
462fb2
diff -up bash-4.1/doc/bash.1.requires bash-4.1/doc/bash.1
462fb2
--- bash-4.1/doc/bash.1.requires	2010-08-02 17:42:41.000000000 +0200
462fb2
+++ bash-4.1/doc/bash.1	2010-08-02 18:09:27.000000000 +0200
462fb2
@@ -231,6 +231,14 @@ The shell becomes restricted (see
462fb2
 .B "RESTRICTED SHELL"
462fb2
 below).
462fb2
 .TP
462fb2
+.B \-\-rpm-requires
462fb2
+Produce the list of files that are required for the 
462fb2
+shell script to run.  This implies '-n' and is subject
462fb2
+to the same limitations as compile time error checking checking;
462fb2
+Command substitutions, Conditional expressions and
462fb2
+.BR eval
462fb2
+builtin are not parsed so some dependencies may be missed.
462fb2
+.TP
462fb2
 .B \-\-verbose
462fb2
 Equivalent to  \fB\-v\fP.
462fb2
 .TP
462fb2
diff -up bash-4.1/doc/bashref.texi.requires bash-4.1/doc/bashref.texi
462fb2
--- bash-4.1/doc/bashref.texi.requires	2010-08-02 17:42:41.000000000 +0200
462fb2
+++ bash-4.1/doc/bashref.texi	2010-08-02 18:11:58.000000000 +0200
462fb2
@@ -5343,6 +5343,13 @@ standard.  @xref{Bash POSIX Mode}, for a
462fb2
 @item --restricted
462fb2
 Make the shell a restricted shell (@pxref{The Restricted Shell}).
462fb2
 
462fb2
+@item --rpm-requires
462fb2
+Produce the list of files that are required for the 
462fb2
+shell script to run.  This implies '-n' and is subject
462fb2
+to the same limitations as compile time error checking checking;
462fb2
+Command substitutions, Conditional expressions and @command{eval}
462fb2
+are not parsed so some dependencies may be missed.
462fb2
+
462fb2
 @item --verbose
462fb2
 Equivalent to @option{-v}.  Print shell input lines as they're read.
462fb2
 
462fb2
diff -up bash-4.1/eval.c.requires bash-4.1/eval.c
462fb2
--- bash-4.1/eval.c.requires	2009-01-04 20:32:26.000000000 +0100
462fb2
+++ bash-4.1/eval.c	2010-08-02 17:42:41.000000000 +0200
462fb2
@@ -53,6 +53,7 @@ extern int last_command_exit_value, stdi
462fb2
 extern int need_here_doc;
462fb2
 extern int current_command_number, current_command_line_count, line_number;
462fb2
 extern int expand_aliases;
462fb2
+extern int rpm_requires;
462fb2
 
462fb2
 static void send_pwd_to_eterm __P((void));
462fb2
 static sighandler alrm_catcher __P((int));
462fb2
@@ -136,7 +137,7 @@ reader_loop ()
462fb2
 
462fb2
       if (read_command () == 0)
462fb2
 	{
462fb2
-	  if (interactive_shell == 0 && read_but_dont_execute)
462fb2
+	  if (interactive_shell == 0 && (read_but_dont_execute && !rpm_requires))
462fb2
 	    {
462fb2
 	      last_command_exit_value = EXECUTION_SUCCESS;
462fb2
 	      dispose_command (global_command);
462fb2
diff -up bash-4.1/execute_cmd.c.requires bash-4.1/execute_cmd.c
462fb2
--- bash-4.1/execute_cmd.c.requires	2010-08-02 17:42:41.000000000 +0200
462fb2
+++ bash-4.1/execute_cmd.c	2010-08-02 17:42:41.000000000 +0200
462fb2
@@ -503,6 +503,8 @@ async_redirect_stdin ()
462fb2
 
462fb2
 #define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0)
462fb2
 
462fb2
+extern int rpm_requires;
462fb2
+
462fb2
 /* Execute the command passed in COMMAND, perhaps doing it asynchrounously.
462fb2
    COMMAND is exactly what read_command () places into GLOBAL_COMMAND.
462fb2
    ASYNCHROUNOUS, if non-zero, says to do this command in the background.
462fb2
@@ -534,7 +536,13 @@ execute_command_internal (command, async
462fb2
 #else
462fb2
   if (breaking || continuing)
462fb2
     return (last_command_exit_value);
462fb2
-  if (command == 0 || read_but_dont_execute)
462fb2
+  if (command == 0 || (read_but_dont_execute && !rpm_requires))
462fb2
+    return (EXECUTION_SUCCESS);
462fb2
+  if (rpm_requires && command->type == cm_function_def)
462fb2
+    return last_command_exit_value =
462fb2
+      execute_intern_function (command->value.Function_def->name,
462fb2
+                              command->value.Function_def->command);
462fb2
+  if (read_but_dont_execute)
462fb2
     return (EXECUTION_SUCCESS);
462fb2
 #endif
462fb2
 
462fb2
@@ -5066,7 +5074,7 @@ execute_intern_function (name, function)
462fb2
 
462fb2
   if (check_identifier (name, posixly_correct) == 0)
462fb2
     {
462fb2
-      if (posixly_correct && interactive_shell == 0)
462fb2
+      if (posixly_correct && interactive_shell == 0 && rpm_requires == 0)
462fb2
 	{
462fb2
 	  last_command_exit_value = EX_BADUSAGE;
462fb2
 	  jump_to_top_level (ERREXIT);
462fb2
diff -up bash-4.1/execute_cmd.h.requires bash-4.1/execute_cmd.h
462fb2
--- bash-4.1/execute_cmd.h.requires	2009-01-16 22:20:15.000000000 +0100
462fb2
+++ bash-4.1/execute_cmd.h	2010-08-02 17:42:41.000000000 +0200
462fb2
@@ -22,6 +22,8 @@
462fb2
 #define _EXECUTE_CMD_H_
462fb2
 
462fb2
 #include "stdc.h"
462fb2
+#include "variables.h"
462fb2
+#include "command.h"
462fb2
 
462fb2
 extern struct fd_bitmap *new_fd_bitmap __P((int));
462fb2
 extern void dispose_fd_bitmap __P((struct fd_bitmap *));
462fb2
diff -up bash-4.1/make_cmd.c.requires bash-4.1/make_cmd.c
462fb2
--- bash-4.1/make_cmd.c.requires	2009-09-11 23:26:12.000000000 +0200
462fb2
+++ bash-4.1/make_cmd.c	2010-08-02 17:42:41.000000000 +0200
462fb2
@@ -42,11 +42,15 @@
462fb2
 #include "flags.h"
462fb2
 #include "make_cmd.h"
462fb2
 #include "dispose_cmd.h"
462fb2
+#include "execute_cmd.h"
462fb2
 #include "variables.h"
462fb2
 #include "subst.h"
462fb2
 #include "input.h"
462fb2
 #include "ocache.h"
462fb2
 #include "externs.h"
462fb2
+#include "builtins.h"
462fb2
+
462fb2
+#include "builtins/common.h"
462fb2
 
462fb2
 #if defined (JOB_CONTROL)
462fb2
 #include "jobs.h"
462fb2
@@ -56,6 +60,10 @@
462fb2
 
462fb2
 extern int line_number, current_command_line_count, parser_state;
462fb2
 extern int last_command_exit_value;
462fb2
+extern int rpm_requires;
462fb2
+
462fb2
+static char *alphabet_set = "abcdefghijklmnopqrstuvwxyz"
462fb2
+                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
462fb2
 
462fb2
 /* Object caching */
462fb2
 sh_obj_cache_t wdcache = {0, 0, 0};
462fb2
@@ -820,6 +828,27 @@ make_coproc_command (name, command)
462fb2
   return (make_command (cm_coproc, (SIMPLE_COM *)temp));
462fb2
 }
462fb2
 
462fb2
+static void
462fb2
+output_requirement (deptype, filename)
462fb2
+const char *deptype;
462fb2
+char *filename;
462fb2
+{
462fb2
+  if (strchr(filename, '$') || (filename[0] != '/' && strchr(filename, '/')))
462fb2
+    return;
462fb2
+
462fb2
+  /* 
462fb2
+      if the executable is called via variable substitution we can
462fb2
+      not dermine what it is at compile time.  
462fb2
+
462fb2
+      if the executable consists only of characters not in the
462fb2
+      alphabet we do not consider it a dependency just an artifact
462fb2
+      of shell parsing (ex "exec < ${infile}").
462fb2
+  */
462fb2
+
462fb2
+  if (strpbrk(filename, alphabet_set))
462fb2
+    printf ("%s(%s)\n", deptype, filename);
462fb2
+}
462fb2
+
462fb2
 /* Reverse the word list and redirection list in the simple command
462fb2
    has just been parsed.  It seems simpler to do this here the one
462fb2
    time then by any other method that I can think of. */
462fb2
@@ -837,6 +866,27 @@ clean_simple_command (command)
462fb2
 	REVERSE_LIST (command->value.Simple->redirects, REDIRECT *);
462fb2
     }
462fb2
 
462fb2
+  if (rpm_requires && command->value.Simple->words)
462fb2
+    {
462fb2
+      char *cmd0;
462fb2
+      char *cmd1;
462fb2
+      struct builtin *b;
462fb2
+
462fb2
+      cmd0 = command->value.Simple->words->word->word;
462fb2
+      b = builtin_address_internal (cmd0, 0);
462fb2
+      cmd1 = 0;
462fb2
+      if (command->value.Simple->words->next)
462fb2
+        cmd1 = command->value.Simple->words->next->word->word;
462fb2
+
462fb2
+      if (b) {
462fb2
+        if ( (b->flags & REQUIRES_BUILTIN) && cmd1)
462fb2
+          output_requirement ("executable", cmd1);
462fb2
+      } else {
462fb2
+        if (!assignment(cmd0, 0))
462fb2
+          output_requirement (find_function(cmd0) ? "function" : "executable", cmd0);
462fb2
+      }
462fb2
+    } /*rpm_requires*/
462fb2
+
462fb2
   parser_state &= ~PST_REDIRLIST;
462fb2
   return (command);
462fb2
 }
462fb2
diff -up bash-4.1/shell.c.requires bash-4.1/shell.c
462fb2
--- bash-4.1/shell.c.requires	2010-08-02 17:42:41.000000000 +0200
462fb2
+++ bash-4.1/shell.c	2010-08-02 17:42:41.000000000 +0200
462fb2
@@ -193,6 +193,9 @@ int have_devfd = 0;
462fb2
 /* The name of the .(shell)rc file. */
462fb2
 static char *bashrc_file = "~/.bashrc";
462fb2
 
462fb2
+/* Non-zero if we are finding the scripts requirements. */
462fb2
+int rpm_requires;
462fb2
+
462fb2
 /* Non-zero means to act more like the Bourne shell on startup. */
462fb2
 static int act_like_sh;
462fb2
 
462fb2
@@ -251,6 +254,7 @@ static const struct {
462fb2
   { "posix", Int, &posixly_correct, (char **)0x0 },
462fb2
   { "protected", Int, &protected_mode, (char **)0x0 },
462fb2
   { "rcfile", Charp, (int *)0x0, &bashrc_file },
462fb2
+  { "rpm-requires", Int, &rpm_requires, (char **)0x0 },
462fb2
 #if defined (RESTRICTED_SHELL)
462fb2
   { "restricted", Int, &restricted, (char **)0x0 },
462fb2
 #endif
462fb2
@@ -485,6 +489,12 @@ main (argc, argv, env)
462fb2
   if (dump_translatable_strings)
462fb2
     read_but_dont_execute = 1;
462fb2
 
462fb2
+  if (rpm_requires)
462fb2
+    {
462fb2
+      read_but_dont_execute = 1;
462fb2
+      initialize_shell_builtins ();
462fb2
+    }
462fb2
+
462fb2
   if (running_setuid && privileged_mode == 0)
462fb2
     disable_priv_mode ();
462fb2