RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone) { /* * Validate input and figure out how many variable to clone and where to get them. */ bool fCaseSensitive = true; bool fPutEnvBlock = false; size_t cVars; const char * const *papszEnv; #ifdef RTENV_HAVE_WENVIRON PCRTUTF16 const * papwszEnv; #endif PRTENVINTERNAL pIntEnvToClone; AssertPtrReturn(pEnv, VERR_INVALID_POINTER); if (EnvToClone == RTENV_DEFAULT) { cVars = 0; pIntEnvToClone = NULL; #ifdef RTENV_HAVE_WENVIRON papszEnv = NULL; papwszEnv = (PCRTUTF16 * const)_wenviron; if (!papwszEnv) { _wgetenv(L"Path"); /* Force the CRT to initalize it. */ papwszEnv = (PCRTUTF16 * const)_wenviron; } if (papwszEnv) while (papwszEnv[cVars]) cVars++; #else papszEnv = rtEnvDefault(); if (papszEnv) while (papszEnv[cVars]) cVars++; #endif #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) /* DOS systems was case insensitive. A prime example is the 'Path' variable on windows which turns into the 'PATH' variable. */ fCaseSensitive = false; #endif } else { pIntEnvToClone = EnvToClone; AssertPtrReturn(pIntEnvToClone, VERR_INVALID_HANDLE); AssertReturn(pIntEnvToClone->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); RTENV_LOCK(pIntEnvToClone); fPutEnvBlock = pIntEnvToClone->fPutEnvBlock; papszEnv = pIntEnvToClone->papszEnv; cVars = pIntEnvToClone->cVars; } /* * Create the duplicate. */ PRTENVINTERNAL pIntEnv; int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, fCaseSensitive, fPutEnvBlock); if (RT_SUCCESS(rc)) { pIntEnv->cVars = cVars; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; if (EnvToClone == RTENV_DEFAULT) { /* ASSUMES the default environment is in the current codepage. */ size_t iDst = 0; for (size_t iSrc = 0; iSrc < cVars; iSrc++) { #ifdef RTENV_HAVE_WENVIRON int rc2 = RTUtf16ToUtf8(papwszEnv[iSrc], &pIntEnv->papszEnv[iDst]); #else int rc2 = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iDst], papszEnv[iSrc]); #endif if (RT_SUCCESS(rc2)) { /* Make sure it contains an '='. */ iDst++; if (strchr(pIntEnv->papszEnv[iDst - 1], '=')) continue; rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst - 1], "="); if (RT_SUCCESS(rc2)) continue; } else if (rc2 == VERR_NO_TRANSLATION) { rc = VWRN_ENV_NOT_FULLY_TRANSLATED; continue; } /* failed fatally. */ pIntEnv->cVars = iDst; RTEnvDestroy(pIntEnv); return rc2; } pIntEnv->cVars = iDst; } else { for (size_t iVar = 0; iVar < cVars; iVar++) { char *pszVar = RTStrDup(papszEnv[iVar]); if (RT_UNLIKELY(!pszVar)) { RTENV_UNLOCK(pIntEnvToClone); pIntEnv->cVars = iVar; RTEnvDestroy(pIntEnv); return VERR_NO_STR_MEMORY; } pIntEnv->papszEnv[iVar] = pszVar; } } /* done */ *pEnv = pIntEnv; } if (pIntEnvToClone) RTENV_UNLOCK(pIntEnvToClone); return rc; }
RTDECL(int) RTEnvCreate(PRTENV pEnv) { AssertPtrReturn(pEnv, VERR_INVALID_POINTER); return rtEnvCreate(pEnv, RTENV_GROW_SIZE, true /*fCaseSensitive*/, false /*fPutEnvBlock*/); }
RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone) { /* * Validate input and figure out how many variable to clone and where to get them. */ size_t cVars; const char * const *papszEnv; PRTENVINTERNAL pIntEnvToClone; AssertPtrReturn(pEnv, VERR_INVALID_POINTER); if (EnvToClone == RTENV_DEFAULT) { pIntEnvToClone = NULL; papszEnv = rtEnvDefault(); cVars = 0; if (papszEnv) while (papszEnv[cVars]) cVars++; } else { pIntEnvToClone = EnvToClone; AssertPtrReturn(pIntEnvToClone, VERR_INVALID_HANDLE); AssertReturn(pIntEnvToClone->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); RTENV_LOCK(pIntEnvToClone); papszEnv = pIntEnvToClone->papszEnv; cVars = pIntEnvToClone->cVars; } /* * Create the duplicate. */ PRTENVINTERNAL pIntEnv; int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */); if (RT_SUCCESS(rc)) { pIntEnv->cVars = cVars; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; if (EnvToClone == RTENV_DEFAULT) { /* ASSUMES the default environment is in the current codepage. */ size_t iDst = 0; for (size_t iSrc = 0; iSrc < cVars; iSrc++) { int rc2 = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iDst], papszEnv[iSrc]); if (RT_SUCCESS(rc2)) iDst++; else if (rc2 == VERR_NO_TRANSLATION) rc = VWRN_ENV_NOT_FULLY_TRANSLATED; else { pIntEnv->cVars = iDst; RTEnvDestroy(pIntEnv); return rc2; } } pIntEnv->cVars = iDst; } else { for (size_t iVar = 0; iVar < cVars; iVar++) { char *pszVar = RTStrDup(papszEnv[iVar]); if (RT_UNLIKELY(!pszVar)) { RTENV_UNLOCK(pIntEnvToClone); pIntEnv->cVars = iVar; RTEnvDestroy(pIntEnv); return VERR_NO_STR_MEMORY; } pIntEnv->papszEnv[iVar] = pszVar; } } /* done */ *pEnv = pIntEnv; } if (pIntEnvToClone) RTENV_UNLOCK(pIntEnvToClone); return rc; }
RTDECL(int) RTEnvCloneUtf16Block(PRTENV phEnv, PCRTUTF16 pwszzBlock, uint32_t fFlags) { AssertPtrReturn(pwszzBlock, VERR_INVALID_POINTER); AssertReturn(!fFlags, VERR_INVALID_FLAGS); /* * Count the number of variables in the block. */ uint32_t cVars = 0; PCRTUTF16 pwsz = pwszzBlock; while (*pwsz != '\0') { cVars++; pwsz += RTUtf16Len(pwsz) + 1; AssertReturn(cVars < _256K, VERR_OUT_OF_RANGE); } /* * Create the duplicate. */ PRTENVINTERNAL pIntEnv; int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, false /*fCaseSensitive*/, false /*fPutEnvBlock*/); if (RT_SUCCESS(rc)) { pIntEnv->cVars = cVars; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; size_t iDst = 0; for (pwsz = pwszzBlock; *pwsz != '\0'; pwsz += RTUtf16Len(pwsz) + 1) { int rc2 = RTUtf16ToUtf8(pwsz, &pIntEnv->papszEnv[iDst]); if (RT_SUCCESS(rc2)) { /* Make sure it contains an '='. */ const char *pszEqual = strchr(pIntEnv->papszEnv[iDst], '='); if (!pszEqual) { rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst], "="); if (RT_SUCCESS(rc2)) pszEqual = strchr(pIntEnv->papszEnv[iDst], '='); } if (pszEqual) { /* Check for duplicates, keep the last version. */ const char *pchVar = pIntEnv->papszEnv[iDst]; size_t cchVarNmAndEq = pszEqual - pchVar; for (size_t iDst2 = 0; iDst2 < iDst; iDst2++) if (pIntEnv->pfnCompare(pIntEnv->papszEnv[iDst2], pchVar, cchVarNmAndEq) == 0) { RTStrFree(pIntEnv->papszEnv[iDst2]); pIntEnv->papszEnv[iDst2] = pIntEnv->papszEnv[iDst]; pIntEnv->papszEnv[iDst] = NULL; iDst--; break; } iDst++; continue; } iDst++; } /* failed fatally. */ pIntEnv->cVars = iDst; RTEnvDestroy(pIntEnv); return rc2; } Assert(iDst <= pIntEnv->cVars); pIntEnv->cVars = iDst; /* done */ *phEnv = pIntEnv; } return rc; }
RTDECL(int) RTEnvCreate(PRTENV pEnv) { AssertPtrReturn(pEnv, VERR_INVALID_POINTER); return rtEnvCreate(pEnv, RTENV_GROW_SIZE); }