Blame SOURCES/bash-requires.patch

50ece2
diff --git a/builtins.h b/builtins.h
50ece2
index 0cfea18..a6ef958 100644
50ece2
--- a/builtins.h
50ece2
+++ b/builtins.h
50ece2
@@ -42,6 +42,7 @@
50ece2
 #define ASSIGNMENT_BUILTIN 0x10	/* This builtin takes assignment statements. */
50ece2
 #define POSIX_BUILTIN	0x20	/* This builtins is special in the Posix command search order. */
50ece2
 #define LOCALVAR_BUILTIN   0x40	/* This builtin creates local variables */
50ece2
+#define REQUIRES_BUILTIN 0x80  /* This builtin requires other files. */
50ece2
 
50ece2
 #define BASE_INDENT	4
50ece2
 
50ece2
diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c
50ece2
index 4f51201..283bfea 100644
50ece2
--- a/builtins/mkbuiltins.c
50ece2
+++ b/builtins/mkbuiltins.c
50ece2
@@ -69,10 +69,15 @@ extern char *strcpy ();
50ece2
 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
50ece2
 
50ece2
 /* Flag values that builtins can have. */
50ece2
+/*  These flags are for the C code generator, 
50ece2
+    the C which is produced (./builtin.c)
50ece2
+    includes the flags definitions found 
50ece2
+    in ../builtins.h */
50ece2
 #define BUILTIN_FLAG_SPECIAL	0x01
50ece2
 #define BUILTIN_FLAG_ASSIGNMENT 0x02
50ece2
 #define BUILTIN_FLAG_LOCALVAR	0x04
50ece2
 #define BUILTIN_FLAG_POSIX_BUILTIN 0x08
50ece2
+#define BUILTIN_FLAG_REQUIRES  0x10
50ece2
 
50ece2
 #define BASE_INDENT	4
50ece2
 
50ece2
@@ -173,11 +178,20 @@ char *posix_builtins[] =
50ece2
   (char *)NULL
50ece2
 };
50ece2
 
50ece2
+/* The builtin commands that cause requirements on other files. */
50ece2
+static char *requires_builtins[] =
50ece2
+{
50ece2
+  ".", "command", "exec", "source", "inlib",
50ece2
+  (char *)NULL
50ece2
+};
50ece2
+
50ece2
+
50ece2
 /* Forward declarations. */
50ece2
 static int is_special_builtin ();
50ece2
 static int is_assignment_builtin ();
50ece2
 static int is_localvar_builtin ();
50ece2
 static int is_posix_builtin ();
50ece2
+static int is_requires_builtin ();
50ece2
 
50ece2
 #if !defined (HAVE_RENAME)
50ece2
 static int rename ();
50ece2
@@ -831,6 +845,9 @@ builtin_handler (self, defs, arg)
50ece2
     new->flags |= BUILTIN_FLAG_LOCALVAR;
50ece2
   if (is_posix_builtin (name))
50ece2
     new->flags |= BUILTIN_FLAG_POSIX_BUILTIN;
50ece2
+  if (is_requires_builtin (name))
50ece2
+    new->flags |= BUILTIN_FLAG_REQUIRES;
50ece2
+
50ece2
 
50ece2
   array_add ((char *)new, defs->builtins);
50ece2
   building_builtin = 1;
50ece2
@@ -1250,12 +1267,13 @@ write_builtins (defs, structfile, externfile)
50ece2
 		  else
50ece2
 		    fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
50ece2
 
50ece2
-		  fprintf (structfile, "%s%s%s%s%s, %s_doc,\n",
50ece2
+		  fprintf (structfile, "%s%s%s%s%s%s, %s_doc,\n",
50ece2
 		    "BUILTIN_ENABLED | STATIC_BUILTIN",
50ece2
 		    (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
50ece2
 		    (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
50ece2
 		    (builtin->flags & BUILTIN_FLAG_LOCALVAR) ? " | LOCALVAR_BUILTIN" : "",
50ece2
 		    (builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "",
50ece2
+		    (builtin->flags & BUILTIN_FLAG_REQUIRES) ? " | REQUIRES_BUILTIN" : "",
50ece2
 		    document_name (builtin));
50ece2
 
50ece2
 		  /* Don't translate short document summaries that are identical
50ece2
@@ -1645,6 +1663,13 @@ is_posix_builtin (name)
50ece2
   return (_find_in_table (name, posix_builtins));
50ece2
 }
50ece2
 
50ece2
+static int
50ece2
+is_requires_builtin (name)
50ece2
+     char *name;
50ece2
+{
50ece2
+  return (_find_in_table (name, requires_builtins));
50ece2
+}
50ece2
+
50ece2
 #if !defined (HAVE_RENAME)
50ece2
 static int
50ece2
 rename (from, to)
50ece2
diff --git a/doc/bash.1 b/doc/bash.1
50ece2
index c21e877..04ce845 100644
50ece2
--- a/doc/bash.1
50ece2
+++ b/doc/bash.1
50ece2
@@ -238,6 +238,14 @@ The shell becomes restricted (see
50ece2
 .B "RESTRICTED SHELL"
50ece2
 below).
50ece2
 .TP
50ece2
+.B \-\-rpm-requires
50ece2
+Produce the list of files that are required for the 
50ece2
+shell script to run.  This implies '-n' and is subject
50ece2
+to the same limitations as compile time error checking checking;
50ece2
+Command substitutions, Conditional expressions and
50ece2
+.BR eval
50ece2
+builtin are not parsed so some dependencies may be missed.
50ece2
+.TP
50ece2
 .B \-\-verbose
50ece2
 Equivalent to \fB\-v\fP.
50ece2
 .TP
50ece2
diff --git a/doc/bashref.texi b/doc/bashref.texi
50ece2
index 06957b6..e3fe925 100644
50ece2
--- a/doc/bashref.texi
50ece2
+++ b/doc/bashref.texi
50ece2
@@ -6243,6 +6243,13 @@ standard.  @xref{Bash POSIX Mode}, for a description of the Bash
50ece2
 @item --restricted
50ece2
 Make the shell a restricted shell (@pxref{The Restricted Shell}).
50ece2
 
50ece2
+@item --rpm-requires
50ece2
+Produce the list of files that are required for the 
50ece2
+shell script to run.  This implies '-n' and is subject
50ece2
+to the same limitations as compile time error checking checking;
50ece2
+Command substitutions, Conditional expressions and @command{eval}
50ece2
+are not parsed so some dependencies may be missed.
50ece2
+
50ece2
 @item --verbose
50ece2
 Equivalent to @option{-v}.  Print shell input lines as they're read.
50ece2
 
50ece2
diff --git a/eval.c b/eval.c
50ece2
index db863e7..5a5af32 100644
50ece2
--- a/eval.c
50ece2
+++ b/eval.c
50ece2
@@ -56,6 +56,7 @@ extern int need_here_doc;
50ece2
 extern int current_command_number, current_command_line_count, line_number;
50ece2
 extern int expand_aliases;
50ece2
 extern char *ps0_prompt;
50ece2
+extern int rpm_requires;
50ece2
 
50ece2
 #if defined (HAVE_POSIX_SIGNALS)
50ece2
 extern sigset_t top_level_mask;
50ece2
@@ -148,7 +149,7 @@ reader_loop ()
50ece2
 
50ece2
       if (read_command () == 0)
50ece2
 	{
50ece2
-	  if (interactive_shell == 0 && read_but_dont_execute)
50ece2
+	  if (interactive_shell == 0 && (read_but_dont_execute && !rpm_requires))
50ece2
 	    {
50ece2
 	      last_command_exit_value = EXECUTION_SUCCESS;
50ece2
 	      dispose_command (global_command);
50ece2
diff --git a/execute_cmd.c b/execute_cmd.c
50ece2
index b5cd405..88c7a5c 100644
50ece2
--- a/execute_cmd.c
50ece2
+++ b/execute_cmd.c
50ece2
@@ -533,6 +533,8 @@ async_redirect_stdin ()
50ece2
 
50ece2
 #define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0)
50ece2
 
50ece2
+extern int rpm_requires;
50ece2
+
50ece2
 /* Execute the command passed in COMMAND, perhaps doing it asynchronously.
50ece2
    COMMAND is exactly what read_command () places into GLOBAL_COMMAND.
50ece2
    ASYNCHROUNOUS, if non-zero, says to do this command in the background.
50ece2
@@ -565,7 +567,13 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
50ece2
 
50ece2
   if (breaking || continuing)
50ece2
     return (last_command_exit_value);
50ece2
-  if (command == 0 || read_but_dont_execute)
50ece2
+  if (command == 0 || (read_but_dont_execute && !rpm_requires))
50ece2
+    return (EXECUTION_SUCCESS);
50ece2
+  if (rpm_requires && command->type == cm_function_def)
50ece2
+    return last_command_exit_value =
50ece2
+      execute_intern_function (command->value.Function_def->name,
50ece2
+                              command->value.Function_def);
50ece2
+  if (read_but_dont_execute)
50ece2
     return (EXECUTION_SUCCESS);
50ece2
 
50ece2
   QUIT;
50ece2
@@ -5752,7 +5760,7 @@ execute_intern_function (name, funcdef)
50ece2
 
50ece2
   if (check_identifier (name, posixly_correct) == 0)
50ece2
     {
50ece2
-      if (posixly_correct && interactive_shell == 0)
50ece2
+      if (posixly_correct && interactive_shell == 0 && rpm_requires == 0)
50ece2
 	{
50ece2
 	  last_command_exit_value = EX_BADUSAGE;
50ece2
 	  jump_to_top_level (ERREXIT);
50ece2
diff --git a/execute_cmd.h b/execute_cmd.h
50ece2
index 62bec82..d42dc85 100644
50ece2
--- a/execute_cmd.h
50ece2
+++ b/execute_cmd.h
50ece2
@@ -22,6 +22,8 @@
50ece2
 #define _EXECUTE_CMD_H_
50ece2
 
50ece2
 #include "stdc.h"
50ece2
+#include "variables.h"
50ece2
+#include "command.h"
50ece2
 
50ece2
 #if defined (ARRAY_VARS)
50ece2
 struct func_array_state
50ece2
diff --git a/make_cmd.c b/make_cmd.c
50ece2
index b42e9ff..a982fe0 100644
50ece2
--- a/make_cmd.c
50ece2
+++ b/make_cmd.c
50ece2
@@ -42,11 +42,15 @@
50ece2
 #include "flags.h"
50ece2
 #include "make_cmd.h"
50ece2
 #include "dispose_cmd.h"
50ece2
+#include "execute_cmd.h"
50ece2
 #include "variables.h"
50ece2
 #include "subst.h"
50ece2
 #include "input.h"
50ece2
 #include "ocache.h"
50ece2
 #include "externs.h"
50ece2
+#include "builtins.h"
50ece2
+
50ece2
+#include "builtins/common.h"
50ece2
 
50ece2
 #if defined (JOB_CONTROL)
50ece2
 #include "jobs.h"
50ece2
@@ -57,6 +61,10 @@
50ece2
 extern int line_number, current_command_line_count, parser_state;
50ece2
 extern int last_command_exit_value;
50ece2
 extern int shell_initialized;
50ece2
+extern int rpm_requires;
50ece2
+
50ece2
+static char *alphabet_set = "abcdefghijklmnopqrstuvwxyz"
50ece2
+                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
50ece2
 
50ece2
 int here_doc_first_line = 0;
50ece2
 
50ece2
@@ -839,6 +847,27 @@ make_coproc_command (name, command)
50ece2
   return (make_command (cm_coproc, (SIMPLE_COM *)temp));
50ece2
 }
50ece2
 
50ece2
+static void
50ece2
+output_requirement (deptype, filename)
50ece2
+const char *deptype;
50ece2
+char *filename;
50ece2
+{
50ece2
+  if (strchr(filename, '$') || (filename[0] != '/' && strchr(filename, '/')))
50ece2
+    return;
50ece2
+
50ece2
+  /* 
50ece2
+      if the executable is called via variable substitution we can
50ece2
+      not dermine what it is at compile time.  
50ece2
+
50ece2
+      if the executable consists only of characters not in the
50ece2
+      alphabet we do not consider it a dependency just an artifact
50ece2
+      of shell parsing (ex "exec < ${infile}").
50ece2
+  */
50ece2
+
50ece2
+  if (strpbrk(filename, alphabet_set))
50ece2
+    printf ("%s(%s)\n", deptype, filename);
50ece2
+}
50ece2
+
50ece2
 /* Reverse the word list and redirection list in the simple command
50ece2
    has just been parsed.  It seems simpler to do this here the one
50ece2
    time then by any other method that I can think of. */
50ece2
@@ -856,6 +885,27 @@ clean_simple_command (command)
50ece2
 	REVERSE_LIST (command->value.Simple->redirects, REDIRECT *);
50ece2
     }
50ece2
 
50ece2
+  if (rpm_requires && command->value.Simple->words)
50ece2
+    {
50ece2
+      char *cmd0;
50ece2
+      char *cmd1;
50ece2
+      struct builtin *b;
50ece2
+
50ece2
+      cmd0 = command->value.Simple->words->word->word;
50ece2
+      b = builtin_address_internal (cmd0, 0);
50ece2
+      cmd1 = 0;
50ece2
+      if (command->value.Simple->words->next)
50ece2
+        cmd1 = command->value.Simple->words->next->word->word;
50ece2
+
50ece2
+      if (b) {
50ece2
+        if ( (b->flags & REQUIRES_BUILTIN) && cmd1)
50ece2
+          output_requirement ("executable", cmd1);
50ece2
+      } else {
50ece2
+        if (!assignment(cmd0, 0))
50ece2
+          output_requirement (find_function(cmd0) ? "function" : "executable", cmd0);
50ece2
+      }
50ece2
+    } /*rpm_requires*/
50ece2
+
50ece2
   parser_state &= ~PST_REDIRLIST;
50ece2
   return (command);
50ece2
 }
50ece2
diff --git a/shell.c b/shell.c
50ece2
index 7f63969..a0fb7ce 100644
50ece2
--- a/shell.c
50ece2
+++ b/shell.c
50ece2
@@ -201,6 +201,9 @@ int have_devfd = 0;
50ece2
 /* The name of the .(shell)rc file. */
50ece2
 static char *bashrc_file = DEFAULT_BASHRC;
50ece2
 
50ece2
+/* Non-zero if we are finding the scripts requirements. */
50ece2
+int rpm_requires;
50ece2
+
50ece2
 /* Non-zero means to act more like the Bourne shell on startup. */
50ece2
 static int act_like_sh;
50ece2
 
50ece2
@@ -264,6 +267,7 @@ static const struct {
50ece2
   { "protected", Int, &protected_mode, (char **)0x0 },
50ece2
 #endif
50ece2
   { "rcfile", Charp, (int *)0x0, &bashrc_file },
50ece2
+  { "rpm-requires", Int, &rpm_requires, (char **)0x0 },
50ece2
 #if defined (RESTRICTED_SHELL)
50ece2
   { "restricted", Int, &restricted, (char **)0x0 },
50ece2
 #endif
50ece2
@@ -500,6 +504,12 @@ main (argc, argv, env)
50ece2
   if (dump_translatable_strings)
50ece2
     read_but_dont_execute = 1;
50ece2
 
50ece2
+  if (rpm_requires)
50ece2
+    {
50ece2
+      read_but_dont_execute = 1;
50ece2
+      initialize_shell_builtins ();
50ece2
+    }
50ece2
+
50ece2
   if (running_setuid && privileged_mode == 0)
50ece2
     disable_priv_mode ();
50ece2
 
50ece2
-- 
50ece2
2.9.3
50ece2