env-generic.cpp revision 5b281ba489ca18f0380d7efc7a5108b606cce449
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Environment, Generic.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
804197ca1d56719343cd21af782ddc2c695a6760vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
804197ca1d56719343cd21af782ddc2c695a6760vboxsync * available from http://www.virtualbox.org. This file is free software;
804197ca1d56719343cd21af782ddc2c695a6760vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * terms and conditions of either the GPL or the CDDL or both.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * additional information or have any questions.
65a755c25b49d32c914e2d569fcdfb766e1ee879vboxsync/*******************************************************************************
65a755c25b49d32c914e2d569fcdfb766e1ee879vboxsync* Header Files *
65a755c25b49d32c914e2d569fcdfb766e1ee879vboxsync*******************************************************************************/
4157c84dffb94fe976739ad709e4fd95d22c6667vboxsync#if defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) || defined(RT_OS_OPENBSD)
6988e736149e8800875f9fbb001a6018926d6562vboxsyncextern char **environ;
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync/*******************************************************************************
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync* Defined Constants And Macros *
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync*******************************************************************************/
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync/** Macro that unlocks the specified environment block. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync/** Macro that unlocks the specified environment block. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync/*******************************************************************************
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync* Structures and Typedefs *
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync*******************************************************************************/
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * The internal representation of a (non-default) environment.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /** Magic value . */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /** Number of variables in the array.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * This does not include the terminating NULL entry. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /** Capacity (allocated size) of the array.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * This includes space for the terminating NULL element (for compatibility
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * with the C library), so that c <= cCapacity - 1. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /** Array of environment variables. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /** Array of environment variables in the process CP.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * This get (re-)constructed when RTEnvGetExecEnvP method is called. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync/** The allocation granularity of the RTENVINTERNAL::papszEnv memory. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Internal worker that resolves the pointer to the default
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * process environment. (environ)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * @returns Pointer to the default environment.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * This may be NULL.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsyncstatic const char * const *rtEnvDefault(void)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /* So far, our L4 libraries do not include environment support. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Internal worker that creates an environment handle with a specified capacity.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * @returns IPRT status code.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * @param ppIntEnv Where to store the result.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * @param cAllocated The initial array size.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsyncstatic int rtEnvCreate(PRTENVINTERNAL *ppIntEnv, size_t cAllocated)
65a755c25b49d32c914e2d569fcdfb766e1ee879vboxsync * Allocate environment handle.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync PRTENVINTERNAL pIntEnv = (PRTENVINTERNAL)RTMemAlloc(sizeof(*pIntEnv));
65a755c25b49d32c914e2d569fcdfb766e1ee879vboxsync * Pre-allocate the variable array.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync pIntEnv->cAllocated = RT_ALIGN_Z(RT_MAX(cAllocated, RTENV_GROW_SIZE), RTENV_GROW_SIZE);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync pIntEnv->papszEnv = (char **)RTMemAllocZ(sizeof(pIntEnv->papszEnv[0]) * pIntEnv->cAllocated);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Ignore NIL_RTENV and validate input.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Do the cleanup.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync while (iVar-- > 0)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync for (iVar = 0; pIntEnv->papszEnvOtherCP[iVar]; iVar++)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /*RTCritSectDelete(&pIntEnv->CritSect) */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsyncRTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Validate input and figure out how many variable to clone and where to get them.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync const char * const *papszEnv;
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertPtrReturn(pIntEnvToClone, VERR_INVALID_HANDLE);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertReturn(pIntEnvToClone->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Create the duplicate.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /* ASSUMES the default environment is in the current codepage. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync int rc = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iVar], papszEnv[iVar]);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsyncRTDECL(int) RTEnvPutEx(RTENV Env, const char *pszVarEqualValue)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertPtrReturn(pszVarEqualValue, VERR_INVALID_POINTER);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Make a copy of the variable name so we can terminate it
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * properly and then pass the request on to RTEnvSetEx.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsyncRTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Since RTEnvPut isn't UTF-8 clean and actually expects the strings
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * to be in the current code page (codeset), we'll do the necessary
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * conversions here.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync rc = RTStrUtf8ToCurrentCP(&pszValueOtherCP, pszValue);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Create the variable string.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync char *pszEntry = (char *)RTMemAlloc(cchVar + cchValue + 2);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync memcpy(&pszEntry[cchVar + 1], pszValue, cchValue + 1);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Find the location of the variable. (iVar = cVars if new)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Replace the current entry. Simple.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Adding a new variable. Resize the array if required
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * and then insert the new value at the end.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync void *pvNew = RTMemRealloc(pIntEnv->papszEnv, sizeof(char *) * (pIntEnv->cAllocated + RTENV_GROW_SIZE));
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync for (size_t iNewVar = pIntEnv->cVars; iNewVar < pIntEnv->cAllocated; iNewVar++)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync pIntEnv->papszEnv[iVar + 1] = NULL; /* this isn't really necessary, but doesn't hurt. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsyncRTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Since RTEnvUnset isn't UTF-8 clean and actually expects the strings
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * to be in the current code page (codeset), we'll do the necessary
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * conversions here.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Remove all variable by the given name.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync pIntEnv->papszEnv[iVar] = pIntEnv->papszEnv[pIntEnv->cVars];
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /* no break, there could be more. */
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsyncRTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertPtrNullReturn(pszValue, VERR_INVALID_POINTER);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Since RTEnvGet isn't UTF-8 clean and actually expects the strings
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * to be in the current code page (codeset), we'll do the necessary
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * conversions here.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync const char *pszValueOtherCP = RTEnvGet(pszVarOtherCP);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync rc = RTStrCurrentCPToUtf8(&pszValueUtf8, pszValueOtherCP);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Locate the first variable and return it to the caller.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync const char *pszValueOrg = pIntEnv->papszEnv[iVar] + cchVar + 1;
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsyncRTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync bool fExist = false;
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Since RTEnvExist isn't UTF-8 clean and actually expects the strings
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * to be in the current code page (codeset), we'll do the necessary
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * conversions here.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync int rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, false);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Simple search.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsyncRTDECL(char const * const *) RTEnvGetExecEnvP(RTENV Env)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync const char * const *papszRet;
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync static const char * const s_papszDummy[2] = { NULL, NULL };
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, NULL);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Free any old envp.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync for (size_t iVar = 0; pIntEnv->papszEnvOtherCP[iVar]; iVar++)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync * Construct a new envp with the strings in the process code set.
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync papszRet = pIntEnv->papszEnvOtherCP = papsz = (char **)RTMemAlloc(sizeof(char *) * (pIntEnv->cVars + 1));
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync int rc = RTStrUtf8ToCurrentCP(&papsz[iVar], pIntEnv->papszEnv[iVar]);
ababd7e83ee3d23c5191a0d3802f10764df69e36vboxsync /* RTEnvDestroy / we cleans up later. */