Blame SOURCES/bash-requires.patch

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