/*-----------------------------------------------------------------------*
 * filename - setenvp.c
 *
 * function(s)
 *      _lock_env       - lock the environment semaphore
 *      _unlock_env     - unlock the environment semaphore
 *      _setenvp        - set up environment strings
 *-----------------------------------------------------------------------*/

/*
 *      C/C++ Run Time Library - Version 1.5
 *
 *      Copyright (c) 1991, 1994 by Borland International
 *      All Rights Reserved.
 *
 */

#include <string.h>
#include <stdlib.h>
#include <_io.h>
#include <_thread.h>

/*----------------------------------------------------------------------
 * Public variables
 */
int _setenvp__ = 0;                 /* satisfy ext. ref. generated by BCC */
char ** _RTLENTRY _EXPDATA environ; /* pointer to array of env. strings */
lock_t _env_lock;                   /* semaphore for env. strings */

/*----------------------------------------------------------------------
 * External variables
 */
extern char **_C0environ;           /* startup's copy of environ */
extern char *_osenv;                /* pointer to NT environment data */

#ifdef _MT

/*---------------------------------------------------------------------*

Name            _lock_env - lock the environment semaphore

Usage           void _lock_env(void);

Prototype in

Related
functions usage void _unlock_env(void);

Description     This function locks the semaphore that governs
                access to the environment strings.

Return value    None.

*---------------------------------------------------------------------*/

void _lock_env(void)
{
    _lock(_env_lock,"locking environment lock");
}

/*---------------------------------------------------------------------*

Name            _unlock_env - unlock the environment semaphore

Usage           void _unlock_env(void);

Prototype in

Related
functions usage void _unlock_env(void);

Description     This function unlocks the global lock that governs
                access to the environment strings.

Return value    None.

*---------------------------------------------------------------------*/

void _unlock_env(void)
{
    _unlock(_env_lock,"unlocking environment lock");
}

#endif  /* _MT */

/*---------------------------------------------------------------------*

Name            envcpy - copy a single environment string

Usage           void envcpy(char *dst, char *src);

Description     This function copies an environment string from src
                to dst, converting the name (everything before the first
                '=' character) to uppercase.

Return value    None.

*---------------------------------------------------------------------*/

static void envcpy(char *dst, char *src)
{
    char c;

    /* Copy everything up to the '=' character, converting to upper case.
     */
    while ((c = *src) != '\0' && c != '=')
    {
        *dst = (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
        src++;
        dst++;
    }

    strcpy(dst,src);    /* Copy the remainder of the string. */
}

/*---------------------------------------------------------------------*

Name            _setenvp - set up environment strings

Usage           void _setenvp(void);

Description     This function is called by at startup time.
                It saves copies of each environment string,
                and creates an array of pointers to these strings.
                The pointer to the array is saved in both environ
                and _C0environ.  It assumes that a pointer to
                the environment has already been placed in _osenv
                by the startup code.

Return value    None.

*---------------------------------------------------------------------*/

static void _setenvp(void)
{
#pragma startup _setenvp 3

    char *p, *e;
    int n, len;

    /* First, count the strings in the environment.
     */
    for (n = 0, p = _osenv; (len = strlen(p)) != 0; n++, p += len + 1)
        ;

    /* Allocate space for the array of pointers.  Include an extra
     * for a null pointer at the end of the list.
     */
    if ((environ = malloc((n+1)*sizeof(char*))) == NULL)
        return;

    /* Make copies of each environment string, save a pointer to
     * each in the environ array.
     */
    for (n = 0, p = _osenv; (len = strlen(p)) != 0; n++, p += len + 1)
    {
        if ((e = malloc(len+1)) == NULL)
            break;
        envcpy(e,p);
        environ[n] = e;
    }
    environ[n] = NULL;

    /* The startup code passes _C0environ to main().
     */
    _C0environ = environ;

    /* Create the lock used to govern access to the environment strings.
     */
    _create_lock(&_env_lock,"creating environment lock");
}
