/* Software License Agreement
 * 
 *     Copyright(C) 1994-2021 David Lindauer, (LADSoft)
 * 
 *     This file is part of the Orange C Compiler package.
 * 
 *     The Orange C Compiler package is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     The Orange C Compiler package is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with Orange C.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *     As a special exception, if other files instantiate templates or
 *     use macros or inline functions from this file, or you compile
 *     this file and link it with other works to produce a work based
 *     on this file, this file does not by itself cause the resulting
 *     work to be covered by the GNU General Public License. However
 *     the source code for this file must still be made available in
 *     accordance with section (3) of the GNU General Public License.
 *     
 *     This exception does not invalidate any other reasons why a work
 *     based on this file might be covered by the GNU General Public
 *     License.
 * 
 *     contact information:
 *         email: TouchStone222@runbox.com <David Lindauer>
 * 
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <locale.h>
#include "libp.h"
#include "errno.h"

extern char _RTL_DATA** _environ;
int _RTL_FUNC putenv(const char* name)
{
    char **q = _environ, **p;
    int len = 0, count = 0;
    char* z = strchr(name, '=');
    if (!z)
        return -1;
    len = z - name;
    __ll_enter_critical();
    while (*q)
    {
        count++;
        if (!strnicmp(name, *q, len) && (*q)[len] == '=')
        {
            *q = name;  // yes this is supposed to be raw
            __ll_exit_critical();
            return 0;
        }
        q++;
    }
    p = (char**)realloc(_environ, (count + 2) * sizeof(char**));
    if (!p)
    {
        __ll_exit_critical();
        errno = ENOMEM;
        return -1;
    }
    p[count + 2 - 1] = NULL;
    p[count + 2 - 2] = name;
    _environ = p;
    __ll_exit_critical();
    return 0;
}
int _RTL_FUNC _putenv(const char* name) { return putenv(name); }
int _RTL_FUNC _putenv_s(const char* name, const char* value)
{
    char* buf = calloc(strlen(name) + strlen(value) + 2, 1);
    if (!buf)
    {
        errno = ENOMEM;
        return -1;
    }
    strcpy(buf, name);
    buf[strlen(buf)] = '=';
    strcat(buf, value);
    int rv = putenv(strdup(buf));
    free(buf);
    return rv;
}
int _RTL_FUNC setenv(const char* name, const char* value, int overwrite)
{
    if (name == 0 || name[0] == 0 || strchr(name, '='))
    {
        errno = EINVAL;
        return -1;
    }
    if (!overwrite && getenv(name))
        return 0;
    return _putenv_s(name, value);
}
int _RTL_FUNC unsetenv(const char* name)
{
    char** q = _environ;
    int len = 0;
    len = strlen(name);
    __ll_enter_critical();
    while (*q)
    {
        if (!strnicmp(name, *q, len) && (*q)[len] == '=')
        {
            while (*q)
            {
                *q = *(q + 1);
                q++;
            }
            __ll_exit_critical();
            return 0;
        }
        q++;
    }
    __ll_exit_critical();
    return 0;
}