env-generic.cpp revision 3d5d761b58f80f44f4e751bbc61caf2de4d7007c
/* $Id$ */
/** @file
* IPRT - Environment, Generic.
*/
/*
* Copyright (C) 2006-2007 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <stdlib.h>
#if !defined(RT_OS_WINDOWS)
# include <unistd.h>
#endif
#ifdef RT_OS_DARWIN
# include <crt_externs.h>
#endif
#if defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) || defined(RT_OS_OPENBSD)
extern char **environ;
#endif
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
/** Macro that unlocks the specified environment block. */
#define RTENV_LOCK(pEnvInt) do { } while (0)
/** Macro that unlocks the specified environment block. */
#define RTENV_UNLOCK(pEnvInt) do { } while (0)
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* The internal representation of a (non-default) environment.
*/
typedef struct RTENVINTERNAL
{
/** Magic value . */
/** Number of variables in the array.
* This does not include the terminating NULL entry. */
/** Capacity (allocated size) of the array.
* This includes space for the terminating NULL element (for compatibility
* with the C library), so that c <= cCapacity - 1. */
/** Array of environment variables. */
char **papszEnv;
/** Array of environment variables in the process CP.
* This get (re-)constructed when RTEnvGetExecEnvP method is called. */
char **papszEnvOtherCP;
/** The allocation granularity of the RTENVINTERNAL::papszEnv memory. */
#define RTENV_GROW_SIZE 16
/**
* Internal worker that resolves the pointer to the default
* process environment. (environ)
*
* @returns Pointer to the default environment.
* This may be NULL.
*/
static const char * const *rtEnvDefault(void)
{
#ifdef RT_OS_DARWIN
return *(_NSGetEnviron());
/* So far, our L4 libraries do not include environment support. */
return NULL;
#else
return environ;
#endif
}
/**
* Internal worker that creates an environment handle with a specified capacity.
*
* @returns IPRT status code.
* @param ppIntEnv Where to store the result.
* @param cAllocated The initial array size.
*/
{
/*
* Allocate environment handle.
*/
if (pIntEnv)
{
/*
* Pre-allocate the variable array.
*/
{
return VINF_SUCCESS;
}
}
return VERR_NO_MEMORY;
}
{
}
{
/*
* Ignore NIL_RTENV and validate input.
*/
|| Env == RTENV_DEFAULT)
return VINF_SUCCESS;
/*
* Do the cleanup.
*/
while (iVar-- > 0)
if (pIntEnv->papszEnvOtherCP)
{
{
}
}
/*RTCritSectDelete(&pIntEnv->CritSect) */
return VINF_SUCCESS;
}
{
/*
* Validate input and figure out how many variable to clone and where to get them.
*/
const char * const *papszEnv;
if (EnvToClone == RTENV_DEFAULT)
{
papszEnv = rtEnvDefault();
cVars = 0;
if (papszEnv)
cVars++;
}
else
{
}
/*
* Create the duplicate.
*/
if (RT_SUCCESS(rc))
{
if (EnvToClone == RTENV_DEFAULT)
{
/* ASSUMES the default environment is in the current codepage. */
{
if (RT_SUCCESS(rc2))
iDst++;
else if (rc2 == VERR_NO_TRANSLATION)
else
{
return rc2;
}
}
}
else
{
{
if (RT_UNLIKELY(!pszVar))
{
return VERR_NO_STR_MEMORY;
}
}
}
/* done */
}
if (pIntEnvToClone)
return rc;
}
{
int rc;
if (!pszEq)
else
{
/*
* Make a copy of the variable name so we can terminate it
* properly and then pass the request on to RTEnvSetEx.
*/
}
return rc;
}
{
int rc;
if (Env == RTENV_DEFAULT)
{
/*
* Since RTEnvPut isn't UTF-8 clean and actually expects the strings
* to be in the current code page (codeset), we'll do the necessary
* conversions here.
*/
char *pszVarOtherCP;
if (RT_SUCCESS(rc))
{
char *pszValueOtherCP;
if (RT_SUCCESS(rc))
{
}
}
}
else
{
/*
* Create the variable string.
*/
if (pszEntry)
{
/*
* Find the location of the variable. (iVar = cVars if new)
*/
rc = VINF_SUCCESS;
break;
{
/*
* Replace the current entry. Simple.
*/
}
else
{
/*
* Adding a new variable. Resize the array if required
* and then insert the new value at the end.
*/
{
void *pvNew = RTMemRealloc(pIntEnv->papszEnv, sizeof(char *) * (pIntEnv->cAllocated + RTENV_GROW_SIZE));
if (!pvNew)
rc = VERR_NO_MEMORY;
else
{
}
}
if (RT_SUCCESS(rc))
{
}
}
if (RT_FAILURE(rc))
}
else
rc = VERR_NO_MEMORY;
}
return rc;
}
{
int rc;
if (Env == RTENV_DEFAULT)
{
/*
* Since RTEnvUnset isn't UTF-8 clean and actually expects the strings
* to be in the current code page (codeset), we'll do the necessary
* conversions here.
*/
char *pszVarOtherCP;
if (RT_SUCCESS(rc))
{
}
}
else
{
/*
* Remove all variable by the given name.
*/
{
rc = VINF_SUCCESS;
/* no break, there could be more. */
}
}
return rc;
}
RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual)
{
if (pcchActual)
*pcchActual = 0;
int rc;
if (Env == RTENV_DEFAULT)
{
/*
* Since RTEnvGet isn't UTF-8 clean and actually expects the strings
* to be in the current code page (codeset), we'll do the necessary
* conversions here.
*/
char *pszVarOtherCP;
if (RT_SUCCESS(rc))
{
if (pszValueOtherCP)
{
char *pszValueUtf8;
if (RT_SUCCESS(rc))
{
rc = VINF_SUCCESS;
if (pcchActual)
*pcchActual = cch;
{
else
}
}
}
else
}
}
else
{
/*
* Locate the first variable and return it to the caller.
*/
{
rc = VINF_SUCCESS;
if (pcchActual)
*pcchActual = cch;
{
else
}
break;
}
}
return rc;
}
{
AssertPtrReturn(pszVar, false);
bool fExist = false;
if (Env == RTENV_DEFAULT)
{
/*
* Since RTEnvExist isn't UTF-8 clean and actually expects the strings
* to be in the current code page (codeset), we'll do the necessary
* conversions here.
*/
char *pszVarOtherCP;
if (RT_SUCCESS(rc))
{
}
}
else
{
AssertPtrReturn(pIntEnv, false);
/*
* Simple search.
*/
{
fExist = true;
break;
}
}
return fExist;
}
{
const char * const *papszRet;
if (Env == RTENV_DEFAULT)
{
papszRet = rtEnvDefault();
if (!papszRet)
{
papszRet = &s_papszDummy[0];
}
}
else
{
/*
* Free any old envp.
*/
if (pIntEnv->papszEnvOtherCP)
{
{
}
}
/*
* Construct a new envp with the strings in the process code set.
*/
char **papsz;
papszRet = pIntEnv->papszEnvOtherCP = papsz = (char **)RTMemAlloc(sizeof(char *) * (pIntEnv->cVars + 1));
if (papsz)
{
{
if (RT_FAILURE(rc))
{
/* RTEnvDestroy / we cleans up later. */
break;
}
}
}
}
return papszRet;
}
/**
* RTSort callback for comparing two environment variables.
*
* @returns -1, 0, 1. See PFNRTSORTCMP.
* @param pvElement1 Variable 1.
* @param pvElement2 Variable 2.
* @param pvUser Ignored.
*/
{
if (iDiff < 0)
iDiff = -1;
else if (iDiff > 0)
iDiff = 1;
return iDiff;
}
{
int rc;
/*
* Validate / simplify input.
*/
if (hEnv == RTENV_DEFAULT)
{
if (RT_FAILURE(rc))
return rc;
}
else
{
rc = VINF_SUCCESS;
}
/*
* Sort it first.
*/
/*
* Calculate the size.
*/
{
}
if (RT_SUCCESS(rc))
{
/*
* Perform the conversion.
*/
if (pwszz)
{
{
}
if (RT_SUCCESS(rc))
{
pwszz[0] = '\0';
}
else
{
pwszzBlock = NULL;
}
}
else
rc = VERR_NO_MEMORY;
}
if (RT_SUCCESS(rc))
return rc;
}
{
}