RTDECL(int) RTPathTemp(char *pszPath, size_t cchPath) { /* * Try get it from the environment first. */ static const char * const s_apszVars[] = { "IPRT_TMPDIR" #if defined(RT_OS_WINDOWS) , "TMP", "TEMP", "USERPROFILE" #elif defined(RT_OS_OS2) , "TMP", "TEMP", "TMPDIR" #else , "TMPDIR" #endif }; for (size_t iVar = 0; iVar < RT_ELEMENTS(s_apszVars); iVar++) { int rc = RTEnvGetEx(RTENV_DEFAULT, s_apszVars[iVar], pszPath, cchPath, NULL); if (rc != VERR_ENV_VAR_NOT_FOUND) return rc; } /* * Here we should use some sane system default, instead we just use * the typical unix temp dir for now. */ /** @todo Windows should default to the windows directory, see GetTempPath. * Some unixes has path.h and _PATH_TMP. There is also a question about * whether /var/tmp wouldn't be a better place... */ if (cchPath < sizeof("/tmp") ) return VERR_BUFFER_OVERFLOW; memcpy(pszPath, "/tmp", sizeof("/tmp")); return VINF_SUCCESS; }
RTR3DECL(int) RTHttpUseSystemProxySettings(RTHTTP hHttp) { PRTHTTPINTERNAL pHttpInt = hHttp; RTHTTP_VALID_RETURN(pHttpInt); /* * Very limited right now, just enought to make it work for ourselves. */ char szProxy[_1K]; int rc = RTEnvGetEx(RTENV_DEFAULT, "http_proxy", szProxy, sizeof(szProxy), NULL); if (RT_SUCCESS(rc)) { int rcCurl; if (!strncmp(szProxy, RT_STR_TUPLE("http://"))) { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXYPORT, 80); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; } else { rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]); if (CURL_FAILED(rcCurl)) return VERR_INVALID_PARAMETER; } } else if (rc == VERR_ENV_VAR_NOT_FOUND) rc = VINF_SUCCESS; return rc; }
int GetVBoxUserHomeDirectory(char *aDir, size_t aDirLen) { AssertReturn(aDir, VERR_INVALID_POINTER); AssertReturn(aDirLen > 0, VERR_BUFFER_OVERFLOW); /* start with null */ *aDir = 0; char szTmp[RTPATH_MAX]; int vrc = RTEnvGetEx(RTENV_DEFAULT, "VBOX_USER_HOME", szTmp, sizeof(szTmp), NULL); if (RT_SUCCESS(vrc) || vrc == VERR_ENV_VAR_NOT_FOUND) { if (RT_SUCCESS(vrc)) { /* get the full path name */ vrc = RTPathAbs(szTmp, aDir, aDirLen); } else { /* compose the config directory (full path) */ /** @todo r=bird: RTPathUserHome doesn't necessarily return a full (abs) path * like the comment above seems to indicate. */ vrc = RTPathUserHome(aDir, aDirLen); if (RT_SUCCESS(vrc)) vrc = RTPathAppend(aDir, aDirLen, VBOX_USER_HOME_SUFFIX); } /* ensure the home directory exists */ if (RT_SUCCESS(vrc)) if (!RTDirExists(aDir)) vrc = RTDirCreateFullPath(aDir, 0700); } return vrc; }
KHLP_DECL(int) kHlpGetEnv(const char *pszVar, char *pszVal, KSIZE cchVal) { int rc = RTEnvGetEx(RTENV_DEFAULT, pszVar, pszVal, cchVal, NULL); switch (rc) { case VINF_SUCCESS: return 0; case VERR_ENV_VAR_NOT_FOUND: return KERR_ENVVAR_NOT_FOUND; case VERR_BUFFER_OVERFLOW: return KERR_BUFFER_OVERFLOW; default: AssertMsgFailedReturn(("%Rrc\n", rc), rc); } }
/** * Init once for the path conversion code. * * @returns IPRT status code. * @param pvUser1 Unused. * @param pvUser2 Unused. */ static DECLCALLBACK(int32_t) rtPathConvInitOnce(void *pvUser) { /* * Read the environment variable, no mercy on misconfigs here except that * empty values are quietly ignored. (We use a temp buffer for stripping.) */ char *pszEnvValue = NULL; char szEnvValue[sizeof(g_szFsCodeset)]; int rc = RTEnvGetEx(RTENV_DEFAULT, RTPATH_CODESET_ENV_VAR, szEnvValue, sizeof(szEnvValue), NULL); if (rc != VERR_ENV_VAR_NOT_FOUND && RT_FAILURE(rc)) return rc; if (RT_SUCCESS(rc)) pszEnvValue = RTStrStrip(szEnvValue); if (pszEnvValue && *pszEnvValue) { g_fPassthruUtf8 = rtPathConvInitIsUtf8(pszEnvValue); g_enmFsToUtf8Idx = RTSTRICONV_FS_TO_UTF8; g_enmUtf8ToFsIdx = RTSTRICONV_UTF8_TO_FS; strcpy(g_szFsCodeset, pszEnvValue); } else { const char *pszCodeset = rtStrGetLocaleCodeset(); size_t cchCodeset = pszCodeset ? strlen(pszCodeset) : sizeof(g_szFsCodeset); if (cchCodeset >= sizeof(g_szFsCodeset)) /* This shouldn't happen, but we'll manage. */ g_szFsCodeset[0] = '\0'; else { memcpy(g_szFsCodeset, pszCodeset, cchCodeset + 1); pszCodeset = g_szFsCodeset; } g_fPassthruUtf8 = rtPathConvInitIsUtf8(pszCodeset); g_enmFsToUtf8Idx = RTSTRICONV_LOCALE_TO_UTF8; g_enmUtf8ToFsIdx = RTSTRICONV_UTF8_TO_LOCALE; } NOREF(pvUser); return VINF_SUCCESS; }
/** * Initializes the address space parts of DBGF. * * @returns VBox status code. * @param pUVM The user mode VM handle. */ int dbgfR3AsInit(PUVM pUVM) { Assert(pUVM->pVM); /* * Create the semaphore. */ int rc = RTSemRWCreate(&pUVM->dbgf.s.hAsDbLock); AssertRCReturn(rc, rc); /* * Create the debugging config instance and set it up, defaulting to * deferred loading in order to keep things fast. */ rc = RTDbgCfgCreate(&pUVM->dbgf.s.hDbgCfg, NULL, true /*fNativePaths*/); AssertRCReturn(rc, rc); rc = RTDbgCfgChangeUInt(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_FLAGS, RTDBGCFGOP_PREPEND, RTDBGCFG_FLAGS_DEFERRED); AssertRCReturn(rc, rc); static struct { RTDBGCFGPROP enmProp; const char *pszEnvName; const char *pszCfgName; } const s_aProps[] = { { RTDBGCFGPROP_FLAGS, "VBOXDBG_FLAGS", "Flags" }, { RTDBGCFGPROP_PATH, "VBOXDBG_PATH", "Path" }, { RTDBGCFGPROP_SUFFIXES, "VBOXDBG_SUFFIXES", "Suffixes" }, { RTDBGCFGPROP_SRC_PATH, "VBOXDBG_SRC_PATH", "SrcPath" }, }; PCFGMNODE pCfgDbgf = CFGMR3GetChild(CFGMR3GetRootU(pUVM), "/DBGF"); for (unsigned i = 0; i < RT_ELEMENTS(s_aProps); i++) { char szEnvValue[8192]; rc = RTEnvGetEx(RTENV_DEFAULT, s_aProps[i].pszEnvName, szEnvValue, sizeof(szEnvValue), NULL); if (RT_SUCCESS(rc)) { rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, szEnvValue); if (RT_FAILURE(rc)) return VMR3SetError(pUVM, rc, RT_SRC_POS, "DBGF Config Error: %s=%s -> %Rrc", s_aProps[i].pszEnvName, szEnvValue, rc); } else if (rc != VERR_ENV_VAR_NOT_FOUND) return VMR3SetError(pUVM, rc, RT_SRC_POS, "DBGF Config Error: Error querying env.var. %s: %Rrc", s_aProps[i].pszEnvName, rc); char *pszCfgValue; rc = CFGMR3QueryStringAllocDef(pCfgDbgf, s_aProps[i].pszCfgName, &pszCfgValue, NULL); if (RT_FAILURE(rc)) return VMR3SetError(pUVM, rc, RT_SRC_POS, "DBGF Config Error: Querying /DBGF/%s -> %Rrc", s_aProps[i].pszCfgName, rc); if (pszCfgValue) { rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, pszCfgValue); if (RT_FAILURE(rc)) return VMR3SetError(pUVM, rc, RT_SRC_POS, "DBGF Config Error: /DBGF/%s=%s -> %Rrc", s_aProps[i].pszCfgName, pszCfgValue, rc); } } /* * Prepend the NoArch and VBoxDbgSyms directories to the path. */ char szPath[RTPATH_MAX]; rc = RTPathAppPrivateNoArch(szPath, sizeof(szPath)); AssertRCReturn(rc, rc); #ifdef RT_OS_DARWIN rc = RTPathAppend(szPath, sizeof(szPath), "../Resources/VBoxDbgSyms/"); #else rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_PATH, RTDBGCFGOP_PREPEND, szPath); AssertRCReturn(rc, rc); rc = RTPathAppend(szPath, sizeof(szPath), "VBoxDbgSyms/"); #endif AssertRCReturn(rc, rc); rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_PATH, RTDBGCFGOP_PREPEND, szPath); AssertRCReturn(rc, rc); /* * Create the standard address spaces. */ RTDBGAS hDbgAs; rc = RTDbgAsCreate(&hDbgAs, 0, RTGCPTR_MAX, "Global"); AssertRCReturn(rc, rc); rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS); AssertRCReturn(rc, rc); RTDbgAsRetain(hDbgAs); pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_GLOBAL)] = hDbgAs; RTDbgAsRetain(hDbgAs); pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_KERNEL)] = hDbgAs; rc = RTDbgAsCreate(&hDbgAs, 0, RTGCPHYS_MAX, "Physical"); AssertRCReturn(rc, rc); rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS); AssertRCReturn(rc, rc); RTDbgAsRetain(hDbgAs); pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_PHYS)] = hDbgAs; rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "HyperRawMode"); AssertRCReturn(rc, rc); rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS); AssertRCReturn(rc, rc); RTDbgAsRetain(hDbgAs); pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC)] = hDbgAs; RTDbgAsRetain(hDbgAs); pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC_AND_GC_GLOBAL)] = hDbgAs; rc = RTDbgAsCreate(&hDbgAs, 0, RTR0PTR_MAX, "HyperRing0"); AssertRCReturn(rc, rc); rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS); AssertRCReturn(rc, rc); RTDbgAsRetain(hDbgAs); pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_R0)] = hDbgAs; return VINF_SUCCESS; }
/** * Initializes the COM runtime. * * This method must be called on each thread of the client application that * wants to access COM facilities. The initialization must be performed before * calling any other COM method or attempting to instantiate COM objects. * * On platforms using XPCOM, this method uses the following scheme to search for * XPCOM runtime: * * 1. If the VBOX_APP_HOME environment variable is set, the path it specifies * is used to search XPCOM libraries and components. If this method fails to * initialize XPCOM runtime using this path, it will immediately return a * failure and will NOT check for other paths as described below. * * 2. If VBOX_APP_HOME is not set, this methods tries the following paths in the * given order: * * a) Compiled-in application data directory (as returned by * RTPathAppPrivateArch()) * b) "/usr/lib/virtualbox" (Linux only) * c) "/opt/VirtualBox" (Linux only) * * The first path for which the initialization succeeds will be used. * * On MS COM platforms, the COM runtime is provided by the system and does not * need to be searched for. * * Once the COM subsystem is no longer necessary on a given thread, Shutdown() * must be called to free resources allocated for it. Note that a thread may * call Initialize() several times but for each of tese calls there must be a * corresponding Shutdown() call. * * @return S_OK on success and a COM result code in case of failure. */ HRESULT Initialize(bool fGui) { HRESULT rc = E_FAIL; #if !defined(VBOX_WITH_XPCOM) /* * We initialize COM in GUI thread in STA, to be compliant with QT and * OLE requirments (for example to allow D&D), while other threads * initialized in regular MTA. To allow fast proxyless access from * GUI thread to COM objects, we explicitly provide our COM objects * with free threaded marshaller. * !!!!! Please think twice before touching this code !!!!! */ DWORD flags = fGui ? COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY : COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE | COINIT_SPEED_OVER_MEMORY; rc = CoInitializeEx(NULL, flags); /* the overall result must be either S_OK or S_FALSE (S_FALSE means * "already initialized using the same apartment model") */ AssertMsg(rc == S_OK || rc == S_FALSE, ("rc=%08X\n", rc)); /* To be flow compatible with the XPCOM case, we return here if this isn't * the main thread or if it isn't its first initialization call. * Note! CoInitializeEx and CoUninitialize does it's own reference * counting, so this exercise is entirely for the EventQueue init. */ bool fRc; RTTHREAD hSelf = RTThreadSelf(); if (hSelf != NIL_RTTHREAD) ASMAtomicCmpXchgHandle(&gCOMMainThread, hSelf, NIL_RTTHREAD, fRc); else fRc = false; if (fGui) Assert(RTThreadIsMain(hSelf)); if (!fRc) { if ( gCOMMainThread == hSelf && SUCCEEDED(rc)) gCOMMainInitCount++; AssertComRC(rc); return rc; } Assert(RTThreadIsMain(hSelf)); /* this is the first main thread initialization */ Assert(gCOMMainInitCount == 0); if (SUCCEEDED(rc)) gCOMMainInitCount = 1; #else /* !defined (VBOX_WITH_XPCOM) */ /* Unused here */ NOREF(fGui); if (ASMAtomicXchgBool(&gIsXPCOMInitialized, true) == true) { /* XPCOM is already initialized on the main thread, no special * initialization is necessary on additional threads. Just increase * the init counter if it's a main thread again (to correctly support * nested calls to Initialize()/Shutdown() for compatibility with * Win32). */ nsCOMPtr<nsIEventQueue> eventQ; rc = NS_GetMainEventQ(getter_AddRefs(eventQ)); if (NS_SUCCEEDED(rc)) { PRBool isOnMainThread = PR_FALSE; rc = eventQ->IsOnCurrentThread(&isOnMainThread); if (NS_SUCCEEDED(rc) && isOnMainThread) ++gXPCOMInitCount; } AssertComRC(rc); return rc; } Assert(RTThreadIsMain(RTThreadSelf())); /* this is the first initialization */ gXPCOMInitCount = 1; bool const fInitEventQueues = true; /* prepare paths for registry files */ char szCompReg[RTPATH_MAX]; char szXptiDat[RTPATH_MAX]; int vrc = GetVBoxUserHomeDirectory(szCompReg, sizeof(szCompReg)); AssertRCReturn(vrc, NS_ERROR_FAILURE); strcpy(szXptiDat, szCompReg); vrc = RTPathAppend(szCompReg, sizeof(szCompReg), "compreg.dat"); AssertRCReturn(vrc, NS_ERROR_FAILURE); vrc = RTPathAppend(szXptiDat, sizeof(szXptiDat), "xpti.dat"); AssertRCReturn(vrc, NS_ERROR_FAILURE); LogFlowFunc(("component registry : \"%s\"\n", szCompReg)); LogFlowFunc(("XPTI data file : \"%s\"\n", szXptiDat)); #if defined (XPCOM_GLUE) XPCOMGlueStartup(nsnull); #endif static const char *kAppPathsToProbe[] = { NULL, /* 0: will use VBOX_APP_HOME */ NULL, /* 1: will try RTPathAppPrivateArch() */ #ifdef RT_OS_LINUX "/usr/lib/virtualbox", "/opt/VirtualBox", #elif RT_OS_SOLARIS "/opt/VirtualBox/amd64", "/opt/VirtualBox/i386", #elif RT_OS_DARWIN "/Application/VirtualBox.app/Contents/MacOS", #endif }; /* Find out the directory where VirtualBox binaries are located */ for (size_t i = 0; i < RT_ELEMENTS(kAppPathsToProbe); ++ i) { char szAppHomeDir[RTPATH_MAX]; if (i == 0) { /* Use VBOX_APP_HOME if present */ vrc = RTEnvGetEx(RTENV_DEFAULT, "VBOX_APP_HOME", szAppHomeDir, sizeof(szAppHomeDir), NULL); if (vrc == VERR_ENV_VAR_NOT_FOUND) continue; AssertRC(vrc); } else if (i == 1) { /* Use RTPathAppPrivateArch() first */ vrc = RTPathAppPrivateArch(szAppHomeDir, sizeof(szAppHomeDir)); AssertRC(vrc); } else { /* Iterate over all other paths */ szAppHomeDir[RTPATH_MAX - 1] = '\0'; strncpy(szAppHomeDir, kAppPathsToProbe[i], RTPATH_MAX - 1); vrc = VINF_SUCCESS; } if (RT_FAILURE(vrc)) { rc = NS_ERROR_FAILURE; continue; } char szCompDir[RTPATH_MAX]; vrc = RTPathAppend(strcpy(szCompDir, szAppHomeDir), sizeof(szCompDir), "components"); if (RT_FAILURE(vrc)) { rc = NS_ERROR_FAILURE; continue; } LogFlowFunc(("component directory : \"%s\"\n", szCompDir)); nsCOMPtr<DirectoryServiceProvider> dsProv; dsProv = new DirectoryServiceProvider(); if (dsProv) rc = dsProv->init(szCompReg, szXptiDat, szCompDir, szAppHomeDir); else rc = NS_ERROR_OUT_OF_MEMORY; if (NS_FAILED(rc)) break; /* Setup the application path for NS_InitXPCOM2. Note that we properly * answer the NS_XPCOM_CURRENT_PROCESS_DIR query in our directory * service provider but it seems to be activated after the directory * service is used for the first time (see the source NS_InitXPCOM2). So * use the same value here to be on the safe side. */ nsCOMPtr <nsIFile> appDir; { char *appDirCP = NULL; vrc = RTStrUtf8ToCurrentCP(&appDirCP, szAppHomeDir); if (RT_SUCCESS(vrc)) { nsCOMPtr<nsILocalFile> file; rc = NS_NewNativeLocalFile(nsEmbedCString(appDirCP), PR_FALSE, getter_AddRefs(file)); if (NS_SUCCEEDED(rc)) appDir = do_QueryInterface(file, &rc); RTStrFree(appDirCP); } else rc = NS_ERROR_FAILURE; } if (NS_FAILED(rc)) break; /* Set VBOX_XPCOM_HOME to the same app path to make XPCOM sources that * still use it instead of the directory service happy */ vrc = RTEnvSetEx(RTENV_DEFAULT, "VBOX_XPCOM_HOME", szAppHomeDir); AssertRC(vrc); /* Finally, initialize XPCOM */ { nsCOMPtr<nsIServiceManager> serviceManager; rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), appDir, dsProv); if (NS_SUCCEEDED(rc)) { nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager, &rc); if (NS_SUCCEEDED(rc)) { rc = registrar->AutoRegister(nsnull); if (NS_SUCCEEDED(rc)) { /* We succeeded, stop probing paths */ LogFlowFunc(("Succeeded.\n")); break; } } } } /* clean up before the new try */ rc = NS_ShutdownXPCOM(nsnull); if (i == 0) { /* We failed with VBOX_APP_HOME, don't probe other paths */ break; } } #endif /* !defined (VBOX_WITH_XPCOM) */ // for both COM and XPCOM, we only get here if this is the main thread; // only then initialize the autolock system (AutoLock.cpp) Assert(RTThreadIsMain(RTThreadSelf())); util::InitAutoLockSystem(); AssertComRC(rc); /* * Init the main event queue (ASSUMES it cannot fail). */ if (SUCCEEDED(rc)) EventQueue::init(); return rc; }
static int tstRTCreateProcEx6Child(int argc, char **argv) { int rc = RTR3InitExeNoArguments(0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); int cErrors = 0; char szValue[_16K]; /* * Check for the environment variable we've set in the parent process. */ if (argc >= 3 && strcmp(argv[2], "inherit") == 0) { if (!RTEnvExistEx(RTENV_DEFAULT, "testcase-child-6")) { RTStrmPrintf(g_pStdErr, "child6: Env.var. 'testcase-child-6' was not inherited from parent\n"); cErrors++; } } else if (argc >= 3 && strstr(argv[2], "change-record") != NULL) { rc = RTEnvGetEx(RTENV_DEFAULT, "testcase-child-6", szValue, sizeof(szValue), NULL); if (RT_SUCCESS(rc) && strcmp(szValue, "changed")) { RTStrmPrintf(g_pStdErr, "child6: Env.var. 'testcase-child-6'='%s', expected 'changed'.\n", szValue); cErrors++; } else if (RT_FAILURE(rc)) { RTStrmPrintf(g_pStdErr, "child6: RTEnvGetEx(,'testcase-child-6',,) -> %Rrc\n", rc); cErrors++; } } else { if (RTEnvExistEx(RTENV_DEFAULT, "testcase-child-6")) { RTStrmPrintf(g_pStdErr, "child6: Env.var. 'testcase-child-6' was inherited from parent\n"); cErrors++; } } /* * Check the user name if present we didn't inherit from parent. */ if ( argc >= 4 && argv[3][0] != '\0' && strstr(argv[2], "noinherit") != NULL) { static struct { const char *pszVarNm; bool fReq; } const s_aVars[] = { #ifdef RT_OS_WINDOWS { "USERNAME", true }, #else { "LOGNAME", true }, { "USER", false }, #endif }; for (unsigned i = 0; i < RT_ELEMENTS(s_aVars); i++) { rc = RTEnvGetEx(RTENV_DEFAULT, s_aVars[i].pszVarNm, szValue, sizeof(szValue), NULL); if (RT_SUCCESS(rc)) { if (strcmp(szValue, argv[3])) { RTStrmPrintf(g_pStdErr, "child6: env.var. '%s'='%s', expected '%s'\n", s_aVars[i].pszVarNm, szValue, argv[3]); cErrors++; } } else if (rc != VERR_ENV_VAR_NOT_FOUND || s_aVars[i].fReq) { RTStrmPrintf(g_pStdErr, "child6: RTGetEnv('%s') -> %Rrc\n", s_aVars[i].pszVarNm, rc); cErrors++; } } } #if 1 /* For manual testing. */ if (strcmp(argv[2],"noinherit") == 0) //if (strcmp(argv[2],"noinherit-change-record") == 0) { RTENV hEnv; rc = RTEnvClone(&hEnv, RTENV_DEFAULT); if (RT_SUCCESS(rc)) { uint32_t cVars = RTEnvCountEx(hEnv); for (uint32_t i = 0; i < cVars; i++) { char szVarNm[_1K]; rc = RTEnvGetByIndexEx(hEnv, i, szVarNm, sizeof(szVarNm), szValue, sizeof(szValue)); if (RT_SUCCESS(rc)) RTStrmPrintf(g_pStdErr, "child6: #%u: %s=%s\n", i, szVarNm, szValue); else { RTStrmPrintf(g_pStdErr, "child6: #%u: %Rrc\n", i, rc); cErrors++; } } RTEnvDestroy(hEnv); } else { RTStrmPrintf(g_pStdErr, "child6: RTEnvClone failed: %Rrc\n", rc); cErrors++; } } #endif return cErrors == 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }
static void tstRTCreateProcEx6(const char *pszAsUser, const char *pszPassword) { RTTestISub("Profile environment"); const char *apszArgs[5] = { g_szExecName, "--testcase-child-6", "inherit", pszAsUser, NULL }; RTTESTI_CHECK_RC_RETV(RTEnvSetEx(RTENV_DEFAULT, "testcase-child-6", "true"), VINF_SUCCESS); /* Use the process environment first. */ RTPROCESS hProc; RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND }; RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus); /* Use the process environment first with a little change. */ apszArgs[2] = "change-record"; RTENV hEnvChange; RTTESTI_CHECK_RC_RETV(RTEnvCreateChangeRecord(&hEnvChange), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTEnvSetEx(hEnvChange, "testcase-child-6", "changed"), VINF_SUCCESS); int rc; RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, hEnvChange, RTPROC_FLAGS_ENV_CHANGE_RECORD, NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); if (RT_SUCCESS(rc)) { ProcStatus.enmReason = RTPROCEXITREASON_ABEND; ProcStatus.iStatus = -1; RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus); } /* Use profile environment this time. */ apszArgs[2] = "noinherit"; RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, RTPROC_FLAGS_PROFILE, NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); if (RT_SUCCESS(rc)) { ProcStatus.enmReason = RTPROCEXITREASON_ABEND; ProcStatus.iStatus = -1; RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus); } /* Use profile environment this time. */ apszArgs[2] = "noinherit-change-record"; RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, hEnvChange, RTPROC_FLAGS_PROFILE | RTPROC_FLAGS_ENV_CHANGE_RECORD, NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); if (RT_SUCCESS(rc)) { ProcStatus.enmReason = RTPROCEXITREASON_ABEND; ProcStatus.iStatus = -1; RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus); } RTTESTI_CHECK_RC(RTEnvDestroy(hEnvChange), VINF_SUCCESS); /* * Restore the environment and check that the PROFILE flag didn't mess with * the process environment. (Note! The bug may be elsewhere as well.) */ RTTESTI_CHECK_RC(RTEnvUnsetEx(RTENV_DEFAULT, "testcase-child-6"), VINF_SUCCESS); RTENV hEnvCur; RTTESTI_CHECK_RC_RETV(RTEnvClone(&hEnvCur, RTENV_DEFAULT), VINF_SUCCESS); uint32_t cCurrent = RTEnvCountEx(hEnvCur); uint32_t cInitial = RTEnvCountEx(g_hEnvInitial); RTTESTI_CHECK_MSG(cCurrent == cInitial, ("cCurrent=%u cInitial=%u\n", cCurrent, cInitial)); uint32_t cVars1; RTENV hEnv1, hEnv2; const char *pszEnv1, *pszEnv2; if (cCurrent >= cInitial) { hEnv1 = hEnvCur; pszEnv1 = "current"; cVars1 = cCurrent; hEnv2 = g_hEnvInitial; pszEnv2 = "initial"; } else { hEnv2 = hEnvCur; pszEnv2 = "current"; hEnv1 = g_hEnvInitial; pszEnv1 = "initial"; cVars1 = cInitial; } for (uint32_t i = 0; i < cVars1; i++) { char szValue1[_16K]; char szVarNm[_1K]; rc = RTEnvGetByIndexEx(hEnv1, i, szVarNm, sizeof(szVarNm), szValue1, sizeof(szValue1)); if (RT_SUCCESS(rc)) { char szValue2[_16K]; rc = RTEnvGetEx(hEnv2, szVarNm, szValue2, sizeof(szValue2), NULL); if (RT_SUCCESS(rc)) { if (strcmp(szValue1, szValue2) != 0) { RTTestIFailed("Variable '%s' differs", szVarNm); RTTestIFailureDetails("%s: '%s'\n" "%s: '%s'\n", pszEnv1, szValue1, pszEnv2, szValue2); } } else RTTestIFailed("RTEnvGetEx(%s,%s,,) failed: %Rrc", pszEnv2, szVarNm, rc); } else RTTestIFailed("RTEnvGetByIndexEx(%s,%u,,,,) failed: %Rrc", pszEnv1, i, rc); } }