Changeset 95842 in vbox for trunk/src/VBox
- Timestamp:
- Jul 26, 2022 9:11:14 PM (2 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/Makefile.kmk
r95834 r95842 2260 2260 common/misc/json.cpp \ 2261 2261 common/string/ministring.cpp \ 2262 generic/env-generic.cpp \2263 2262 generic/RTLogWriteStdErr-generic.cpp \ 2264 2263 generic/RTLogWriteStdOut-generic.cpp \ -
trunk/src/VBox/Runtime/VBox/VBoxRTImp.def
r94871 r95842 1004 1004 RTEnvGet 1005 1005 RTEnvGetEx 1006 RTEnvGetExecEnvP1007 1006 RTEnvPut 1008 1007 RTEnvPutEx -
trunk/src/VBox/Runtime/generic/env-generic.cpp
r93115 r95842 41 41 #include "internal/magics.h" 42 42 43 #include <stdlib.h> 44 #if !defined(RT_OS_WINDOWS) 45 # include <unistd.h> 46 #endif 47 #ifdef RT_OS_DARWIN 48 # include <crt_externs.h> 49 #endif 50 #if defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) || defined(RT_OS_OPENBSD) 43 #ifdef RT_OS_WINDOWS 44 # include <iprt/nt/nt.h> 45 #else 46 # include <stdlib.h> 47 # if !defined(RT_OS_WINDOWS) 48 # include <unistd.h> 49 # endif 50 # ifdef RT_OS_DARWIN 51 # include <crt_externs.h> 52 # endif 53 # if defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) || defined(RT_OS_OPENBSD) 51 54 RT_C_DECLS_BEGIN 52 55 extern char **environ; 53 56 RT_C_DECLS_END 57 # endif 54 58 #endif 55 59 … … 66 70 #define RTENV_UNLOCK(pEnvInt) do { } while (0) 67 71 68 /** @def RTENV_HAVE_WENVIRON69 * Indicates that we have a _wenviron variable with UTF-16 strings that we70 * better use instead of the current-cp strings in environ. */71 #if defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)72 # define RTENV_HAVE_WENVIRON 173 #endif74 75 72 /** @def RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API 76 73 * Indicates the RTEnv*Utf8 APIs are implemented. */ … … 78 75 # define RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API 1 79 76 #endif 80 81 77 82 78 /** @def RTENV_ALLOW_EQUAL_FIRST_IN_VAR … … 125 121 126 122 123 #ifndef RT_OS_WINDOWS 127 124 /** 128 125 * Internal worker that resolves the pointer to the default … … 134 131 static const char * const *rtEnvDefault(void) 135 132 { 136 # ifdef RT_OS_DARWIN133 # ifdef RT_OS_DARWIN 137 134 return *(_NSGetEnviron()); 138 # else135 # else 139 136 return environ; 137 # endif 138 } 140 139 #endif 141 }142 140 143 141 … … 254 252 255 253 256 RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone) 257 { 258 /* 259 * Validate input and figure out how many variable to clone and where to get them. 260 */ 254 static int rtEnvCloneDefault(PRTENV phEnv) 255 { 256 #ifdef RTENV_ALLOW_EQUAL_FIRST_IN_VAR 257 bool const fFirstEqual = true; 258 #else 259 bool const fFirstEqual = false; 260 #endif 261 262 #ifdef RT_OS_WINDOWS 263 /* 264 * Lock the PEB, get the process environment. 265 * 266 * On older windows version GetEnviornmentStringsW will not copy the 267 * environment block, but return the pointer stored in the PEB. This 268 * should be safer wrt to concurrent changes. 269 */ 270 PPEB pPeb = RTNtCurrentPeb(); 271 272 RtlAcquirePebLock(); 273 274 /* Count variables in the block: */ 275 size_t cVars = 0; 276 PCRTUTF16 pwszzEnv = pPeb->ProcessParameters ? pPeb->ProcessParameters->Environment : NULL; 277 if (pwszzEnv) 278 { 279 PCRTUTF16 pwsz = pwszzEnv; 280 while (*pwsz) 281 { 282 cVars++; 283 pwsz += RTUtf16Len(pwsz) + 1; 284 } 285 } 286 287 PRTENVINTERNAL pIntEnv; 288 int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, false /*fCaseSensitive*/, false /*fPutEnvBlock*/, fFirstEqual); 289 if (RT_SUCCESS(rc)) 290 { 291 size_t iDst; 292 for (iDst = 0; iDst < cVars && *pwszzEnv; iDst++, pwszzEnv += RTUtf16Len(pwszzEnv) + 1) 293 { 294 int rc2 = RTUtf16ToUtf8(pwszzEnv, &pIntEnv->papszEnv[iDst]); 295 if (RT_SUCCESS(rc2)) 296 { 297 /* Make sure it contains an '='. */ 298 if (strchr(pIntEnv->papszEnv[iDst], '=')) 299 continue; 300 rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst], "="); 301 if (RT_SUCCESS(rc2)) 302 continue; 303 } 304 305 /* failed fatally. */ 306 pIntEnv->cVars = iDst + 1; 307 RtlReleasePebLock(); 308 RTEnvDestroy(pIntEnv); 309 return rc2; 310 } 311 312 Assert(!*pwszzEnv); Assert(iDst == cVars); 313 pIntEnv->cVars = iDst; 314 pIntEnv->papszEnv[iDst] = NULL; 315 316 /* done */ 317 *phEnv = pIntEnv; 318 } 319 320 RtlReleasePebLock(); 321 return rc; 322 323 #else /* !RT_OS_WINDOWS */ 324 325 /* 326 * Figure out how many variable to clone. 327 */ 328 const char * const *papszEnv = rtEnvDefault(); 329 size_t cVars = 0; 330 if (papszEnv) 331 while (papszEnv[cVars]) 332 cVars++; 333 261 334 bool fCaseSensitive = true; 262 bool fPutEnvBlock = false; 263 bool fFirstEqual = false; 264 size_t cVars; 265 const char * const *papszEnv; 266 #ifdef RTENV_HAVE_WENVIRON 267 PCRTUTF16 const * papwszEnv = NULL; 268 #endif 269 PRTENVINTERNAL pIntEnvToClone; 270 AssertPtrReturn(pEnv, VERR_INVALID_POINTER); 271 if (EnvToClone == RTENV_DEFAULT) 272 { 273 cVars = 0; 274 pIntEnvToClone = NULL; 275 #ifdef RTENV_HAVE_WENVIRON 276 papszEnv = NULL; 277 papwszEnv = (PCRTUTF16 * const)_wenviron; 278 if (!papwszEnv) 279 { 280 _wgetenv(L"Path"); /* Force the CRT to initalize it. */ 281 papwszEnv = (PCRTUTF16 * const)_wenviron; 282 } 283 if (papwszEnv) 284 while (papwszEnv[cVars]) 285 cVars++; 286 #else 287 papszEnv = rtEnvDefault(); 288 if (papszEnv) 289 while (papszEnv[cVars]) 290 cVars++; 291 #endif 292 293 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 294 /* DOS systems was case insensitive. A prime example is the 'Path' 295 variable on windows which turns into the 'PATH' variable. */ 296 fCaseSensitive = false; 297 #endif 298 #ifdef RTENV_ALLOW_EQUAL_FIRST_IN_VAR 299 fFirstEqual = true; 300 #endif 301 } 335 # if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 336 /* DOS systems was case insensitive. A prime example is the 'Path' 337 variable on windows which turns into the 'PATH' variable. */ 338 fCaseSensitive = false; 339 # endif 340 341 /* 342 * Create the duplicate. 343 */ 344 PRTENVINTERNAL pIntEnv; 345 int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, fCaseSensitive, false /*fPutEnvBlock*/, fFirstEqual); 346 if (RT_SUCCESS(rc)) 347 { 348 pIntEnv->cVars = cVars; 349 pIntEnv->papszEnv[pIntEnv->cVars] = NULL; 350 351 /* ASSUMES the default environment is in the current codepage. */ 352 size_t iDst = 0; 353 for (size_t iSrc = 0; iSrc < cVars; iSrc++) 354 { 355 int rc2 = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iDst], papszEnv[iSrc]); 356 if (RT_SUCCESS(rc2)) 357 { 358 /* Make sure it contains an '='. */ 359 iDst++; 360 if (strchr(pIntEnv->papszEnv[iDst - 1], '=')) 361 continue; 362 rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst - 1], "="); 363 if (RT_SUCCESS(rc2)) 364 continue; 365 } 366 else if (rc2 == VERR_NO_TRANSLATION) 367 { 368 rc = VWRN_ENV_NOT_FULLY_TRANSLATED; 369 continue; 370 } 371 372 /* failed fatally. */ 373 pIntEnv->cVars = iDst; 374 RTEnvDestroy(pIntEnv); 375 return rc2; 376 } 377 pIntEnv->cVars = iDst; 378 379 /* done */ 380 *phEnv = pIntEnv; 381 } 382 383 return rc; 384 #endif /* !RT_OS_WINDOWS */ 385 } 386 387 388 /** 389 * Clones a non-default environment instance. 390 * 391 * @param phEnv Where to return the handle to the cloned environment. 392 * @param pIntEnvToClone The source environment. Caller takes care of 393 * locking. 394 */ 395 static int rtEnvCloneNonDefault(PRTENV phEnv, PRTENVINTERNAL pIntEnvToClone) 396 { 397 PRTENVINTERNAL pIntEnv; 398 size_t const cVars = pIntEnvToClone->cVars; 399 int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, 400 pIntEnvToClone->pfnCompare != RTStrNICmp, 401 pIntEnvToClone->fPutEnvBlock, 402 pIntEnvToClone->fFirstEqual); 403 if (RT_SUCCESS(rc)) 404 { 405 pIntEnv->cVars = cVars; 406 pIntEnv->papszEnv[cVars] = NULL; 407 408 const char * const * const papszEnv = pIntEnvToClone->papszEnv; 409 for (size_t iVar = 0; iVar < cVars; iVar++) 410 { 411 char *pszVar = RTStrDup(papszEnv[iVar]); 412 if (RT_UNLIKELY(!pszVar)) 413 { 414 pIntEnv->cVars = iVar; 415 RTEnvDestroy(pIntEnv); 416 return VERR_NO_STR_MEMORY; 417 } 418 pIntEnv->papszEnv[iVar] = pszVar; 419 } 420 421 /* done */ 422 *phEnv = pIntEnv; 423 } 424 return rc; 425 } 426 427 428 RTDECL(int) RTEnvClone(PRTENV phEnv, RTENV hEnvToClone) 429 { 430 /* 431 * Validate input and what kind of source block we're working with. 432 */ 433 int rc; 434 AssertPtrReturn(phEnv, VERR_INVALID_POINTER); 435 if (hEnvToClone == RTENV_DEFAULT) 436 rc = rtEnvCloneDefault(phEnv); 302 437 else 303 438 { 304 pIntEnvToClone =EnvToClone;439 PRTENVINTERNAL pIntEnvToClone = hEnvToClone; 305 440 AssertPtrReturn(pIntEnvToClone, VERR_INVALID_HANDLE); 306 441 AssertReturn(pIntEnvToClone->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); 442 307 443 RTENV_LOCK(pIntEnvToClone); 308 309 fPutEnvBlock = pIntEnvToClone->fPutEnvBlock; 310 fFirstEqual = pIntEnvToClone->fFirstEqual; 311 papszEnv = pIntEnvToClone->papszEnv; 312 cVars = pIntEnvToClone->cVars; 313 } 314 315 /* 316 * Create the duplicate. 317 */ 318 PRTENVINTERNAL pIntEnv; 319 int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, fCaseSensitive, fPutEnvBlock, fFirstEqual); 320 if (RT_SUCCESS(rc)) 321 { 322 pIntEnv->cVars = cVars; 323 pIntEnv->papszEnv[pIntEnv->cVars] = NULL; 324 if (EnvToClone == RTENV_DEFAULT) 325 { 326 /* ASSUMES the default environment is in the current codepage. */ 327 size_t iDst = 0; 328 for (size_t iSrc = 0; iSrc < cVars; iSrc++) 329 { 330 #ifdef RTENV_HAVE_WENVIRON 331 int rc2 = RTUtf16ToUtf8(papwszEnv[iSrc], &pIntEnv->papszEnv[iDst]); 332 #else 333 int rc2 = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iDst], papszEnv[iSrc]); 334 #endif 335 if (RT_SUCCESS(rc2)) 336 { 337 /* Make sure it contains an '='. */ 338 iDst++; 339 if (strchr(pIntEnv->papszEnv[iDst - 1], '=')) 340 continue; 341 rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst - 1], "="); 342 if (RT_SUCCESS(rc2)) 343 continue; 344 } 345 else if (rc2 == VERR_NO_TRANSLATION) 346 { 347 rc = VWRN_ENV_NOT_FULLY_TRANSLATED; 348 continue; 349 } 350 351 /* failed fatally. */ 352 pIntEnv->cVars = iDst; 353 RTEnvDestroy(pIntEnv); 354 return rc2; 355 } 356 pIntEnv->cVars = iDst; 357 } 358 else 359 { 360 for (size_t iVar = 0; iVar < cVars; iVar++) 361 { 362 char *pszVar = RTStrDup(papszEnv[iVar]); 363 if (RT_UNLIKELY(!pszVar)) 364 { 365 RTENV_UNLOCK(pIntEnvToClone); 366 367 pIntEnv->cVars = iVar; 368 RTEnvDestroy(pIntEnv); 369 return VERR_NO_STR_MEMORY; 370 } 371 pIntEnv->papszEnv[iVar] = pszVar; 372 } 373 } 374 375 /* done */ 376 *pEnv = pIntEnv; 377 } 378 379 if (pIntEnvToClone) 444 rc = rtEnvCloneNonDefault(phEnv, pIntEnvToClone); 380 445 RTENV_UNLOCK(pIntEnvToClone); 446 } 381 447 return rc; 382 448 } … … 917 983 918 984 985 #ifndef RT_OS_WINDOWS 919 986 RTDECL(char const * const *) RTEnvGetExecEnvP(RTENV Env) 920 987 { … … 979 1046 } 980 1047 RT_EXPORT_SYMBOL(RTEnvGetExecEnvP); 1048 #endif /* !RT_OS_WINDOWS */ 981 1049 982 1050 -
trunk/src/VBox/Runtime/testcase/tstRTEnv.cpp
r93115 r95842 303 303 * execve envp and we're done. 304 304 */ 305 #ifndef RT_OS_WINDOWS 305 306 RTTestSub(hTest, "RTEnvGetExecEnvP"); 306 const char * const *papsz = RTEnvGetExecEnvP(RTENV_DEFAULT);307 papsz = RTEnvGetExecEnvP(RTENV_DEFAULT); 307 308 CHECK(papsz != NULL); 308 309 papsz = RTEnvGetExecEnvP(RTENV_DEFAULT); … … 313 314 papsz = RTEnvGetExecEnvP(Env); 314 315 CHECK(papsz != NULL); 316 #endif 315 317 316 318 CHECK_RC(RTEnvDestroy(Env), VINF_SUCCESS);
Note:
See TracChangeset
for help on using the changeset viewer.