Removed the use of the environ variable and instead use the environment array
authorJohn Criswell <criswell@uiuc.edu>
Wed, 17 Sep 2003 15:20:51 +0000 (15:20 +0000)
committerJohn Criswell <criswell@uiuc.edu>
Wed, 17 Sep 2003 15:20:51 +0000 (15:20 +0000)
passed into main().  This may (or may not) be more portable, but it looks
nicer.
Added functions to copy the environment array and modify the copy, thus
preserving the environment.
Switched from using system() to using ExecWait().
The code now removes the assembly file generated when using the -native option.
Fixed the remove_env() function: The previous revision truncated the
environment variable list.  This version just zaps the variable as intended.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8579 91177308-0d34-0410-b5e6-96231b3b80d8

tools/gccld/gccld.cpp

index d78139db556db36d3536fd8a6d283f8e206a9acb..1712f0b36d1a979ed95d01a6485ef090eaa5743e 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/Scalar.h"
 #include "Support/FileUtilities.h"
+#include "Support/SystemUtils.h"
 #include "Support/CommandLine.h"
 #include "Support/Signals.h"
 #include "Config/unistd.h"
@@ -30,9 +31,6 @@
 #include <set>
 #include <algorithm>
 
-// This is the environment given to the program.
-extern char ** environ;
-
 namespace {
   cl::list<std::string> 
   InputFilenames(cl::Positional, cl::desc("<input bytecode files>"),
@@ -319,6 +317,80 @@ static int PrintAndReturn(const char *progname, const std::string &Message,
   return 1;
 }
 
+//
+//
+// Function: copy_env()
+//
+// Description:
+//     This function takes an array of environment variables and makes a
+//     copy of it.  This copy can then be manipulated any way the caller likes
+//  without affecting the process's real environment.
+//
+// Inputs:
+//  envp - An array of C strings containing an environment.
+//
+// Outputs:
+//  None.
+//
+// Return value:
+//  NULL - An error occurred.
+//  Otherwise, a pointer to a new array of C strings is returned.  Every string
+//  in the array is a duplicate of the one in the original array (i.e. we do
+//  not copy the char *'s from one array to another).
+//
+static char **
+copy_env (char ** envp)
+{
+  // The new environment list
+  char ** newenv;
+
+  // The number of entries in the old environment list
+  int entries;
+
+  //
+  // Count the number of entries in the old list;
+  //
+  for (entries = 0; envp[entries] != NULL; entries++)
+  {
+    ;
+  }
+
+  //
+  // Add one more entry for the NULL pointer that ends the list.
+  //
+  ++entries;
+
+  //
+  // If there are no entries at all, just return NULL.
+  //
+  if (entries == 0)
+  {
+    return NULL;
+  }
+
+  //
+  // Allocate a new environment list.
+  //
+  if ((newenv = new (char *) [entries]) == NULL)
+  {
+    return NULL;
+  }
+
+  //
+  // Make a copy of the list.  Don't forget the NULL that ends the list.
+  //
+  entries = 0;
+  while (envp[entries] != NULL)
+  {
+    newenv[entries] = strdup (envp[entries]);
+    ++entries;
+  }
+  newenv[entries] = NULL;
+
+  return newenv;
+}
+
+
 //
 // Function: remove_env()
 //
@@ -371,7 +443,7 @@ remove_env (const char * name, char ** envp)
     //
     if (!strcmp (name, envp[index]))
     {
-      envp[index] = NULL;
+      *envp[index] = '\0';
     }
     else
     {
@@ -383,7 +455,7 @@ remove_env (const char * name, char ** envp)
 }
 
 
-int main(int argc, char **argv) {
+int main(int argc, char **argv, char ** envp) {
   cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n");
 
   std::string ErrorMessage;
@@ -509,26 +581,39 @@ int main(int argc, char **argv) {
     //
     if (Native)
     {
-      // Name of the output assembly file
-      std::string AssemblyFile = OutputFilename + ".s";
-
-      // Name of the command to execute
-      std::string cmd;
-
       //
-      // Create an executable file from the bytecode file.
+      // Remove these environment variables from the environment of the
+      // programs that we will execute.  It appears that GCC sets these
+      // environment variables so that the programs it uses can configure
+      // themselves identically.
+      //
+      // However, when we invoke GCC below, we want it to use its  normal
+      // configuration.  Hence, we must sanitize it's environment.
       //
-      remove_env ("LIBRARY_PATH", environ);
-      remove_env ("COLLECT_GCC_OPTIONS", environ);
-      remove_env ("GCC_EXEC_PREFIX", environ);
-      remove_env ("COMPILER_PATH", environ);
-      remove_env ("COLLECT_GCC", environ);
+      char ** clean_env = copy_env (envp);
+      if (clean_env == NULL)
+      {
+        return PrintAndReturn (argv[0], "Failed to duplicate environment");
+      }
+      remove_env ("LIBRARY_PATH", clean_env);
+      remove_env ("COLLECT_GCC_OPTIONS", clean_env);
+      remove_env ("GCC_EXEC_PREFIX", clean_env);
+      remove_env ("COMPILER_PATH", clean_env);
+      remove_env ("COLLECT_GCC", clean_env);
 
       //
       // Run LLC to convert the bytecode file into assembly code.
       //
-      cmd = "llc -f -o " + AssemblyFile + " " + RealBytecodeOutput;
-      if ((system (cmd.c_str())) == -1)
+      char * cmd[8];
+      std::string AssemblyFile = OutputFilename + ".s";
+
+      cmd[0] = (char *) "llc";
+      cmd[1] = (char *) "-f";
+      cmd[2] = (char *) "-o";
+      cmd[3] = (char *) AssemblyFile.c_str();
+      cmd[4] = (char *) RealBytecodeOutput.c_str();
+      cmd[5] = (char *) NULL;
+      if ((ExecWait (cmd, clean_env)) == -1)
       {
         return PrintAndReturn (argv[0], "Failed to compile bytecode");
       }
@@ -541,11 +626,25 @@ int main(int argc, char **argv) {
       //  and linker because we don't know where to put the _start symbol.
       //  GCC mysteriously knows how to do it.
       //
-      cmd = "gcc -o " + OutputFilename + " " + AssemblyFile;
-      if ((system (cmd.c_str())) == -1)
+      cmd[0] = (char *) "gcc";
+      cmd[1] = (char *) "-o";
+      cmd[2] = (char *) OutputFilename.c_str();
+      cmd[3] = (char *) AssemblyFile.c_str();
+      cmd[4] = (char *) NULL;
+      if ((ExecWait (cmd, clean_env)) == -1)
       {
         return PrintAndReturn (argv[0], "Failed to link native code file");
       }
+
+      //
+      // The assembly file is no longer needed.  Remove it, but do not exit
+      // if we fail to unlink it.
+      //
+      if (((access (AssemblyFile.c_str(), F_OK)) != -1) &&
+          ((unlink (AssemblyFile.c_str())) == -1))
+      {
+        std::cerr << "Warning: Failed to unlink " << AssemblyFile << "\n";
+      }
     }
     else
     {