env-generic.cpp revision 4157c84dffb94fe976739ad709e4fd95d22c6667
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* $Id$ */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** @file
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * innotek Portable Runtime - Environment, Generic.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*
98427c0ab08697e468c26dc33ee9571308577867vboxsync * Copyright (C) 2006-2007 innotek GmbH
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * available from http://www.virtualbox.org. This file is free software;
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * you can redistribute it and/or modify it under the terms of the GNU
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * General Public License as published by the Free Software Foundation,
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Header Files *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/env.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <iprt/assert.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/alloc.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/alloca.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/string.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/err.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include "internal/magics.h"
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <stdlib.h>
506df97a8c78dacfe69bc4d3ee5d3de832d0f19avboxsync#if !defined(RT_OS_WINDOWS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <unistd.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_DARWIN
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# include <crt_externs.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#if defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) || defined(RT_OS_OPENBSD)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync__BEGIN_DECLS
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncextern char **environ;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync__END_DECLS
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Defined Constants And Macros *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** Macro that unlocks the specified environment block. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define RTENV_LOCK(pEnvInt) do { } while (0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** Macro that unlocks the specified environment block. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define RTENV_UNLOCK(pEnvInt) do { } while (0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Structures and Typedefs *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * The internal representation of a (non-default) environment.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsynctypedef struct RTENVINTERNAL
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** Magic value . */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint32_t u32Magic;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** Number of variables in the array.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * This does not include the terminating NULL entry. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t cVars;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** Capacity (allocated size) of the array.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * This includes space for the terminating NULL element (for compatibility
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * with the C library), so that c <= cCapacity - 1. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t cAllocated;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** Array of environment variables. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync char **papszEnv;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** Array of environment variables in the process CP.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * This get (re-)constructed when RTEnvGetExecEnvP method is called. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync char **papszEnvOtherCP;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync} RTENVINTERNAL, *PRTENVINTERNAL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** The allocation granularity of the RTENVINTERNAL::papszEnv memory. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define RTENV_GROW_SIZE 16
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Internal worker that resolves the pointer to the default
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * process environment. (environ)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns Pointer to the default environment.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * This may be NULL.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic const char * const *rtEnvDefault(void)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#ifdef RT_OS_DARWIN
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return *(_NSGetEnviron());
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#elif defined(RT_OS_L4)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* So far, our L4 libraries do not include environment support. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return environ;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Internal worker that creates an environment handle with a specified capacity.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns IPRT status code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param ppIntEnv Where to store the result.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param cAllocated The initial array size.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic int rtEnvCreate(PRTENVINTERNAL *ppIntEnv, size_t cAllocated)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Allocate environment handle.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PRTENVINTERNAL pIntEnv = (PRTENVINTERNAL)RTMemAlloc(sizeof(*pIntEnv));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pIntEnv)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Pre-allocate the variable array.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->u32Magic = RTENV_MAGIC;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->papszEnvOtherCP = NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->cVars = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->cAllocated = RT_ALIGN_Z(RT_MAX(cAllocated, RTENV_GROW_SIZE), RTENV_GROW_SIZE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->papszEnv = (char **)RTMemAllocZ(sizeof(pIntEnv->papszEnv[0]) * pIntEnv->cAllocated);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pIntEnv->papszEnv)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *ppIntEnv = pIntEnv;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTMemFree(pIntEnv);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_NO_MEMORY;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncRTDECL(int) RTEnvCreate(PRTENV pEnv)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(pEnv, VERR_INVALID_POINTER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rtEnvCreate(pEnv, RTENV_GROW_SIZE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncRTDECL(int) RTEnvDestroy(RTENV Env)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Ignore NIL_RTENV and validate input.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( Env == NIL_RTENV
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || Env == RTENV_DEFAULT)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PRTENVINTERNAL pIntEnv = Env;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Do the cleanup.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTENV_LOCK(pIntEnv);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->u32Magic++;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t iVar = pIntEnv->cVars;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync while (iVar-- > 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTStrFree(pIntEnv->papszEnv[iVar]);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTMemFree(pIntEnv->papszEnv);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->papszEnv = NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pIntEnv->papszEnvOtherCP)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (iVar = 0; pIntEnv->papszEnvOtherCP[iVar]; iVar++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTStrFree(pIntEnv->papszEnvOtherCP[iVar]);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->papszEnvOtherCP[iVar] = NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTMemFree(pIntEnv->papszEnvOtherCP);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->papszEnvOtherCP = NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTENV_UNLOCK(pIntEnv);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*RTCritSectDelete(&pIntEnv->CritSect) */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTMemFree(pIntEnv);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VINF_SUCCESS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncRTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone)
98427c0ab08697e468c26dc33ee9571308577867vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Validate input and figure out how many variable to clone and where to get them.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t cVars;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const char * const *papszEnv;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PRTENVINTERNAL pIntEnvToClone;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(pEnv, VERR_INVALID_POINTER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (EnvToClone == RTENV_DEFAULT)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnvToClone = NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync papszEnv = rtEnvDefault();
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cVars = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (papszEnv)
98427c0ab08697e468c26dc33ee9571308577867vboxsync while (papszEnv[cVars])
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cVars++;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnvToClone = EnvToClone;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(pIntEnvToClone, VERR_INVALID_HANDLE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertReturn(pIntEnvToClone->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTENV_LOCK(pIntEnvToClone);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
98427c0ab08697e468c26dc33ee9571308577867vboxsync papszEnv = pIntEnvToClone->papszEnv;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cVars = pIntEnvToClone->cVars;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
98427c0ab08697e468c26dc33ee9571308577867vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Create the duplicate.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PRTENVINTERNAL pIntEnv;
98427c0ab08697e468c26dc33ee9571308577867vboxsync int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_SUCCESS(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->cVars = cVars;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->papszEnv[pIntEnv->cVars] = NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (EnvToClone == RTENV_DEFAULT)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* ASSUMES the default environment is in the current codepage. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (size_t iVar = 0; iVar < cVars; iVar++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
98427c0ab08697e468c26dc33ee9571308577867vboxsync int rc = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iVar], papszEnv[iVar]);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_FAILURE(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->cVars = iVar;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTEnvDestroy(pIntEnv);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (size_t iVar = 0; iVar < cVars; iVar++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync char *pszVar = RTStrDup(papszEnv[iVar]);
98427c0ab08697e468c26dc33ee9571308577867vboxsync if (RT_UNLIKELY(!pszVar))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTENV_UNLOCK(pIntEnvToClone);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pIntEnv->cVars = iVar;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTEnvDestroy(pIntEnv);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
98427c0ab08697e468c26dc33ee9571308577867vboxsync pIntEnv->papszEnv[iVar] = pszVar;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* done */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *pEnv = pIntEnv;
98427c0ab08697e468c26dc33ee9571308577867vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pIntEnvToClone)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTENV_UNLOCK(pIntEnvToClone);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncRTDECL(int) RTEnvPutEx(RTENV Env, const char *pszVarEqualValue)
98427c0ab08697e468c26dc33ee9571308577867vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(pszVarEqualValue, VERR_INVALID_POINTER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const char *pszEq = strchr(pszVarEqualValue, '=');
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!pszEq)
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync rc = RTEnvUnsetEx(Env, pszVarEqualValue);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
98427c0ab08697e468c26dc33ee9571308577867vboxsync /*
98427c0ab08697e468c26dc33ee9571308577867vboxsync * Make a copy of the variable name so we can terminate it
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * properly and then pass the request on to RTEnvSetEx.
98427c0ab08697e468c26dc33ee9571308577867vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const char *pszValue = pszEq + 1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t cchVar = pszEq - pszVarEqualValue;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(cchVar < 1024);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync char *pszVar = (char *)alloca(cchVar + 1);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync memcpy(pszVar, pszVarEqualValue, cchVar);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pszVar[cchVar] = '\0';
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTEnvSetEx(Env, pszVar, pszValue);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue)
{
AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
AssertReturn(*pszVar, VERR_INVALID_PARAMETER);
AssertPtrReturn(pszValue, VERR_INVALID_POINTER);
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;
rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
if (RT_SUCCESS(rc))
{
char *pszValueOtherCP;
rc = RTStrUtf8ToCurrentCP(&pszValueOtherCP, pszValue);
if (RT_SUCCESS(rc))
{
rc = RTEnvSet(pszVarOtherCP, pszValueOtherCP);
RTStrFree(pszValueOtherCP);
}
RTStrFree(pszVarOtherCP);
}
}
else
{
PRTENVINTERNAL pIntEnv = Env;
AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
/*
* Create the variable string.
*/
const size_t cchVar = strlen(pszVar);
const size_t cchValue = strlen(pszValue);
char *pszEntry = (char *)RTMemAlloc(cchVar + cchValue + 2);
if (pszEntry)
{
memcpy(pszEntry, pszVar, cchVar);
pszEntry[cchVar] = '=';
memcpy(&pszEntry[cchVar + 1], pszValue, cchValue + 1);
RTENV_LOCK(pIntEnv);
/*
* Find the location of the variable. (iVar = cVars if new)
*/
rc = VINF_SUCCESS;
size_t iVar;
for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
&& pIntEnv->papszEnv[iVar][cchVar] == '=')
break;
if (iVar < pIntEnv->cVars)
{
/*
* Replace the current entry. Simple.
*/
RTMemFree(pIntEnv->papszEnv[iVar]);
pIntEnv->papszEnv[iVar] = pszEntry;
}
else
{
/*
* Adding a new variable. Resize the array if required
* and then insert the new value at the end.
*/
if (pIntEnv->cVars + 2 > pIntEnv->cAllocated)
{
void *pvNew = RTMemRealloc(pIntEnv->papszEnv, sizeof(char *) * (pIntEnv->cAllocated + RTENV_GROW_SIZE));
if (!pvNew)
rc = VERR_NO_MEMORY;
else
{
pIntEnv->papszEnv = (char **)pvNew;
pIntEnv->cAllocated += RTENV_GROW_SIZE;
for (size_t iNewVar = pIntEnv->cVars; iNewVar < pIntEnv->cAllocated; iNewVar++)
pIntEnv->papszEnv[iNewVar] = NULL;
}
}
if (RT_SUCCESS(rc))
{
pIntEnv->papszEnv[iVar] = pszEntry;
pIntEnv->papszEnv[iVar + 1] = NULL; /* this isn't really necessary, but doesn't hurt. */
pIntEnv->cVars++;
Assert(pIntEnv->cVars == iVar + 1);
}
}
RTENV_UNLOCK(pIntEnv);
if (RT_FAILURE(rc))
RTMemFree(pszEntry);
}
else
rc = VERR_NO_MEMORY;
}
return rc;
}
RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar)
{
AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
AssertReturn(*pszVar, VERR_INVALID_PARAMETER);
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;
rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
if (RT_SUCCESS(rc))
{
rc = RTEnvUnset(pszVarOtherCP);
RTStrFree(pszVarOtherCP);
}
}
else
{
PRTENVINTERNAL pIntEnv = Env;
AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
RTENV_LOCK(pIntEnv);
/*
* Remove all variable by the given name.
*/
rc = VINF_ENV_VAR_NOT_FOUND;
const size_t cchVar = strlen(pszVar);
size_t iVar;
for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
&& pIntEnv->papszEnv[iVar][cchVar] == '=')
{
RTMemFree(pIntEnv->papszEnv[iVar]);
pIntEnv->cVars--;
if (pIntEnv->cVars > 0)
pIntEnv->papszEnv[iVar] = pIntEnv->papszEnv[pIntEnv->cVars];
pIntEnv->papszEnv[pIntEnv->cVars] = NULL;
rc = VINF_SUCCESS;
/* no break, there could be more. */
}
RTENV_UNLOCK(pIntEnv);
}
return rc;
}
RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual)
{
AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
AssertPtrNullReturn(pszValue, VERR_INVALID_POINTER);
AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER);
AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER);
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;
rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
if (RT_SUCCESS(rc))
{
const char *pszValueOtherCP = RTEnvGet(pszVarOtherCP);
RTStrFree(pszVarOtherCP);
if (pszValueOtherCP)
{
char *pszValueUtf8;
rc = RTStrCurrentCPToUtf8(&pszValueUtf8, pszValueOtherCP);
if (RT_SUCCESS(rc))
{
rc = VINF_SUCCESS;
size_t cch = strlen(pszValueUtf8);
if (pcchActual)
*pcchActual = cch;
if (pszValue && cbValue)
{
if (cch < cbValue)
memcpy(pszValue, pszValueUtf8, cch + 1);
else
rc = VERR_BUFFER_OVERFLOW;
}
}
}
else
rc = VERR_ENV_VAR_NOT_FOUND;
}
}
else
{
PRTENVINTERNAL pIntEnv = Env;
AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
RTENV_LOCK(pIntEnv);
/*
* Locate the first variable and return it to the caller.
*/
rc = VERR_ENV_VAR_NOT_FOUND;
const size_t cchVar = strlen(pszVar);
size_t iVar;
for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
&& pIntEnv->papszEnv[iVar][cchVar] == '=')
{
rc = VINF_SUCCESS;
const char *pszValueOrg = pIntEnv->papszEnv[iVar] + cchVar + 1;
size_t cch = strlen(pszValueOrg);
if (pcchActual)
*pcchActual = cch;
if (pszValue && cbValue)
{
if (cch < cbValue)
memcpy(pszValue, pszValueOrg, cch + 1);
else
rc = VERR_BUFFER_OVERFLOW;
}
break;
}
RTENV_UNLOCK(pIntEnv);
}
return rc;
}
RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar)
{
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;
int rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
if (RT_SUCCESS(rc))
{
fExist = RTEnvExist(pszVarOtherCP);
RTStrFree(pszVarOtherCP);
}
}
else
{
PRTENVINTERNAL pIntEnv = Env;
AssertPtrReturn(pIntEnv, false);
AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, false);
RTENV_LOCK(pIntEnv);
/*
* Simple search.
*/
const size_t cchVar = strlen(pszVar);
for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
if ( !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
&& pIntEnv->papszEnv[iVar][cchVar] == '=')
{
fExist = true;
break;
}
RTENV_UNLOCK(pIntEnv);
}
return fExist;
}
RTDECL(char const * const *) RTEnvGetExecEnvP(RTENV Env)
{
const char * const *papszRet;
if (Env == RTENV_DEFAULT)
{
papszRet = rtEnvDefault();
if (!papszRet)
{
static const char * const s_papszDummy[2] = { NULL, NULL };
papszRet = &s_papszDummy[0];
}
}
else
{
PRTENVINTERNAL pIntEnv = Env;
AssertPtrReturn(pIntEnv, NULL);
AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, NULL);
RTENV_LOCK(pIntEnv);
/*
* Free any old envp.
*/
if (pIntEnv->papszEnvOtherCP)
{
for (size_t iVar = 0; pIntEnv->papszEnvOtherCP[iVar]; iVar++)
{
RTStrFree(pIntEnv->papszEnvOtherCP[iVar]);
pIntEnv->papszEnvOtherCP[iVar] = NULL;
}
RTMemFree(pIntEnv->papszEnvOtherCP);
pIntEnv->papszEnvOtherCP = NULL;
}
/*
* 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)
{
papsz[pIntEnv->cVars] = NULL;
for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
{
int rc = RTStrUtf8ToCurrentCP(&papsz[iVar], pIntEnv->papszEnv[iVar]);
if (RT_FAILURE(rc))
{
/* RTEnvDestroy / we cleans up later. */
papsz[iVar] = NULL;
AssertRC(rc);
papszRet = NULL;
break;
}
}
}
RTENV_UNLOCK(pIntEnv);
}
return papszRet;
}