svashisht / rpms / bash

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