VirtualBox

Changeset 4475 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Sep 1, 2007 1:21:19 AM (17 years ago)
Author:
vboxsync
Message:

Some adjustments to RTEnv and RTProcCreate. Should work on darwin now.

Location:
trunk/src/VBox/Runtime
Files:
8 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/VBox/RTAssertDoBreakpoint-vbox.cpp

    r4071 r4475  
    8787        };
    8888        RTPROCESS Process;
    89         int rc = RTProcCreate(apszArgs[0], &apszArgs[0], NULL, 0, &Process);
     89        int rc = RTProcCreate(apszArgs[0], &apszArgs[0], RTENV_DEFAULT, 0, &Process);
    9090        if (RT_FAILURE(rc))
    9191            return false;
  • trunk/src/VBox/Runtime/generic/env-generic.cpp

    r4474 r4475  
    2323#include <iprt/assert.h>
    2424#include <iprt/alloc.h>
     25#include <iprt/alloca.h>
    2526#include <iprt/string.h>
    2627#include <iprt/err.h>
    27 
    28 #if defined(RT_OS_WINDOWS)
    29 # include <stdlib.h>
    30 #else
     28#include "internal/magics.h"
     29
     30#include <stdlib.h>
     31#if !defined(RT_OS_WINDOWS)
    3132# include <unistd.h>
    3233#endif
    33 
    34 #include <string.h>
    35 
    3634#if defined(RT_OS_SOLARIS)
    37 /* It's an implementation detail in Solaris, see
    38  * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/getenv.c line 50.
     35__BEGIN_DECLS
     36extern char **environ;
     37__END_DECLS
     38#endif
     39
     40/*******************************************************************************
     41*   Defined Constants And Macros                                               *
     42*******************************************************************************/
     43/** Macro that unlocks the specified environment block. */
     44#define RTENV_LOCK(pEnvInt)     do { } while (0)
     45/** Macro that unlocks the specified environment block. */
     46#define RTENV_UNLOCK(pEnvInt)   do { } while (0)
     47
     48
     49/*******************************************************************************
     50*   Structures and Typedefs                                                    *
     51*******************************************************************************/
     52/**
     53 * The internal representation of a (non-default) environment.
    3954 */
    40 extern char **environ;
    41 #endif
    42 
    43 struct RTENVINTERNAL
    44 {
    45     /* Array of environment variables. */
    46     char **apszEnv;
    47     /* Count of variables in the array. */
    48     size_t cCount;
    49     /* Capacity (real size) of the array. This includes space for the
    50      * terminating NULL element (for compatibility with the C library), so
    51      * that cCount <= cCapacity - 1. */
    52     size_t cCapacity;
    53 };
    54 
    55 #define RTENV_GROW_SIZE 16
    56 
    57 static int rtEnvCreate(struct RTENVINTERNAL **ppIntEnv, size_t cCapacity)
    58 {
    59     int rc;
    60 
     55typedef struct RTENVINTERNAL
     56{
     57    /** Magic value . */
     58    uint32_t    u32Magic;
     59    /** Number of variables in the array.
     60     * This does not include the terminating NULL entry. */
     61    size_t      cVars;
     62    /** Capacity (allocated size) of the array.
     63     * This includes space for the terminating NULL element (for compatibility
     64     * with the C library), so that c <= cCapacity - 1. */
     65    size_t      cAllocated;
     66    /** Array of environment variables. */
     67    char      **papszEnv;
     68    /** Array of environment variables in the process CP.
     69     * This get (re-)constructed when RTEnvGetExecEnvP method is called. */
     70    char      **papszEnvOtherCP;
     71} RTENVINTERNAL, *PRTENVINTERNAL;
     72
     73/** The allocation granularity of the RTENVINTERNAL::papszEnv memory. */
     74#define RTENV_GROW_SIZE     16
     75
     76
     77/**
     78 * Internal worker that resolves the pointer to the default
     79 * process environment. (environ)
     80 *
     81 * @returns Pointer to the default environment.
     82 *          This may be NULL.
     83 */
     84static const char * const *rtEnvDefault(void)
     85{
     86#ifdef RT_OS_DARWIN
     87    return *(_NSGetEnviron());
     88#elif defined(RT_OS_L4) 
     89    /* So far, our L4 libraries do not include environment support. */
     90    return NULL;
     91#else
     92    return environ;
     93#endif
     94}
     95
     96
     97/**
     98 * Internal worker that creates an environment handle with a specified capacity.
     99 *
     100 * @returns IPRT status code.
     101 * @param   ppIntEnv    Where to store the result.
     102 * @param   cAllocated  The initial array size.
     103 */
     104static int rtEnvCreate(PRTENVINTERNAL *ppIntEnv, size_t cAllocated)
     105{
    61106    /*
    62107     * Allocate environment handle.
    63108     */
    64     struct RTENVINTERNAL *pIntEnv = (struct RTENVINTERNAL *)RTMemAlloc(sizeof(struct RTENVINTERNAL));
     109    PRTENVINTERNAL pIntEnv = (PRTENVINTERNAL)RTMemAlloc(sizeof(*pIntEnv));
    65110    if (pIntEnv)
    66111    {
    67         cCapacity = (cCapacity + RTENV_GROW_SIZE - 1)
    68                     / RTENV_GROW_SIZE * RTENV_GROW_SIZE;
    69112        /*
    70113         * Pre-allocate the variable array.
    71114         */
    72         pIntEnv->cCount = 0;
    73         pIntEnv->cCapacity = cCapacity;
    74         pIntEnv->apszEnv = (char **)RTMemAlloc(sizeof(pIntEnv->apszEnv[0]) * pIntEnv->cCapacity);
    75         if (pIntEnv->apszEnv)
    76         {
    77             /* add terminating NULL */
    78             pIntEnv->apszEnv[0] = NULL;
     115        pIntEnv->u32Magic = RTENV_MAGIC;
     116        pIntEnv->papszEnvOtherCP = NULL;
     117        pIntEnv->cVars = 0;
     118        pIntEnv->cAllocated = RT_ALIGN_Z(RT_MAX(cAllocated, RTENV_GROW_SIZE), RTENV_GROW_SIZE);
     119        pIntEnv->papszEnv = (char **)RTMemAllocZ(sizeof(pIntEnv->papszEnv[0]) * pIntEnv->cAllocated);
     120        if (pIntEnv->papszEnv)
     121        {
    79122            *ppIntEnv = pIntEnv;
    80123            return VINF_SUCCESS;
    81124        }
    82125
    83         rc = VERR_NO_MEMORY;
    84126        RTMemFree(pIntEnv);
    85127    }   
     128
     129    return VERR_NO_MEMORY;
     130}
     131
     132
     133RTDECL(int) RTEnvCreate(PRTENV pEnv)
     134{
     135    AssertPtrReturn(pEnv, VERR_INVALID_POINTER);
     136    return rtEnvCreate(pEnv, RTENV_GROW_SIZE);
     137}
     138
     139
     140RTDECL(int) RTEnvDestroy(RTENV Env)
     141{
     142    /*
     143     * Ignore NIL_RTENV and validate input.
     144     */
     145    if (    Env == NIL_RTENV
     146        ||  Env == RTENV_DEFAULT)
     147        return VINF_SUCCESS;
     148
     149    PRTENVINTERNAL pIntEnv = Env;
     150    AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
     151    AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
     152
     153    /*
     154     * Do the cleanup.
     155     */
     156    RTENV_LOCK(pIntEnv);
     157    pIntEnv->u32Magic++;
     158    size_t iVar = pIntEnv->cVars;
     159    while (iVar-- > 0)
     160        RTStrFree(pIntEnv->papszEnv[iVar]);
     161    RTMemFree(pIntEnv->papszEnv);
     162    pIntEnv->papszEnv = NULL;
     163
     164    if (pIntEnv->papszEnvOtherCP)
     165    {
     166        for (iVar = 0; pIntEnv->papszEnvOtherCP[iVar]; iVar++)
     167        {
     168            RTStrFree(pIntEnv->papszEnvOtherCP[iVar]);
     169            pIntEnv->papszEnvOtherCP[iVar] = NULL;
     170        }
     171        RTMemFree(pIntEnv->papszEnvOtherCP);
     172        pIntEnv->papszEnvOtherCP = NULL;
     173    }
     174
     175    RTENV_UNLOCK(pIntEnv);
     176    /*RTCritSectDelete(&pIntEnv->CritSect) */
     177    RTMemFree(pIntEnv);
     178   
     179    return VINF_SUCCESS;
     180}
     181
     182
     183RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone)
     184{
     185    /*
     186     * Validate input and figure out how many variable to clone and where to get them.
     187     */
     188    size_t cVars;
     189    const char * const *papszEnv;
     190    PRTENVINTERNAL pIntEnvToClone;
     191    AssertPtrReturn(pEnv, VERR_INVALID_POINTER);
     192    if (EnvToClone == RTENV_DEFAULT)
     193    {
     194        pIntEnvToClone = NULL;
     195        papszEnv = rtEnvDefault();
     196        cVars = 0;
     197        if (papszEnv)
     198            while (papszEnv[cVars])
     199                cVars++;
     200    }
    86201    else
    87         rc = VERR_NO_MEMORY;
    88 
     202    {
     203        pIntEnvToClone = EnvToClone;
     204        AssertPtrReturn(pIntEnvToClone, VERR_INVALID_HANDLE);
     205        AssertReturn(pIntEnvToClone->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
     206        RTENV_LOCK(pIntEnvToClone);
     207
     208        papszEnv = pIntEnvToClone->papszEnv;
     209        cVars = pIntEnvToClone->cVars;
     210    }
     211
     212    /*
     213     * Create the duplicate.
     214     */
     215    PRTENVINTERNAL pIntEnv;
     216    int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */);
     217    if (RT_SUCCESS(rc))
     218    {
     219        pIntEnv->cVars = cVars;
     220        pIntEnv->papszEnv[pIntEnv->cVars] = NULL;
     221        if (EnvToClone == RTENV_DEFAULT)
     222        {
     223            /* ASSUMES the default environment is in the current codepage. */
     224            for (size_t iVar = 0; iVar < cVars; iVar++)
     225            {
     226                int rc = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iVar], papszEnv[iVar]);
     227                if (RT_FAILURE(rc))
     228                {
     229                    pIntEnv->cVars = iVar;
     230                    RTEnvDestroy(pIntEnv);
     231                    return rc;
     232                }
     233            }
     234        }
     235        else
     236        {
     237            for (size_t iVar = 0; iVar < cVars; iVar++)
     238            {
     239                char *pszVar = RTStrDup(papszEnv[iVar]);
     240                if (RT_UNLIKELY(!pszVar))
     241                {
     242                    RTENV_UNLOCK(pIntEnvToClone);
     243
     244                    pIntEnv->cVars = iVar;
     245                    RTEnvDestroy(pIntEnv);
     246                    return rc;
     247                }
     248                pIntEnv->papszEnv[iVar] = pszVar;
     249            }
     250        }
     251
     252        /* done */
     253        *pEnv = pIntEnv;
     254    }
     255
     256    if (pIntEnvToClone)
     257        RTENV_UNLOCK(pIntEnvToClone);
    89258    return rc;
    90259}
    91260
    92 /**
    93  * Creates an empty environment block.
    94  *
    95  * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
    96  *
    97  * @param   pEnv        Where to store the handle of the environment block.
    98  */
    99 RTDECL(int) RTEnvCreate(PRTENV pEnv)
    100 {
    101     if (pEnv == NULL)
    102         return VERR_INVALID_POINTER;
    103 
    104     return rtEnvCreate(pEnv, RTENV_GROW_SIZE);
    105 }
    106 
    107 /**
    108  * Destroys an environment block.
    109  *
    110  * @returns IPRT status code.
    111  *
    112  * @param   Env     Handle of the environment block.
    113  */
    114 RTDECL(int) RTEnvDestroy(RTENV Env)
    115 {
    116     struct RTENVINTERNAL *pIntEnv = Env;
    117 
    118     if (pIntEnv == NULL)
    119         return VERR_INVALID_HANDLE;
    120 
    121     for (size_t i = 0; i < pIntEnv->cCount; ++i)
    122     {
    123         RTStrFree(pIntEnv->apszEnv[i]);
    124     }
    125 
    126     RTMemFree(pIntEnv->apszEnv);
    127     RTMemFree(pIntEnv);
    128     return VINF_SUCCESS;
    129 }
    130 
    131 /**
    132  * Creates an environment block and fill it with variables from the given
    133  * environment array.
    134  *
    135  * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
    136  *
    137  * @param   pEnv        Where to store the handle of the environment block.
    138  * @param   apszEnv     Pointer to the NULL-terminated array of environment
    139  *                      variables. If NULL, the current process' environment
    140  *                      will be cloned.
    141  */
    142 RTDECL(int) RTEnvClone(PRTENV pEnv, char const *const *apszEnv)
    143 {
    144 #ifndef RT_OS_L4  /* So far, our L4 libraries do not include environment support. */
    145     if (apszEnv == NULL)
    146         apszEnv = environ;
    147 
    148     /* count the number of varialbes to clone */
    149     size_t cEnv = 0;
    150     for (; apszEnv[cEnv]; ++cEnv) {}
    151 #else
    152     size_t cEnv = 0;
    153 #endif
    154 
    155     struct RTENVINTERNAL *pIntEnv;
    156 
    157     int rc = rtEnvCreate(&pIntEnv, cEnv + 1 /* NULL */);
    158     if (RT_FAILURE(rc))
    159         return rc;
    160 
    161 #ifndef RT_OS_L4
    162     for (size_t i = 0; i < cEnv; ++i)
    163     {
    164         char *pszVar = RTStrDup(environ[i]);
    165         if (pszVar == NULL)
    166         {
     261
     262RTDECL(int) RTEnvPutEx(RTENV Env, const char *pszVarEqualValue)
     263{
     264    int rc;
     265    AssertPtrReturn(pszVarEqualValue, VERR_INVALID_POINTER);
     266    const char *pszEq = strchr(pszVarEqualValue, '=');
     267    if (!pszEq)
     268        rc = RTEnvUnsetEx(Env, pszVarEqualValue);
     269    else
     270    {
     271        /*
     272         * Make a copy of the variable name so we can terminate it
     273         * properly and then pass the request on to RTEnvSetEx.
     274         */
     275        const char *pszValue = pszEq + 1;
     276
     277        size_t cchVar = pszEq - pszVarEqualValue;
     278        Assert(cchVar < 1024);
     279        char *pszVar = (char *)alloca(cchVar + 1);
     280        memcpy(pszVar, pszVarEqualValue, cchVar);
     281        pszVar[cchVar] = '\0';
     282
     283        rc = RTEnvSetEx(Env, pszVar, pszValue);
     284    }
     285    return rc;
     286}
     287
     288
     289RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue)
     290{
     291    AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
     292    AssertPtrReturn(*pszVar, VERR_INVALID_PARAMETER);
     293    AssertPtrReturn(pszValue, VERR_INVALID_POINTER);
     294
     295    int rc;
     296    if (Env == RTENV_DEFAULT)
     297    {
     298        /*
     299         * Since RTEnvPut isn't UTF-8 clean and actually expects the strings
     300         * to be in the current code page (codeset), we'll do the necessary
     301         * conversions here.
     302         */
     303        char *pszVarOtherCP;
     304        rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
     305        if (RT_SUCCESS(rc))
     306        {
     307            char *pszValueOtherCP;
     308            rc = RTStrUtf8ToCurrentCP(&pszValueOtherCP, pszValue);
     309            if (RT_SUCCESS(rc))
     310            {
     311                rc = RTEnvSet(pszVarOtherCP, pszValueOtherCP);
     312                RTStrFree(pszValueOtherCP);
     313            }
     314            RTStrFree(pszVarOtherCP);
     315        }
     316    }
     317    else
     318    {
     319        PRTENVINTERNAL pIntEnv = Env;
     320        AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
     321        AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
     322
     323        /*
     324         * Create the variable string.
     325         */
     326        const size_t cchVar = strlen(pszVar);
     327        const size_t cchValue = strlen(pszValue);
     328        char *pszEntry = (char *)RTMemAlloc(cchVar + cchValue + 2);
     329        if (pszEntry)
     330        {
     331            memcpy(pszEntry, pszVar, cchVar);
     332            pszEntry[cchVar] = '=';
     333            memcpy(&pszEntry[cchVar + 1], pszValue, cchValue + 1);
     334
     335            RTENV_LOCK(pIntEnv);
     336
     337            /*
     338             * Find the location of the variable. (iVar = cVars if new)
     339             */
     340            rc = VINF_SUCCESS;
     341            size_t iVar;
     342            for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
     343                if (    !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
     344                    &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
     345                    break;
     346            if (iVar < pIntEnv->cVars)
     347            {
     348                /*
     349                 * Replace the current entry. Simple.
     350                 */
     351                RTMemFree(pIntEnv->papszEnv[iVar]);
     352                pIntEnv->papszEnv[iVar] = pszEntry;
     353            }
     354            else
     355            {
     356                /*
     357                 * Adding a new variable. Resize the array if required
     358                 * and then insert the new value at the end.
     359                 */
     360                if (pIntEnv->cVars + 2 > pIntEnv->cAllocated)
     361                {
     362                    void *pvNew = RTMemRealloc(pIntEnv->papszEnv, sizeof(char *) * (pIntEnv->cAllocated + RTENV_GROW_SIZE));
     363                    if (!pvNew)
     364                        rc = VERR_NO_MEMORY;
     365                    else
     366                    {
     367                        pIntEnv->papszEnv = (char **)pvNew;
     368                        pIntEnv->cAllocated += RTENV_GROW_SIZE;
     369                        for (size_t iNewVar = pIntEnv->cVars; iNewVar < pIntEnv->cAllocated; iNewVar++)
     370                            pIntEnv->papszEnv[iNewVar] = NULL;
     371                    }
     372                }
     373                if (RT_SUCCESS(rc))
     374                {
     375                    pIntEnv->papszEnv[iVar] = pszEntry;
     376                    pIntEnv->papszEnv[iVar + 1] = NULL; /* this isn't really necessary, but doesn't hurt. */
     377                    pIntEnv->cVars++;
     378                    Assert(pIntEnv->cVars == iVar + 1);
     379                }
     380            }
     381   
     382            RTENV_UNLOCK(pIntEnv);
     383
     384            if (RT_FAILURE(rc))
     385                RTMemFree(pszEntry);
     386        }
     387        else
    167388            rc = VERR_NO_MEMORY;
    168             break;
    169         }
    170 
    171         pIntEnv->apszEnv[i] = pszVar;
    172         ++pIntEnv->cCount;
    173     }
    174 #endif
    175 
    176     if (RT_SUCCESS(rc))
    177     {
    178         /* add terminating NULL */
    179         pIntEnv->apszEnv[pIntEnv->cCount] = NULL;
    180         *pEnv = pIntEnv;
    181         return VINF_SUCCESS;
    182     }
    183 
    184     RTEnvDestroy(pIntEnv);
     389    }
    185390    return rc;
    186391}
    187392
    188 static int rtEnvRemoveVars(struct RTENVINTERNAL *pIntEnv, size_t iFrom, size_t cVars)
    189 {
    190     AssertReturn (iFrom < pIntEnv->cCount, VERR_GENERAL_FAILURE);
    191     AssertReturn (cVars <= pIntEnv->cCount, VERR_GENERAL_FAILURE);
    192     AssertReturn (cVars > 0, VERR_GENERAL_FAILURE);
    193 
    194     /* free variables */
    195     size_t iTo = iFrom + cVars - 1;
    196     for (size_t i = iFrom; i <= iTo; ++i)
    197         RTStrFree(pIntEnv->apszEnv[i]);
    198 
    199     /* remove the hole */
    200     size_t cToMove = pIntEnv->cCount - iTo - 1;
    201     if (cToMove)
    202         memcpy(&pIntEnv->apszEnv[iFrom], &pIntEnv->apszEnv[iTo + 1],
    203                sizeof(pIntEnv->apszEnv[0]) * cToMove);
    204 
    205     pIntEnv->cCount -= cVars;
    206 
    207     /// @todo resize pIntEnv->apszEnv to a multiply of RTENV_GROW_SIZE to keep
    208     /// it compact
    209 
    210     /* add terminating NULL */
    211     pIntEnv->apszEnv[pIntEnv->cCount] = NULL;
    212     return VINF_SUCCESS;
    213 }
    214 
    215 static int rtEnvInsertVars(struct RTENVINTERNAL *pIntEnv, size_t iAt, size_t cVars)
    216 {
    217     AssertReturn (iAt <= pIntEnv->cCount, VERR_GENERAL_FAILURE);
     393
     394RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar)
     395{
     396    AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
     397    AssertPtrReturn(*pszVar, VERR_INVALID_PARAMETER);
    218398
    219399    int rc;
    220 
    221     size_t cCapacity = (pIntEnv->cCount + cVars + 1 /* NULL */ + RTENV_GROW_SIZE - 1)
    222                        / RTENV_GROW_SIZE * RTENV_GROW_SIZE;
    223     bool needAlloc = cCapacity != pIntEnv->cCapacity;
    224 
    225     /* allocate a new variable array if needed */
    226     char **apszEnv = needAlloc ? (char **)RTMemAlloc(sizeof(apszEnv[0]) * cCapacity)
    227                                : pIntEnv->apszEnv;
    228     if (apszEnv)
    229     {
    230         /* copy old variables */
    231         if (needAlloc && iAt)
    232             memcpy (apszEnv, pIntEnv->apszEnv, sizeof(apszEnv[0]) * iAt);
    233         if (iAt < pIntEnv->cCount)
    234             memcpy (&apszEnv[iAt + cVars], &pIntEnv->apszEnv[iAt],
    235                     sizeof(apszEnv[0]) * pIntEnv->cCount - iAt);
    236         /* initialize new variables with NULL */
    237         memset(&apszEnv[iAt], 0, sizeof(apszEnv[0]) * cVars);
    238         /* replace the array */
    239         if (needAlloc)
    240         {
    241             RTMemFree(pIntEnv->apszEnv);
    242             pIntEnv->apszEnv = apszEnv;
    243             pIntEnv->cCapacity = cCapacity;
    244         }
    245         pIntEnv->cCount += cVars;
    246         /* add terminating NULL */
    247         pIntEnv->apszEnv[pIntEnv->cCount] = NULL;
    248         return VINF_SUCCESS;
     400    if (Env == RTENV_DEFAULT)
     401    {
     402        /*
     403         * Since RTEnvUnset isn't UTF-8 clean and actually expects the strings
     404         * to be in the current code page (codeset), we'll do the necessary
     405         * conversions here.
     406         */
     407        char *pszVarOtherCP;
     408        rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
     409        if (RT_SUCCESS(rc))
     410        {
     411            rc = RTEnvUnset(pszVarOtherCP);
     412            RTStrFree(pszVarOtherCP);
     413        }
    249414    }
    250415    else
    251         rc = VERR_NO_MEMORY;
    252 
     416    {
     417        PRTENVINTERNAL pIntEnv = Env;
     418        AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
     419        AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
     420
     421        RTENV_LOCK(pIntEnv);
     422
     423        /*
     424         * Remove all variable by the given name.
     425         */
     426        rc = VINF_ENV_VAR_NOT_FOUND;
     427        const size_t cchVar = strlen(pszVar);
     428        size_t iVar;
     429        for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
     430            if (    !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
     431                &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
     432            {
     433                RTMemFree(pIntEnv->papszEnv[iVar]);
     434                pIntEnv->cVars--;
     435                if (pIntEnv->cVars > 0)
     436                    pIntEnv->papszEnv[iVar] = pIntEnv->papszEnv[pIntEnv->cVars];
     437                pIntEnv->papszEnv[pIntEnv->cVars] = NULL;
     438                rc = VINF_SUCCESS;
     439                /* no break, there could be more. */
     440            }
     441
     442        RTENV_UNLOCK(pIntEnv);
     443    }
    253444    return rc;
    254 }
    255 
    256 static int rtEnvSetEx(struct RTENVINTERNAL *pIntEnv,
    257                       const char *pszVar, size_t cchVar,
    258                       const char *pszValue)
    259 {
    260     AssertReturn (pszVar != NULL, VERR_GENERAL_FAILURE);
    261 
    262     size_t i = 0;
    263     for (; i < pIntEnv->cCount; ++i)
    264     {
    265         if ((cchVar == 0 && !*pszVar) ||
    266             strncmp(pIntEnv->apszEnv[i], pszVar, cchVar) == 0)
    267         {
    268             if (pszValue == NULL)
    269                 return rtEnvRemoveVars(pIntEnv, i, 1);
    270 
    271             break;
    272         }
    273     }
    274 
    275     /* allocate a new variable */
    276     size_t cchNew = cchVar + 1 + strlen(pszValue) + 1;
    277     char *pszNew = (char *)RTMemAlloc(cchNew);
    278     if (pszNew == NULL)
    279         return VERR_NO_MEMORY;
    280     memcpy(pszNew, pszVar, cchVar);
    281     pszNew[cchVar] = '=';
    282     strcpy(pszNew + cchVar + 1, pszValue);
    283 
    284     if (i < pIntEnv->cCount)
    285     {
    286         /* replace the old variable */
    287         RTStrFree(pIntEnv->apszEnv[i]);
    288         pIntEnv->apszEnv[i] = pszNew;
    289         return VINF_SUCCESS;
    290     }
    291 
    292     /* nothing to do to remove a non-existent variable */
    293     if (pszValue == NULL)
    294         return VINF_SUCCESS;
    295 
    296     /* insert the new variable */
    297     int rc = rtEnvInsertVars(pIntEnv, i, 1);
    298     if (RT_SUCCESS(rc))
    299     {
    300         pIntEnv->apszEnv[i] = pszNew;
    301         return VINF_SUCCESS;
    302     }
    303 
    304     RTStrFree(pszNew);
     445   
     446}
     447
     448
     449RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual)
     450{
     451    AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
     452    AssertPtrNullReturn(pszValue, VERR_INVALID_POINTER);
     453    AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER);
     454    AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER);
     455
     456    if (pcchActual)
     457        *pcchActual = 0;
     458    int rc;
     459    if (Env == RTENV_DEFAULT)
     460    {
     461        /*
     462         * Since RTEnvGet isn't UTF-8 clean and actually expects the strings
     463         * to be in the current code page (codeset), we'll do the necessary
     464         * conversions here.
     465         */
     466        char *pszVarOtherCP;
     467        rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
     468        if (RT_SUCCESS(rc))
     469        {
     470            const char *pszValueOtherCP = RTEnvGet(pszVarOtherCP);
     471            RTStrFree(pszVarOtherCP);
     472            if (pszValueOtherCP)
     473            {
     474                char *pszValueUtf8;
     475                rc = RTStrCurrentCPToUtf8(&pszValueUtf8, pszValueOtherCP);
     476                if (RT_SUCCESS(rc))
     477                {
     478                    rc = VINF_SUCCESS;
     479                    size_t cch = strlen(pszValueUtf8);
     480                    if (pcchActual)
     481                        *pcchActual = cch;
     482                    if (pszValue && cbValue)
     483                    {
     484                        if (cch < cbValue)
     485                            memcpy(pszValue, pszValueUtf8, cch + 1);
     486                        else
     487                            rc = VERR_BUFFER_OVERFLOW;
     488                    }
     489                }
     490            }
     491            else
     492                rc = VERR_ENV_VAR_NOT_FOUND;
     493        }
     494    }
     495    else
     496    {
     497        PRTENVINTERNAL pIntEnv = Env;
     498        AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
     499        AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
     500
     501        RTENV_LOCK(pIntEnv);
     502
     503        /*
     504         * Locate the first variable and return it to the caller.
     505         */
     506        rc = VERR_ENV_VAR_NOT_FOUND;
     507        const size_t cchVar = strlen(pszVar);
     508        size_t iVar;
     509        for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
     510            if (    !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
     511                &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
     512            {
     513                rc = VINF_SUCCESS;
     514                const char *pszValueOrg = pIntEnv->papszEnv[iVar] + cchVar + 1;
     515                size_t cch = strlen(pszValueOrg);
     516                if (pcchActual)
     517                    *pcchActual = cch;
     518                if (pszValue && cbValue)
     519                {
     520                    if (cch < cbValue)
     521                        memcpy(pszValue, pszValueOrg, cch + 1);
     522                    else
     523                        rc = VERR_BUFFER_OVERFLOW;
     524                }
     525                break;
     526            }
     527
     528        RTENV_UNLOCK(pIntEnv);
     529    }
    305530    return rc;
    306 }
    307 
    308 /**
    309  * Puts a 'variable=value' string into the environment.
    310  *
    311  * The supplied string must be in the current process' codepage.
    312  * This function makes a copy of the supplied string.
    313  *
    314  * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
    315  *
    316  * @param   Env                 Handle of the environment block.
    317  * @param   pszVarEqualValue    The variable '=' value string. If the value and '=' is
    318  *                              omitted, the variable is removed from the environment.
    319  */
    320 RTDECL(int) RTEnvPutEx(RTENV Env, const char *pszVarEqualValue)
    321 {
    322     struct RTENVINTERNAL *pIntEnv = Env;
    323 
    324     if (pIntEnv == NULL)
    325         return VERR_INVALID_HANDLE;
    326 
    327     if (pszVarEqualValue == NULL)
    328         return VERR_INVALID_POINTER;
    329 
    330     const char *pszEq = strchr(pszVarEqualValue, '=');
    331     return rtEnvSetEx(pIntEnv, pszVarEqualValue,
    332                       pszEq ? pszEq - pszVarEqualValue
    333                             : strlen (pszVarEqualValue),
    334                       pszEq ? pszEq + 1 : NULL);
    335 }
    336 
    337 /**
    338  * Returns a raw pointer to the array of environment variables of the given
    339  * environment block where every variable is a string in format
    340  * 'variable=value'.
    341  *
    342  * All returned strings are in the current process' codepage.
    343  *
    344  * @returns Pointer to the raw array of environment variables.
    345  * @returns NULL if Env is NULL or invalid.
    346  *
    347  * @param   Env                 Handle of the environment block.
    348  */
    349 RTDECL(char const *const *) RTEnvGetArray(RTENV Env)
    350 {
    351     struct RTENVINTERNAL *pIntEnv = Env;
    352 
    353     if (pIntEnv == NULL)
    354         return NULL;
    355 
    356     return pIntEnv->apszEnv;
    357 }
     531   
     532}
     533
     534
     535RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar)
     536{
     537    AssertPtrReturn(pszVar, false);
     538
     539    bool fExist = false;
     540    if (Env == RTENV_DEFAULT)
     541    {
     542        /*
     543         * Since RTEnvExist isn't UTF-8 clean and actually expects the strings
     544         * to be in the current code page (codeset), we'll do the necessary
     545         * conversions here.
     546         */
     547        char *pszVarOtherCP;
     548        int rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
     549        if (RT_SUCCESS(rc))
     550        {
     551            fExist = RTEnvExist(pszVarOtherCP);
     552            RTStrFree(pszVarOtherCP);
     553        }
     554    }
     555    else
     556    {
     557        PRTENVINTERNAL pIntEnv = Env;
     558        AssertPtrReturn(pIntEnv, false);
     559        AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, false);
     560
     561        RTENV_LOCK(pIntEnv);
     562
     563        /*
     564         * Simple search.
     565         */
     566        const size_t cchVar = strlen(pszVar);
     567        for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
     568            if (    !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
     569                &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
     570            {
     571                fExist = true;
     572                break;
     573            }
     574
     575        RTENV_UNLOCK(pIntEnv);
     576    }
     577    return fExist;
     578}
     579
     580
     581RTDECL(char const * const *) RTEnvGetExecEnvP(RTENV Env)
     582{
     583    const char * const *papszRet;
     584    if (Env == RTENV_DEFAULT)
     585    {
     586        papszRet = rtEnvDefault();
     587        if (!papszRet)
     588        {
     589            static const char * const s_papszDummy[2] = { NULL, NULL };
     590            papszRet = &s_papszDummy[0];
     591        }
     592    }
     593    else
     594    {
     595        PRTENVINTERNAL pIntEnv = Env;
     596        AssertPtrReturn(pIntEnv, NULL);
     597        AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, NULL);
     598
     599        RTENV_LOCK(pIntEnv);
     600
     601        /*
     602         * Free any old envp.
     603         */
     604        if (pIntEnv->papszEnvOtherCP)
     605        {
     606            for (size_t iVar = 0; pIntEnv->papszEnvOtherCP[iVar]; iVar++)
     607            {
     608                RTStrFree(pIntEnv->papszEnvOtherCP[iVar]);
     609                pIntEnv->papszEnvOtherCP[iVar] = NULL;
     610            }
     611            RTMemFree(pIntEnv->papszEnvOtherCP);
     612            pIntEnv->papszEnvOtherCP = NULL;
     613        }
     614
     615        /*
     616         * Construct a new envp with the strings in the process code set.
     617         */
     618        char **papsz;
     619        papszRet = pIntEnv->papszEnvOtherCP = papsz = (char **)RTMemAlloc(sizeof(char *) * (pIntEnv->cVars + 1));
     620        if (papsz)
     621        {
     622            papsz[pIntEnv->cVars] = NULL;
     623            for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
     624            {
     625                int rc = RTStrUtf8ToCurrentCP(&papsz[iVar], pIntEnv->papszEnv[iVar]);
     626                if (RT_FAILURE(rc))
     627                {
     628                    /* RTEnvDestroy / we cleans up later. */
     629                    papsz[iVar] = NULL;
     630                    AssertRC(rc);
     631                    papszRet = NULL;
     632                    break;
     633                }
     634            }
     635        }
     636
     637        RTENV_UNLOCK(pIntEnv);
     638    }
     639    return papszRet;
     640}
  • trunk/src/VBox/Runtime/include/internal/magics.h

    r4071 r4475  
    2222 * @{ */
    2323
     24/** The value of RTENVINTERNAL::u32Magic. (Rumiko Takahashi) */
     25#define RTENV_MAGIC                 0x19571010
    2426/** The value of RTDIR::u32Magic. (Michael Ende) */
    2527#define RTDIR_MAGIC                 0x19291112
  • trunk/src/VBox/Runtime/r3/posix/env-posix.cpp

    r4071 r4475  
    2323#include <iprt/string.h>
    2424#include <iprt/alloca.h>
     25#include <iprt/assert.h>
    2526
    2627#include <stdlib.h>
     
    7677}
    7778
     79
     80RTDECL(int) RTEnvUnset(const char *pszVar)
     81{
     82    AssertReturn(!strchr(pszVar, '='), VERR_INVALID_PARAMETER);
     83
     84    /* Check that it exists first.  */
     85    if (!RTEnvExist(pszVar))
     86        return VINF_ENV_VAR_NOT_FOUND;
     87
     88    /* Ok, try remove it. */
     89    if (!putenv((char *)pszVar))
     90        return VINF_SUCCESS;
     91    return RTErrConvertFromErrno(errno);
     92}
     93
  • trunk/src/VBox/Runtime/r3/posix/process-posix.cpp

    r4071 r4475  
    4242#include <iprt/assert.h>
    4343#include <iprt/err.h>
     44#include <iprt/env.h>
    4445#include "internal/process.h"
    4546
    4647
    4748
    48 RTR3DECL(int)   RTProcCreate(const char *pszExec, const char * const *papszArgs, const char * const *papszEnv, unsigned fFlags, PRTPROCESS pProcess)
     49RTR3DECL(int)   RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
    4950{
    5051    /*
    5152     * Validate input.
    5253     */
    53     if (!pszExec || !*pszExec)
    54     {
    55         AssertMsgFailed(("no exec\n"));
    56         return VERR_INVALID_PARAMETER;
    57     }
    58     if (fFlags)
    59     {
    60         AssertMsgFailed(("invalid flags!\n"));
    61         return VERR_INVALID_PARAMETER;
    62     }
     54    AssertPtrReturn(pszExec, VERR_INVALID_POINTER);
     55    AssertReturn(*pszExec, VERR_INVALID_PARAMETER);
     56    AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
     57    AssertReturn(Env != NIL_RTENV, VERR_INVALID_PARAMETER);
     58    const char * const *papszEnv = RTEnvGetExecEnvP(Env);
     59    AssertPtrReturn(papszEnv, VERR_INVALID_HANDLE);
    6360    /* later: path searching. */
    6461
     
    10097    /** @todo check if it requires any of those two attributes, don't remember atm. */
    10198    int rc = posix_spawn(&pid, pszExec, NULL, NULL, (char * const *)papszArgs,
    102                          papszEnv ? (char * const *)papszEnv : environ);
     99                         (char * const *)papszEnv);
    103100    if (!rc)
    104101    {
     
    114111    {
    115112        int rc;
    116         if (papszEnv)
    117             rc = execve(pszExec, (char * const *)papszArgs, (char * const *)papszEnv);
    118         else
    119             rc = execv(pszExec, (char * const *)papszArgs);
     113        rc = execve(pszExec, (char * const *)papszArgs, (char * const *)papszEnv);
    120114        AssertReleaseMsgFailed(("execve returns %d errno=%d\n", rc, errno));
    121115        exit(127);
  • trunk/src/VBox/Runtime/r3/win32/process-win32.cpp

    r4071 r4475  
    2929#include <iprt/assert.h>
    3030#include <iprt/err.h>
     31#include <iprt/env.h>
    3132
    3233
     
    6970/** @todo r=michael This function currently does not work correctly if the arguments
    7071                    contain spaces. */
    71 RTR3DECL(int)   RTProcCreate(const char *pszExec, const char * const *papszArgs, const char * const *papszEnv, unsigned fFlags, PRTPROCESS pProcess)
     72RTR3DECL(int)   RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
    7273{
    7374    /*
    7475     * Validate input.
    7576     */
    76     if (!pszExec || !*pszExec)
    77     {
    78         AssertMsgFailed(("no exec\n"));
    79         return VERR_INVALID_PARAMETER;
    80     }
    81     if (fFlags)
    82     {
    83         AssertMsgFailed(("invalid flags!\n"));
    84         return VERR_INVALID_PARAMETER;
    85     }
     77    AssertPtrReturn(pszExec, VERR_INVALID_POINTER);
     78    AssertReturn(*pszExec, VERR_INVALID_PARAMETER);
     79    AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
     80    AssertReturn(Env != NIL_RTENV, VERR_INVALID_PARAMETER);
     81    const char * const *papszEnv = RTEnvGetExecEnvP(Env);
     82    AssertPtrReturn(papszEnv, VERR_INVALID_HANDLE);
    8683    /* later: path searching. */
    87 
     84   
    8885    /*
    8986     * Spawn the child.
  • trunk/src/VBox/Runtime/testcase/Makefile.kmk

    r4176 r4475  
    2020ifdef VBOX_WITH_TESTCASES
    2121PROGRAMS = \
     22        tstAvl \
     23        tstBitOperations \
    2224        tstCritSect \
    23         tstPrfRT \
     25        tstDeadlock \
     26        tstDir \
     27        tstDir-2 \
     28        tstEnv \
     29        tstErrUnique \
     30        tstFile \
     31        tstFileLock \
     32        tstHeapSimple \
     33        tstInlineAsm \
    2434        tstLdr \
    2535        tstLdr-2 \
     
    2737        tstLdr-4 \
    2838        tstLdrLoad \
    29         tstAvl \
    30         tstTSC \
    31         tstTimer \
     39        tstLog \
     40        tstMove \
     41        tstPath \
     42        tstPrfRT \
     43        tstRTFsQueries \
     44        tstStrFormat \
     45        tstStrToNum \
    3246        tstTime \
    3347        tstTime-2 \
    3448        tstTime-3 \
     49        tstTimer \
    3550        tstTimeSpec \
    36         tstStrFormat \
    37         tstPath \
    38         tstLog \
    39         tstFile \
    40         tstFileLock \
    41         tstBitOperations \
    42         tstInlineAsm \
    43         tstStrToNum \
    44         tstDir \
    45         tstDir-2 \
    46         tstRTFsQueries \
    47         tstMove \
     51        tstTSC \
    4852        tstUtf8 \
    49         tstDeadlock \
    50         tstUuid \
    51         tstErrUnique \
    52         tstHeapSimple
     53        tstUuid
    5354PROGRAMS.win = \
    5455        tstRTProcWait \
     
    228229tstUuid_SOURCES = tstUuid.cpp
    229230
     231tstEnv_SOURCES = tstEnv.cpp
     232
    230233tstErrUnique_SOURCES = tstErrUnique.cpp
    231234tstErrUnique_INCS    = $(PATH_TARGET)/..
  • trunk/src/VBox/Runtime/testcase/tstEnv.cpp

    r4474 r4475  
    11/* $Id$ */
    22/** @file
    3  * innotek Portable Runtime Testcase - Log Formatting.
     3 * innotek Portable Runtime Testcase - Environment.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2007 innotek GmbH
     7 * Copyright (C) 2007 innotek GmbH
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1919*   Header Files                                                               *
    2020*******************************************************************************/
    21 #include <iprt/log.h>
     21#include <iprt/env.h>
    2222#include <iprt/runtime.h>
    2323#include <iprt/err.h>
    24 
    25 #include <stdio.h>
     24#include <iprt/stream.h>
     25
    2626
    2727int main()
    2828{
    2929    RTR3Init();
    30     printf("tstLog: Requires manual inspection of the log output!\n");
    31     RTLogPrintf("%%Vrc %d: %Vrc\n", VERR_INVALID_PARAMETER, VERR_INVALID_PARAMETER);
    32     RTLogPrintf("%%Vrs %d: %Vrs\n", VERR_INVALID_PARAMETER, VERR_INVALID_PARAMETER);
    33     RTLogPrintf("%%Vrf %d: %Vrf\n", VERR_INVALID_PARAMETER, VERR_INVALID_PARAMETER);
    34     RTLogPrintf("%%Vra %d: %Vra\n", VERR_INVALID_PARAMETER, VERR_INVALID_PARAMETER);
    35 
    36     RTLogPrintf("%%Vt: %Vt\n");
    37 
    38     static uint8_t au8Hex[256];
    39     for (unsigned iHex = 0; iHex < sizeof(au8Hex); iHex++)
    40         au8Hex[iHex] = (uint8_t)iHex;
    41     RTLogPrintf("%%Vhxs   : %Vhxs\n", &au8Hex[0]);
    42     RTLogPrintf("%%.32Vhxs: %.32Vhxs\n", &au8Hex[0]);
    43 
    44     RTLogPrintf("%%Vhxd   :\n%Vhxd\n", &au8Hex[0]);
    45     RTLogPrintf("%%.64Vhxd:\n%.64Vhxd\n", &au8Hex[0]);
    46     RTLogPrintf("%%.*Vhxd:\n%.*Vhxd\n", 64, &au8Hex[0]);
    47     RTLogPrintf("%%32.256Vhxd : \n%32.256Vhxd\n", &au8Hex[0]);
    48     RTLogPrintf("%%32.*Vhxd : \n%32.*Vhxd\n", 256, &au8Hex[0]);
    49     RTLogPrintf("%%7.32Vhxd : \n%7.32Vhxd\n", &au8Hex[0]);
    50     RTLogPrintf("%%7.*Vhxd : \n%7.*Vhxd\n", 32, &au8Hex[0]);
    51     RTLogPrintf("%%*.*Vhxd : \n%*.*Vhxd\n", 7, 32, &au8Hex[0]);
    52 
    53     RTLogPrintf("%%VGp: %VGp\n", (RTGCPHYS)0x87654321);
    54     RTLogPrintf("%%VGv: %VGv\n", (RTGCPTR)0x87654321);
    55     RTLogPrintf("%%VHp: %VHp\n", (RTGCPHYS)0x87654321);
    56     RTLogPrintf("%%VHv: %VHv\n", (RTGCPTR)0x87654321);
    57 
    58     RTLogPrintf("%%VI8 : %VI8\n", (uint8_t)808);
    59     RTLogPrintf("%%VI16: %VI16\n", (uint16_t)16016);
    60     RTLogPrintf("%%VI32: %VI32\n", _1G);
    61     RTLogPrintf("%%VI64: %VI64\n", _1E);
    62 
    63     RTLogPrintf("%%VU8 : %VU8\n", (uint8_t)808);
    64     RTLogPrintf("%%VU16: %VU16\n", (uint16_t)16016);
    65     RTLogPrintf("%%VU32: %VU32\n", _2G32);
    66     RTLogPrintf("%%VU64: %VU64\n", _2E);
    67 
    68     RTLogPrintf("%%VX8 : %VX8 %#VX8\n",   (uint8_t)808, (uint8_t)808);
    69     RTLogPrintf("%%VX16: %VX16 %#VX16\n", (uint16_t)16016, (uint16_t)16016);
    70     RTLogPrintf("%%VX32: %VX32 %#VX32\n", _2G32, _2G32);
    71     RTLogPrintf("%%VX64: %VX64 %#VX64\n", _2E, _2E);
    72 
    73     RTLogFlush(NULL);
    74 
    75     return 0;
     30    RTPrintf("tstEnv: TESTING...\n");
     31
     32    int cErrors = 0;
     33
     34#define CHECK(expr)  do { if (!(expr)) { RTPrintf("tstEnv: error line %d: %s\n", __LINE__, #expr); cErrors++; } } while (0)
     35#define CHECK_RC(expr, rc)  do { int rc2 = expr; if (rc2 != (rc)) { RTPrintf("tstEnv: error line %d: %s -> %Rrc expected %Rrc\n", __LINE__, #expr, rc2, rc); cErrors++; } } while (0)
     36#define CHECK_STR(str1, str2)  do { if (strcmp(str1, str2)) { RTPrintf("tstEnv: error line %d: '%s' != '%s' (*)\n", __LINE__, str1, str2); cErrors++; } } while (0)
     37
     38    /*
     39     * Try mess around with the path a bit.
     40     */
     41#ifdef RT_OS_WINDOWS
     42    static const char * const k_pszPathVar = "Path";
     43#else
     44    static const char * const k_pszPathVar = "PATH";
     45#endif
     46    static const char * const k_pszNonExistantVar = "IPRT_I_DON_T_EXIST";
     47
     48    CHECK(RTEnvExist(k_pszPathVar));
     49    CHECK(RTEnvExistEx(RTENV_DEFAULT, k_pszPathVar));
     50    CHECK(!RTEnvExist(k_pszNonExistantVar));
     51    CHECK(!RTEnvExistEx(RTENV_DEFAULT, k_pszNonExistantVar));
     52
     53    CHECK(RTEnvGet(k_pszPathVar) != NULL);
     54    char szBuf[8192];
     55    size_t cch;
     56    CHECK_RC(RTEnvGetEx(RTENV_DEFAULT, k_pszPathVar, NULL, 0, &cch), VINF_SUCCESS);
     57    CHECK(cch < sizeof(szBuf));
     58    CHECK_RC(RTEnvGetEx(RTENV_DEFAULT, k_pszPathVar, szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     59    CHECK_RC(RTEnvGetEx(RTENV_DEFAULT, k_pszPathVar, szBuf, sizeof(szBuf), NULL), VINF_SUCCESS);
     60    CHECK_RC(RTEnvGetEx(RTENV_DEFAULT, k_pszPathVar, szBuf, 1, &cch), VERR_BUFFER_OVERFLOW);
     61    CHECK_RC(RTEnvGetEx(RTENV_DEFAULT, k_pszPathVar, szBuf, 1, NULL), VERR_BUFFER_OVERFLOW);
     62
     63    /* ditto for a clone. */
     64    RTENV Env;
     65    CHECK_RC(RTEnvClone(&Env, RTENV_DEFAULT), VINF_SUCCESS);
     66
     67    CHECK(RTEnvExistEx(Env, k_pszPathVar));
     68    CHECK(!RTEnvExistEx(Env, k_pszNonExistantVar));
     69
     70    CHECK_RC(RTEnvGetEx(Env, k_pszPathVar, NULL, 0, &cch), VINF_SUCCESS);
     71    CHECK(cch < sizeof(szBuf));
     72    CHECK_RC(RTEnvGetEx(Env, k_pszPathVar, szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     73    CHECK_RC(RTEnvGetEx(Env, k_pszPathVar, szBuf, sizeof(szBuf), NULL), VINF_SUCCESS);
     74    CHECK_RC(RTEnvGetEx(Env, k_pszPathVar, szBuf, 1, &cch), VERR_BUFFER_OVERFLOW);
     75    CHECK_RC(RTEnvGetEx(Env, k_pszPathVar, szBuf, 1, NULL), VERR_BUFFER_OVERFLOW);
     76
     77    /*
     78     * Set and Unset
     79     */
     80    CHECK_RC(RTEnvSetEx(RTENV_DEFAULT, "IPRTMyNewVar", "MyValue1"), VINF_SUCCESS);
     81    CHECK_RC(RTEnvGetEx(RTENV_DEFAULT, "IPRTMyNewVar", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     82    CHECK_STR(szBuf, "MyValue1");
     83    CHECK_RC(RTEnvSetEx(RTENV_DEFAULT, "IPRTMyNewVar", "MyValue2"), VINF_SUCCESS);
     84    CHECK_RC(RTEnvGetEx(RTENV_DEFAULT, "IPRTMyNewVar", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     85    CHECK_STR(szBuf, "MyValue2");
     86
     87    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar", "MyValue1"), VINF_SUCCESS);
     88    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     89    CHECK_STR(szBuf, "MyValue1");
     90    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar", "MyValue2"), VINF_SUCCESS);
     91    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     92    CHECK_STR(szBuf, "MyValue2");
     93
     94    CHECK_RC(RTEnvUnsetEx(Env, "IPRTMyNewVar"), VINF_SUCCESS);
     95    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar", szBuf, sizeof(szBuf), &cch), VERR_ENV_VAR_NOT_FOUND);
     96    CHECK_RC(RTEnvUnsetEx(Env, "IPRTMyNewVar"), VINF_ENV_VAR_NOT_FOUND);
     97
     98    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar0", "MyValue0"), VINF_SUCCESS);
     99    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar1", "MyValue1"), VINF_SUCCESS);
     100    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar2", "MyValue2"), VINF_SUCCESS);
     101    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar3", "MyValue3"), VINF_SUCCESS);
     102    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar4", "MyValue4"), VINF_SUCCESS);
     103    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar5", "MyValue5"), VINF_SUCCESS);
     104    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar6", "MyValue6"), VINF_SUCCESS);
     105    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar7", "MyValue7"), VINF_SUCCESS);
     106    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar8", "MyValue8"), VINF_SUCCESS);
     107    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar9", "MyValue9"), VINF_SUCCESS);
     108    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar10", "MyValue10"), VINF_SUCCESS);
     109    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar11", "MyValue11"), VINF_SUCCESS);
     110    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar12", "MyValue12"), VINF_SUCCESS);
     111    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar13", "MyValue13"), VINF_SUCCESS);
     112    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar14", "MyValue14"), VINF_SUCCESS);
     113    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar15", "MyValue15"), VINF_SUCCESS);
     114    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar16", "MyValue16"), VINF_SUCCESS);
     115    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar17", "MyValue17"), VINF_SUCCESS);
     116    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar18", "MyValue18"), VINF_SUCCESS);
     117    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar19", "MyValue19"), VINF_SUCCESS);
     118    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar20", "MyValue20"), VINF_SUCCESS);
     119    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar21", "MyValue21"), VINF_SUCCESS);
     120    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar22", "MyValue22"), VINF_SUCCESS);
     121    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar23", "MyValue23"), VINF_SUCCESS);
     122    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar24", "MyValue24"), VINF_SUCCESS);
     123    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar25", "MyValue25"), VINF_SUCCESS);
     124    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar26", "MyValue26"), VINF_SUCCESS);
     125    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar27", "MyValue27"), VINF_SUCCESS);
     126    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar28", "MyValue28"), VINF_SUCCESS);
     127    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar29", "MyValue29"), VINF_SUCCESS);
     128    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar30", "MyValue30"), VINF_SUCCESS);
     129    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar31", "MyValue31"), VINF_SUCCESS);
     130    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar32", "MyValue32"), VINF_SUCCESS);
     131    CHECK_RC(RTEnvSetEx(Env, "IPRTMyNewVar33", "MyValue33"), VINF_SUCCESS);
     132    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar30", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     133    CHECK_STR(szBuf, "MyValue30");
     134    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar31", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     135    CHECK_STR(szBuf, "MyValue31");
     136    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar32", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     137    CHECK_STR(szBuf, "MyValue32");
     138    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar33", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     139    CHECK_STR(szBuf, "MyValue33");
     140
     141    CHECK_RC(RTEnvUnsetEx(Env, "IPRTMyNewVar33"), VINF_SUCCESS);
     142    CHECK(!RTEnvExistEx(Env, "IPRTMyNewVar33"));
     143    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar33", szBuf, sizeof(szBuf), &cch), VERR_ENV_VAR_NOT_FOUND);
     144    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar32", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     145    CHECK_STR(szBuf, "MyValue32");
     146    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar15", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     147    CHECK_STR(szBuf, "MyValue15");
     148
     149    CHECK_RC(RTEnvUnsetEx(Env, "IPRTMyNewVar3"), VINF_SUCCESS);
     150    CHECK(!RTEnvExistEx(Env, "IPRTMyNewVar3"));
     151    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar3", szBuf, sizeof(szBuf), &cch), VERR_ENV_VAR_NOT_FOUND);
     152    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar32", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     153    CHECK_STR(szBuf, "MyValue32");
     154    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar15", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     155    CHECK_STR(szBuf, "MyValue15");
     156
     157    CHECK_RC(RTEnvUnsetEx(Env, k_pszPathVar), VINF_SUCCESS);
     158    CHECK(!RTEnvExistEx(Env, k_pszPathVar));
     159    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar32", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     160    CHECK_STR(szBuf, "MyValue32");
     161    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar15", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     162    CHECK_STR(szBuf, "MyValue15");
     163
     164    /*
     165     * Put.
     166     */
     167    CHECK_RC(RTEnvPutEx(Env, "IPRTMyNewVar28"), VINF_SUCCESS);
     168    CHECK(!RTEnvExistEx(Env, "IPRTMyNewVar28"));
     169    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar32", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     170    CHECK_STR(szBuf, "MyValue32");
     171    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar15", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     172    CHECK_STR(szBuf, "MyValue15");
     173
     174    CHECK_RC(RTEnvPutEx(Env, "IPRTMyNewVar28=MyValue28"), VINF_SUCCESS);
     175    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar28", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     176    CHECK_STR(szBuf, "MyValue28");
     177    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar32", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     178    CHECK_STR(szBuf, "MyValue32");
     179    CHECK_RC(RTEnvGetEx(Env, "IPRTMyNewVar15", szBuf, sizeof(szBuf), &cch), VINF_SUCCESS);
     180    CHECK_STR(szBuf, "MyValue15");
     181
     182    /*
     183     * Another cloning.
     184     */
     185    RTENV Env2;
     186    CHECK_RC(RTEnvClone(&Env2, Env), VINF_SUCCESS);
     187    CHECK_RC(RTEnvDestroy(Env2), VINF_SUCCESS);
     188
     189    /*
     190     * execve envp and we're done.
     191     */
     192    const char * const *papsz = RTEnvGetExecEnvP(RTENV_DEFAULT);
     193    CHECK(papsz != NULL);
     194    papsz = RTEnvGetExecEnvP(RTENV_DEFAULT);
     195    CHECK(papsz != NULL);
     196
     197    papsz = RTEnvGetExecEnvP(Env);
     198    CHECK(papsz != NULL);
     199    papsz = RTEnvGetExecEnvP(Env);
     200    CHECK(papsz != NULL);
     201
     202    CHECK_RC(RTEnvDestroy(Env), VINF_SUCCESS);
     203
     204    /*
     205     * Summary
     206     */
     207    if (!cErrors)
     208        RTPrintf("tstEnv: SUCCESS\n");
     209    else
     210        RTPrintf("tstEnv: FAILURE - %d errors\n", cErrors);
     211    return !!cErrors;
    76212}
    77213
  • trunk/src/VBox/Runtime/testcase/tstRTProcWait.cpp

    r4071 r4475  
    2525#include <iprt/stream.h>
    2626#include <iprt/semaphore.h>
     27#include <iprt/env.h>
    2728#include <iprt/err.h>
    2829#include <iprt/string.h>
     
    4344    pArgs->Process = NIL_RTPROCESS;
    4445    const char *apszArgs[3] = { pArgs->pszExe, "child", NULL };
    45     return RTProcCreate(apszArgs[0], apszArgs, NULL, 0, &pArgs->Process);
     46    return RTProcCreate(apszArgs[0], apszArgs, RTENV_DEFAULT, 0, &pArgs->Process);
    4647}
    4748
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette