]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Run programs in a user environment without Tools' settings.
authorVMware, Inc <>
Thu, 15 Oct 2009 21:05:19 +0000 (14:05 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 15 Oct 2009 21:05:19 +0000 (14:05 -0700)
vmware-user on Linux uses the app-loader tool to set up its
environment so it can use various bundled libraries. However,
this cause these environment variables to be set that when
VIX runs programs or scripts from vmware-user, these processes
fail due to library conflicts. For example, gedit on RHEL 4 was
compiled with a version of libpango that conflicts with the
version of this library that ships with the Tools.

The solution is to store the original, pre-app-loader
environment with the VIX tools module. Some of the
infrastructure was already in place to fix a similar issue when
launching a web browser to view the Help from toolbox. However,
this needed to be plumbed through VIX, and added to lib/procMgr.

Also, one further wrinkle is that VIX allows clients to
programatically change the environment. So, we keep track of the
environment using a hash table, update it when processing
WriteVariable commands, then serial the hashtable into a environ
block when RunProgram or RunScript are called.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/include/procMgr.h
open-vm-tools/lib/include/vixTools.h
open-vm-tools/lib/procMgr/procMgrPosix.c
open-vm-tools/lib/vixTools/vixTools.c
open-vm-tools/services/plugins/vix/foundryToolsDaemon.c
open-vm-tools/services/plugins/vix/foundryToolsDaemon.h
open-vm-tools/vmware-user/vmware-user.cpp

index 150214e53563ed7ff894cc8a1777b028c6911e42..54833e603acb7946a89ab456238d15b39c85b0e0 100644 (file)
@@ -59,36 +59,36 @@ typedef struct ProcMgr_ProcList {
 } ProcMgr_ProcList;
 
 
-#if defined(_WIN32)
-/*
- * If a caller needs to use a non-default set of arguments for
- * CreateProcess[AsUser] in ProcMgr_Exec[A]sync, this structure should be used. 
- *
- * - If 'userArgs' is NULL, defaults are used:
- *   - bInheritHandles defaults to TRUE
- *   - lpStartupInfo is instantiated and initialized with:
- *     - cb initialized to size of the object
- *     - dwFlags initialized to STARTF_USESHOWWINDOW
- *     - wShowWindow initialized to SW_MINIMIZE.
- *   - defaults for all other parameters are NULL/FALSE
- *
- * - If 'userArgs' is not NULL, the values in the 'userArgs' object are used
- *   according to the following rules:
- *   - If lpStartupInfo is NULL, it is instantiated and initialized with:
- *     - cb initialized to size of the object
- *     - dwFlags initialized to STARTF_USESHOWWINDOW
- *     - wShowWindow initialized to SW_MINIMIZE.
- *     - The caller would need to do some of this initialization if they set
- *       lpStartupInfo.
- *   - If hToken is set:
- *     - if lpStartupInfo->lpDesktop is not NULL, then it is used directly. Otherwise,
- *       lpStartupInfo->lpDesktop is initialized appropriately.
- *
- *     XXX: Make it more convenient for callers(like ToolsDaemonTcloRunProgramImpl) 
- *     to set just wShowWindow without needing to instantiate and initialize a 
- *     STARTUPINFO object. 
- */
 typedef struct ProcMgr_ProcArgs {
+#if defined(_WIN32)
+   /*
+    * If a caller needs to use a non-default set of arguments for
+    * CreateProcess[AsUser] in ProcMgr_Exec[A]sync, this structure should be used. 
+    *
+    * - If 'userArgs' is NULL, defaults are used:
+    *   - bInheritHandles defaults to TRUE
+    *   - lpStartupInfo is instantiated and initialized with:
+    *     - cb initialized to size of the object
+    *     - dwFlags initialized to STARTF_USESHOWWINDOW
+    *     - wShowWindow initialized to SW_MINIMIZE.
+    *   - defaults for all other parameters are NULL/FALSE
+    *
+    * - If 'userArgs' is not NULL, the values in the 'userArgs' object are used
+    *   according to the following rules:
+    *   - If lpStartupInfo is NULL, it is instantiated and initialized with:
+    *     - cb initialized to size of the object
+    *     - dwFlags initialized to STARTF_USESHOWWINDOW
+    *     - wShowWindow initialized to SW_MINIMIZE.
+    *     - The caller would need to do some of this initialization if they set
+    *       lpStartupInfo.
+    *   - If hToken is set:
+    *     - if lpStartupInfo->lpDesktop is not NULL, then it is used directly. Otherwise,
+    *       lpStartupInfo->lpDesktop is initialized appropriately.
+    *
+    *     XXX: Make it more convenient for callers(like ToolsDaemonTcloRunProgramImpl) 
+    *     to set just wShowWindow without needing to instantiate and initialize a 
+    *     STARTUPINFO object. 
+    */
    HANDLE hToken;
 
    LPCWSTR lpApplicationName;
@@ -99,11 +99,16 @@ typedef struct ProcMgr_ProcArgs {
    LPVOID lpEnvironment;
    LPCWSTR lpCurrentDirectory;
    LPSTARTUPINFO lpStartupInfo;
-} ProcMgr_ProcArgs;
 #else
-/* Placeholder type for non win32 platforms. Not used. */
-typedef void * ProcMgr_ProcArgs;
+   /*
+    * The environment variables to run the program with. If NULL, use the current
+    * environment.
+    */
+   char **envp;
 #endif
+} ProcMgr_ProcArgs;
+
+
 
 
 typedef void ProcMgr_Callback(Bool status, void *clientData);
index 7215b915f119a0d23dda54140399321e06e5d847..8a4a73a0e69d6b3b4c69540a67137dfc27966596 100644 (file)
@@ -38,6 +38,7 @@ typedef void (*VixToolsReportProgramDoneProcType)(const char *requestName,
                                                   void *clientData);
 
 VixError VixTools_Initialize(Bool thisProcessRunsAsRootArg,
+                             const char * const *originalEnvp,
                              VixToolsReportProgramDoneProcType reportProgramDoneProc,
                              void *clientData);
 
index 94e7d5a5c08ed1ec424e10840dd594f699b2f58a..3188b5062795b5c8c03177b674dcf1180bdd6a71 100644 (file)
@@ -69,6 +69,7 @@
 #include "str.h"
 #include "fileIO.h"
 #include "codeset.h"
+#include "unicode.h"
 
 
 /*
@@ -97,7 +98,8 @@ struct ProcMgr_AsyncProc {
    int exitCode;
 };
 
-static pid_t ProcMgrStartProcess(char const *cmd);
+static pid_t ProcMgrStartProcess(char const *cmd,
+                                 char * const  *envp);
 
 static Bool ProcMgrWaitForProcCompletion(pid_t pid,
                                          Bool *validExitCode,
@@ -573,13 +575,13 @@ ProcMgr_FreeProcList(ProcMgr_ProcList *procList)
 
 Bool
 ProcMgr_ExecSync(char const *cmd,                  // IN: UTF-8 command line
-                 ProcMgr_ProcArgs *userArgs)       // IN: Unused
+                 ProcMgr_ProcArgs *userArgs)       // IN: optional
 {
    pid_t pid;
 
    Debug("Executing sync command: %s\n", cmd);
 
-   pid = ProcMgrStartProcess(cmd);
+   pid = ProcMgrStartProcess(cmd, userArgs ? userArgs->envp : NULL);
 
    if (pid == -1) {
       return FALSE;
@@ -606,37 +608,54 @@ ProcMgr_ExecSync(char const *cmd,                  // IN: UTF-8 command line
  *----------------------------------------------------------------------
  */
 
-static pid_t 
-ProcMgrStartProcess(char const *cmd)            // IN: UTF-8 encoded cmd
+static pid_t
+ProcMgrStartProcess(char const *cmd,            // IN: UTF-8 encoded cmd
+                    char * const *envp)         // IN: UTF-8 encoded env vars
 {
    pid_t pid;
    char *cmdCurrent = NULL;
+   char **envpCurrent = NULL;
 
    if (cmd == NULL) {
       ASSERT(FALSE);
       return -1;
    }
 
+   /*
+    * Convert the strings before the call to fork(), since the conversion
+    * routines may rely on locks that do not survive fork().
+    */
+
    if (!CodeSet_Utf8ToCurrent(cmd, strlen(cmd), &cmdCurrent, NULL)) {
       Warning("Could not convert from UTF-8 to current\n");
       return -1;
    }
 
+   if (NULL != envp) {
+      envpCurrent = Unicode_GetAllocList(envp, -1, STRING_ENCODING_DEFAULT);
+   }
+
    pid = fork();
 
    if (pid == -1) {
       Warning("Unable to fork: %s.\n\n", strerror(errno));
    } else if (pid == 0) {
+      static const char shellPath[] = "/bin/sh";
+      char *args[] = { "sh", "-c", cmdCurrent, NULL };
 
       /*
        * Child
        */
 
-      execl("/bin/sh", "sh", "-c", cmdCurrent, (char *)NULL);
+      if (NULL != envpCurrent) {
+         execve(shellPath, args, envpCurrent);
+      } else  {
+         execv(shellPath, args);
+      }
 
       /* Failure */
       Panic("Unable to execute the \"%s\" shell command: %s.\n\n",
-            cmdCurrent, strerror(errno));
+            cmd, strerror(errno));
    }
 
    /*
@@ -644,6 +663,7 @@ ProcMgrStartProcess(char const *cmd)            // IN: UTF-8 encoded cmd
     */
 
    free(cmdCurrent);
+   Unicode_FreeList(envpCurrent, -1);
    return pid;
 }
 
@@ -732,7 +752,7 @@ ProcMgrWaitForProcCompletion(pid_t pid,                 // IN
 
 ProcMgr_AsyncProc *
 ProcMgr_ExecAsync(char const *cmd,                 // IN: UTF-8 command line
-                  ProcMgr_ProcArgs *userArgs)      // IN: Unused
+                  ProcMgr_ProcArgs *userArgs)      // IN: optional
 {
    ProcMgr_AsyncProc *asyncProc = NULL;
    pid_t pid;
@@ -799,7 +819,7 @@ ProcMgr_ExecAsync(char const *cmd,                 // IN: UTF-8 command line
        * Only run the program if we have not already experienced a failure.
        */
       if (status) {
-         childPid = ProcMgrStartProcess(cmd);
+         childPid = ProcMgrStartProcess(cmd, userArgs ? userArgs->envp : NULL);
          status = childPid != -1;
       }
 
index a961653d14b18a3bce8a16ab876b70e6f54291d6..b7523bf309dba7b7f87077dadb693287103170af 100644 (file)
@@ -77,6 +77,7 @@
 #include "codeset.h"
 #include "posix.h"
 #include "unicode.h"
+#include "hashTable.h"
 
 #if defined(linux) || defined(_WIN32)
 #include "netutil.h"
@@ -144,6 +145,18 @@ static Bool allowConsoleUserOps = FALSE;
 static VixToolsReportProgramDoneProcType reportProgramDoneProc = NULL;
 static void *reportProgramDoneData = NULL;
 
+#ifndef _WIN32
+typedef struct VixToolsEnvironmentTableIterator {
+   char **envp;
+   size_t pos;
+} VixToolsEnvironmentTableIterator;
+
+/*
+ * Stores the environment variables to use when executing guest applications.
+ */
+static HashTable *userEnvironmentTable = NULL;
+#endif
+
 static VixError VixToolsGetFileInfo(VixCommandRequestHeader *requestMsg,
                                     char **result);
 
@@ -247,6 +260,17 @@ static VixError VixToolsDoesUsernameMatchCurrentUser(const char *username);
 
 static Bool VixToolsPidRefersToThisProcess(ProcMgr_Pid pid);
 
+#ifndef _WIN32
+static void VixToolsBuildUserEnvironmentTable(const char * const *envp);
+
+static char **VixToolsEnvironmentTableToEnvp(const HashTable *envTable);
+
+static int VixToolsEnvironmentTableEntryToEnvpEntry(const char *key, void *value,
+                                                    void *clientData);
+
+static void VixToolsFreeEnvp(char **envp);
+#endif
+
 
 /*
  *-----------------------------------------------------------------------------
@@ -265,6 +289,7 @@ static Bool VixToolsPidRefersToThisProcess(ProcMgr_Pid pid);
 
 VixError
 VixTools_Initialize(Bool thisProcessRunsAsRootParam,                                // IN
+                    const char * const *originalEnvp,                               // IN
                     VixToolsReportProgramDoneProcType reportProgramDoneProcParam,   // IN
                     void *clientData)                                               // IN
 {
@@ -274,10 +299,197 @@ VixTools_Initialize(Bool thisProcessRunsAsRootParam,
    reportProgramDoneProc = reportProgramDoneProcParam;
    reportProgramDoneData = clientData;
 
+#ifndef _WIN32
+   VixToolsBuildUserEnvironmentTable(originalEnvp);
+#endif
+
    return(err);
 } // VixTools_Initialize
 
 
+#ifndef _WIN32
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VixToolsBuildUserEnvironmentTable --
+ *
+ *      Takes an array of strings of the form "<key>=<value>" storing the
+ *      environment variables (as per environ(7)) that should be used when
+ *      running programs, and populates the hash table with them.
+ *
+ *      If 'envp' is NULL, skip creating the user environment table, so that
+ *      we just use the current environment.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      May initialize the global userEnvironmentTable.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+VixToolsBuildUserEnvironmentTable(const char * const *envp)   // IN: optional
+{
+   if (NULL == envp) {
+      ASSERT(NULL == userEnvironmentTable);
+      return;
+   }
+
+   if (NULL == userEnvironmentTable) {
+      userEnvironmentTable = HashTable_Alloc(64,  // buckets (power of 2)
+                                             HASH_STRING_KEY | HASH_FLAG_COPYKEY,
+                                             free); // freeFn for the values
+   } else {
+      /*
+       * If we're being reinitialized, we can just clear the table and
+       * load the new values into it. They shouldn't have changed, but
+       * in case they ever do this will cover it.
+       */
+      HashTable_Clear(userEnvironmentTable);
+   }
+
+   for (; NULL != *envp; envp++) {
+      char *name;
+      char *value;
+      char *whereToSplit;
+      size_t nameLen;
+
+      whereToSplit = strchr(*envp, '=');
+      if (NULL == whereToSplit) {
+         /* Our code generated this list, so this shouldn't happen. */
+         ASSERT(0);
+         continue;
+      }
+
+      nameLen = whereToSplit - *envp;
+      name = Util_SafeMalloc(nameLen + 1);
+      memcpy(name, *envp, nameLen);
+      name[nameLen] = '\0';
+
+      whereToSplit++;   // skip over '='
+
+      value = Util_SafeStrdup(whereToSplit);
+
+      HashTable_Insert(userEnvironmentTable, name, value);
+      DEBUG_ONLY(value = NULL;)  // the hash table now owns 'value'
+
+      free(name);
+      DEBUG_ONLY(name = NULL;)
+   }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VixToolsEnvironmentTableToEnvp --
+ *
+ *      Take a hash table storing environment variables names and values and
+ *      build an array out of them.
+ *
+ * Results:
+ *      char ** - envp array as per environ(7). Must be freed using
+ *      VixToolsFreeEnvp
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static char **
+VixToolsEnvironmentTableToEnvp(const HashTable *envTable)   // IN
+{
+   char **envp;
+
+   if (NULL != envTable) {
+      VixToolsEnvironmentTableIterator itr;
+      size_t numEntries = HashTable_GetNumElements(envTable);
+
+      itr.envp = envp = Util_SafeMalloc((numEntries + 1) * sizeof *envp);
+      itr.pos = 0;
+
+      HashTable_ForEach(envTable, VixToolsEnvironmentTableEntryToEnvpEntry, &itr);
+
+      ASSERT(numEntries == itr.pos);
+
+      envp[numEntries] = NULL;
+   } else {
+      envp = NULL;
+   }
+
+   return envp;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VixToolsEnvironmentTableEntryToEnvpEntry --
+ *
+ *      Callback for HashTable_ForEach(). Gets called for each entry in an
+ *      environment table, converting the key (environment variable name) and
+ *      value (environment variable value) into a string of the form
+ *      "<key>=<value>" and adding that to the envp array passed in with the
+ *      VixToolsEnvironmentTableIterator client data.
+ *
+ * Results:
+ *      int - always 0
+ *
+ * Side effects:
+ *      Sets one entry in the envp.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VixToolsEnvironmentTableEntryToEnvpEntry(const char *key,     // IN
+                                         void *value,         // IN
+                                         void *clientData)    // IN/OUT
+{
+   VixToolsEnvironmentTableIterator *itr = clientData;
+
+   itr->envp[itr->pos++] = Str_SafeAsprintf(NULL, "%s=%s", key, (char *)value);
+
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VixToolsFreeEnvp --
+ *
+ *      Free's an array of strings where both the strings and the array
+ *      were heap allocated.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+VixToolsFreeEnvp(char **envp)   // IN
+{
+   if (NULL != envp) {
+      char **itr;
+
+      for (itr = envp; NULL != *itr; itr++) {
+         free(*itr);
+      }
+
+      free(envp);
+   }
+}
+#endif  // #ifndef _WIN32
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -449,9 +661,9 @@ VixToolsRunProgramImpl(char *requestName,      // IN
    char *stopProgramFileName;
    Bool programExists;
    Bool programIsExecutable;
+   ProcMgr_ProcArgs procArgs;
 #if defined(_WIN32)
    Bool forcedRoot = FALSE;
-   ProcMgr_ProcArgs procArgs;
    STARTUPINFO si;
 #endif
 #if defined(VMTOOLS_USE_GLIB)
@@ -551,15 +763,19 @@ VixToolsRunProgramImpl(char *requestName,      // IN
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = (VIX_RUNPROGRAM_ACTIVATE_WINDOW & runProgramOptions)
                      ? SW_SHOWNORMAL : SW_MINIMIZE;
-   asyncState->procState = ProcMgr_ExecAsync(fullCommandLine, &procArgs);
 #else
-   asyncState->procState = ProcMgr_ExecAsync(fullCommandLine, NULL);
+   procArgs.envp = VixToolsEnvironmentTableToEnvp(userEnvironmentTable);
 #endif
 
+   asyncState->procState = ProcMgr_ExecAsync(fullCommandLine, &procArgs);
+
 #if defined(_WIN32)
    if (forcedRoot) {
       Impersonate_UnforceRoot();
    }
+#else
+   VixToolsFreeEnvp(procArgs.envp);
+   DEBUG_ONLY(procArgs.envp = NULL;)
 #endif
 
    if (NULL == asyncState->procState) {
@@ -1718,6 +1934,23 @@ VixToolsReadVariable(VixCommandRequestHeader *requestMsg,   // IN
        * Alwasy get environment variable for the current user, even if the
        * current user is root/administrator
        */
+#ifndef _WIN32
+      /*
+       * If we are maintaining our own set of environment variables
+       * because the application we're running from changed the user's
+       * environment, then we should be reading from that.
+       */
+      if (NULL != userEnvironmentTable) {
+         if (HashTable_Lookup(userEnvironmentTable, valueName,
+                              (void **) &value)) {
+            value = Util_SafeStrdup(value);
+         } else {
+            value = Util_SafeStrdup("");
+         }
+         break;
+      }
+#endif
+
       value = System_GetEnv(FALSE, valueName);
       if (NULL == value) {
          value = Util_SafeStrdup("");
@@ -1806,7 +2039,25 @@ VixToolsWriteVariable(VixCommandRequestHeader *requestMsg)   // IN
       result = System_SetEnv(FALSE, valueName, value);
       if (0 != result) {
          err = FoundryToolsDaemon_TranslateSystemErr();
+         goto abort;
       }
+
+#ifndef _WIN32
+      /*
+       * We need to make sure that this change is reflected in the table of
+       * environment variables we use when launching programs. This is so if a
+       * a user sets LD_LIBRARY_PATH with WriteVariable, and then calls
+       * RunProgramInGuest, that program will see the new value.
+       */
+      if (NULL != userEnvironmentTable) {
+         /*
+          * The hash table will make a copy of valueName, but we have to supply
+          * a deep copy of the value.
+          */
+         HashTable_ReplaceOrInsert(userEnvironmentTable, valueName,
+                                   Util_SafeStrdup(value));
+      }
+#endif
       break;
 
    case VIX_GUEST_CONFIG:
@@ -2486,9 +2737,9 @@ VixToolsRunScript(VixCommandRequestHeader *requestMsg,  // IN
    static char resultBuffer[32];
    VixMsgRunScriptRequest *scriptRequest;
    const char *interpreterFlags = "";
+   ProcMgr_ProcArgs procArgs;
 #if defined(_WIN32)
    Bool forcedRoot = FALSE;
-   ProcMgr_ProcArgs procArgs;
 #endif
 #if defined(VMTOOLS_USE_GLIB)
    GSource *timer;
@@ -2673,15 +2924,19 @@ if (0 == *interpreterName) {
    memset(&procArgs, 0, sizeof procArgs);
    procArgs.hToken = (PROCESS_CREATOR_USER_TOKEN == userToken) ? NULL : userToken;
    procArgs.bInheritHandles = TRUE;
-   asyncState->procState = ProcMgr_ExecAsync(fullCommandLine, &procArgs);
 #else
-   asyncState->procState = ProcMgr_ExecAsync(fullCommandLine, NULL);
+   procArgs.envp = VixToolsEnvironmentTableToEnvp(userEnvironmentTable);
 #endif
 
+   asyncState->procState = ProcMgr_ExecAsync(fullCommandLine, &procArgs);
+
 #if defined(_WIN32)
    if (forcedRoot) {
       Impersonate_UnforceRoot();
    }
+#else
+   VixToolsFreeEnvp(procArgs.envp);
+   DEBUG_ONLY(procArgs.envp = NULL;)
 #endif
 
    if (NULL == asyncState->procState) {
@@ -4376,5 +4631,3 @@ VixToolsEnableStaticOnPrimary(const char *ipAddr,       // IN
    return ret;
 }
 #endif
-
-
index dab5a57145a1142a97f4127a99ef0553a5bf5c2c..e72af25b09d989fb0c24e6a58c292f33bb32e4ca 100644 (file)
@@ -446,7 +446,14 @@ void
 FoundryToolsDaemon_Initialize(ToolsAppCtx *ctx)
 {
    thisProcessRunsAsRoot = (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) == 0);
+
+   /*
+    * TODO: Add the original/native environment (envp) to ToolsAppContext so
+    * we can know what the environment variables were before the loader scripts
+    * changed them.
+    */
    (void) VixTools_Initialize(thisProcessRunsAsRoot,
+                              NULL,   // envp
                               ToolsDaemonTcloReportProgramCompleted,
                               ctx);
 
@@ -477,10 +484,11 @@ FoundryToolsDaemon_Initialize(ToolsAppCtx *ctx)
  */
 
 void
-FoundryToolsDaemon_RegisterRoutines(RpcIn *in,                    // IN
-                                    GuestApp_Dict **confDictRef,  // IN
-                                    DblLnkLst_Links *eventQueue,  // IN
-                                    Bool runAsRoot)               // IN
+FoundryToolsDaemon_RegisterRoutines(RpcIn *in,                        // IN
+                                    GuestApp_Dict **confDictRef,      // IN
+                                    DblLnkLst_Links *eventQueue,      // IN
+                                    const char * const *orginalEnvp,  // IN
+                                    Bool runAsRoot)                   // IN
 {
    static Bool inited = FALSE;
 #if defined(linux) || defined(_WIN32)
@@ -495,6 +503,7 @@ FoundryToolsDaemon_RegisterRoutines(RpcIn *in,                    // IN
    globalEventQueue = eventQueue;
 
    (void) VixTools_Initialize(thisProcessRunsAsRoot,
+                              orginalEnvp,
                               ToolsDaemonTcloReportProgramCompleted,
                               NULL);
 
index 5b0fc2acc6665b8461a58f803cf57f8d2acae071..962395826cdcb7a16848d0384cd387e5750a6bfd 100644 (file)
@@ -45,6 +45,7 @@ FoundryToolsDaemon_Initialize(ToolsAppCtx *ctx);
 void FoundryToolsDaemon_RegisterRoutines(RpcIn *in, 
                                          GuestApp_Dict **confDictRef, 
                                          DblLnkLst_Links *eventQueue,
+                                         const char * const *originalEnvp,
                                          Bool runAsRoot);
 /* There isn't an _UnregisterRoutines yet. */
 
index d4515be15f76a01cb5c6cc3e52db13c0e59671d2..cc774d563b9dac3491e567b7d8ab7723e8a15164 100644 (file)
@@ -58,6 +58,7 @@ extern "C" {
 #include "unity.h"
 #include "ghIntegration.h"
 #include "resolution.h"
+#include "system.h"
 
 #include "vm_atomic.h"
 #include "hostinfo.h"
@@ -740,8 +741,11 @@ VMwareUserConfFileLoop(void *clientData) // IN
  *
  *-----------------------------------------------------------------------------
  */
+
 int
-main(int argc, char *argv[])
+main(int argc,         // IN
+     char *argv[],     // IN
+     char *envp[])     // IN
 {
    struct sigaction olds[ARRAYSIZE(gSignals)];
    int index;
@@ -953,10 +957,29 @@ main(int argc, char *argv[])
 
 #if !defined(N_PLAT_NLM) && !defined(sun)
    {
+      const char **nativeEnvp;
+      char **utf8NativeEnvp;
+
+      /*
+       * Determine our pre-VMware wrapper native environment and pass that to
+       * Foundry so it can spawn applications.
+       */
+
+      nativeEnvp = System_GetNativeEnviron(const_cast<const char **>(envp));
+
+      /* Foundry takes its strings UTF-8. */
+      utf8NativeEnvp = Unicode_AllocList(const_cast<char **>(nativeEnvp),
+                                         -1,  // nativeEnvp is NULL terminated
+                                         STRING_ENCODING_DEFAULT);
+
       FoundryToolsDaemon_RegisterRoutines(gRpcIn,
                                           &confDict,
                                           gEventQueue,
+                                          utf8NativeEnvp,
                                           FALSE);
+
+      Unicode_FreeList(utf8NativeEnvp, -1);
+      System_FreeNativeEnviron(nativeEnvp);
    }
 #endif