src/stdlib/SDL_getenv.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 05 Jul 2013 23:57:19 -0700
changeset 7351 668a3dc28361
parent 7003 eeaf77005c30
child 7828 1451063c8ecd
permissions -rw-r--r--
Removed the inline functions from SDL_stdinc.h
Having the SDL functions inline is causing build issues, and in the case of malloc(), etc. causing malloc/free mismatches, if the application build environment differs from the SDL build environment.

In the interest of safety and consistency, the functions will always be in the SDL library and will only be redirected to the C library there, if they are available.

See the following threads on the SDL mailing list for the gruesome details:
* SDL_stdinc.h inlines problematic when application not compiled in exact same feature environment
* Error compiling program against SDL2 with -std=c++11 g++ flag
slouken@1330
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
slouken@1330
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1330
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1330
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1330
    20
*/
slouken@1402
    21
#include "SDL_config.h"
slouken@1330
    22
slouken@1354
    23
#include "SDL_stdinc.h"
slouken@1330
    24
icculus@7003
    25
#if !defined(SDL_setenv) && defined(__WIN32__)
slouken@5090
    26
#include "../core/windows/SDL_windows.h"
slouken@1330
    27
/* Note this isn't thread-safe! */
slouken@1895
    28
static char *SDL_envmem = NULL; /* Ugh, memory leak */
slouken@1456
    29
static size_t SDL_envmemlen = 0;
icculus@7003
    30
#endif
icculus@7003
    31
slouken@1330
    32
icculus@3581
    33
/* Put a variable into the environment */
slouken@7351
    34
#if defined(HAVE_SETENV)
slouken@7351
    35
int
slouken@7351
    36
SDL_setenv(const char *name, const char *value, int overwrite)
slouken@7351
    37
{
slouken@7351
    38
    return setenv(name, value, overwrite);
slouken@7351
    39
}
icculus@7003
    40
#elif defined(__WIN32__)
slouken@1895
    41
int
icculus@3581
    42
SDL_setenv(const char *name, const char *value, int overwrite)
slouken@1330
    43
{
icculus@3581
    44
    if (!overwrite) {
icculus@3581
    45
        char ch = 0;
slouken@5090
    46
        const size_t len = GetEnvironmentVariableA(name, &ch, sizeof (ch));
icculus@3581
    47
        if (len > 0) {
icculus@3581
    48
            return 0;  /* asked not to overwrite existing value. */
icculus@3581
    49
        }
slouken@1895
    50
    }
slouken@5090
    51
    if (!SetEnvironmentVariableA(name, *value ? value : NULL)) {
slouken@1895
    52
        return -1;
slouken@1895
    53
    }
slouken@1895
    54
    return 0;
slouken@1330
    55
}
icculus@7003
    56
/* We have a real environment table, but no real setenv? Fake it w/ putenv. */
icculus@7003
    57
#elif (defined(HAVE_GETENV) && defined(HAVE_PUTENV) && !defined(HAVE_SETENV))
icculus@7003
    58
int
icculus@7003
    59
SDL_setenv(const char *name, const char *value, int overwrite)
icculus@7003
    60
{
icculus@7003
    61
    size_t len;
icculus@7003
    62
    char *new_variable;
slouken@1330
    63
icculus@7003
    64
    if (getenv(name) != NULL) {
icculus@7003
    65
        if (overwrite) {
icculus@7003
    66
            unsetenv(name);
icculus@7003
    67
        } else {
icculus@7003
    68
            return 0;  /* leave the existing one there. */
icculus@7003
    69
        }
icculus@7003
    70
    }
slouken@1330
    71
icculus@7003
    72
    /* This leaks. Sorry. Get a better OS so we don't have to do this. */
icculus@7003
    73
    len = SDL_strlen(name) + SDL_strlen(value) + 2;
icculus@7003
    74
    new_variable = (char *) SDL_malloc(len);
icculus@7003
    75
    if (!new_variable) {
icculus@7003
    76
        return (-1);
slouken@1895
    77
    }
icculus@7003
    78
icculus@7003
    79
    SDL_snprintf(new_variable, len, "%s=%s", name, value);
icculus@7003
    80
    return putenv(new_variable);
slouken@1330
    81
}
slouken@1330
    82
#else /* roll our own */
slouken@1895
    83
static char **SDL_env = (char **) 0;
slouken@1895
    84
int
icculus@3581
    85
SDL_setenv(const char *name, const char *value, int overwrite)
slouken@1330
    86
{
slouken@1895
    87
    int added;
slouken@1895
    88
    int len, i;
slouken@1895
    89
    char **new_env;
slouken@1895
    90
    char *new_variable;
slouken@1330
    91
slouken@1895
    92
    /* A little error checking */
icculus@3581
    93
    if (!name || !value) {
slouken@1895
    94
        return (-1);
slouken@1895
    95
    }
slouken@1330
    96
slouken@3583
    97
    /* See if it already exists */
slouken@3583
    98
    if (!overwrite && SDL_getenv(name)) {
slouken@3583
    99
        return 0;
slouken@3583
   100
    }
slouken@3583
   101
slouken@1895
   102
    /* Allocate memory for the variable */
icculus@3581
   103
    len = SDL_strlen(name) + SDL_strlen(value) + 2;
icculus@3581
   104
    new_variable = (char *) SDL_malloc(len);
slouken@1895
   105
    if (!new_variable) {
slouken@1895
   106
        return (-1);
slouken@1895
   107
    }
slouken@1330
   108
icculus@3581
   109
    SDL_snprintf(new_variable, len, "%s=%s", name, value);
icculus@3581
   110
    value = new_variable + SDL_strlen(name) + 1;
icculus@3581
   111
    name = new_variable;
icculus@3581
   112
slouken@1895
   113
    /* Actually put it into the environment */
slouken@1895
   114
    added = 0;
slouken@1895
   115
    i = 0;
slouken@1895
   116
    if (SDL_env) {
slouken@1895
   117
        /* Check to see if it's already there... */
slouken@1895
   118
        len = (value - name);
slouken@1895
   119
        for (; SDL_env[i]; ++i) {
slouken@1895
   120
            if (SDL_strncmp(SDL_env[i], name, len) == 0) {
slouken@1895
   121
                break;
slouken@1895
   122
            }
slouken@1895
   123
        }
slouken@1895
   124
        /* If we found it, just replace the entry */
slouken@1895
   125
        if (SDL_env[i]) {
slouken@1895
   126
            SDL_free(SDL_env[i]);
slouken@1895
   127
            SDL_env[i] = new_variable;
slouken@1895
   128
            added = 1;
slouken@1895
   129
        }
slouken@1895
   130
    }
slouken@1330
   131
slouken@1895
   132
    /* Didn't find it in the environment, expand and add */
slouken@1895
   133
    if (!added) {
slouken@1895
   134
        new_env = SDL_realloc(SDL_env, (i + 2) * sizeof(char *));
slouken@1895
   135
        if (new_env) {
slouken@1895
   136
            SDL_env = new_env;
slouken@1895
   137
            SDL_env[i++] = new_variable;
slouken@1895
   138
            SDL_env[i++] = (char *) 0;
slouken@1895
   139
            added = 1;
slouken@1895
   140
        } else {
slouken@1895
   141
            SDL_free(new_variable);
slouken@1895
   142
        }
slouken@1895
   143
    }
slouken@1895
   144
    return (added ? 0 : -1);
slouken@1330
   145
}
icculus@7003
   146
#endif
slouken@1330
   147
slouken@1330
   148
/* Retrieve a variable named "name" from the environment */
slouken@7351
   149
#if defined(HAVE_GETENV)
slouken@7351
   150
char *
slouken@7351
   151
SDL_getenv(const char *name)
slouken@7351
   152
{
slouken@7351
   153
    return getenv(name);
slouken@7351
   154
}
icculus@7003
   155
#elif defined(__WIN32__)
icculus@7003
   156
char *
icculus@7003
   157
SDL_getenv(const char *name)
icculus@7003
   158
{
icculus@7003
   159
    size_t bufferlen;
icculus@7003
   160
icculus@7003
   161
    bufferlen =
icculus@7003
   162
        GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
icculus@7003
   163
    if (bufferlen == 0) {
icculus@7003
   164
        return NULL;
icculus@7003
   165
    }
icculus@7003
   166
    if (bufferlen > SDL_envmemlen) {
icculus@7003
   167
        char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
icculus@7003
   168
        if (newmem == NULL) {
icculus@7003
   169
            return NULL;
icculus@7003
   170
        }
icculus@7003
   171
        SDL_envmem = newmem;
icculus@7003
   172
        SDL_envmemlen = bufferlen;
icculus@7003
   173
        GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
icculus@7003
   174
    }
icculus@7003
   175
    return SDL_envmem;
icculus@7003
   176
}
icculus@7003
   177
#else
slouken@1895
   178
char *
slouken@1895
   179
SDL_getenv(const char *name)
slouken@1330
   180
{
slouken@1895
   181
    int len, i;
slouken@1895
   182
    char *value;
slouken@1330
   183
slouken@1895
   184
    value = (char *) 0;
slouken@1895
   185
    if (SDL_env) {
slouken@1895
   186
        len = SDL_strlen(name);
slouken@1895
   187
        for (i = 0; SDL_env[i] && !value; ++i) {
slouken@1895
   188
            if ((SDL_strncmp(SDL_env[i], name, len) == 0) &&
slouken@1895
   189
                (SDL_env[i][len] == '=')) {
slouken@1895
   190
                value = &SDL_env[i][len + 1];
slouken@1895
   191
            }
slouken@1895
   192
        }
slouken@1895
   193
    }
slouken@1895
   194
    return value;
slouken@1330
   195
}
icculus@3581
   196
#endif
icculus@3581
   197
icculus@3581
   198
slouken@1330
   199
#ifdef TEST_MAIN
slouken@1330
   200
#include <stdio.h>
slouken@1330
   201
slouken@1895
   202
int
slouken@1895
   203
main(int argc, char *argv[])
slouken@1330
   204
{
slouken@1895
   205
    char *value;
slouken@1330
   206
slouken@1895
   207
    printf("Checking for non-existent variable... ");
slouken@1895
   208
    fflush(stdout);
slouken@1895
   209
    if (!SDL_getenv("EXISTS")) {
slouken@1895
   210
        printf("okay\n");
slouken@1895
   211
    } else {
slouken@1895
   212
        printf("failed\n");
slouken@1895
   213
    }
slouken@1895
   214
    printf("Setting FIRST=VALUE1 in the environment... ");
slouken@1895
   215
    fflush(stdout);
slouken@3591
   216
    if (SDL_setenv("FIRST", "VALUE1", 0) == 0) {
slouken@1895
   217
        printf("okay\n");
slouken@1895
   218
    } else {
slouken@1895
   219
        printf("failed\n");
slouken@1895
   220
    }
slouken@1895
   221
    printf("Getting FIRST from the environment... ");
slouken@1895
   222
    fflush(stdout);
slouken@1895
   223
    value = SDL_getenv("FIRST");
slouken@1895
   224
    if (value && (SDL_strcmp(value, "VALUE1") == 0)) {
slouken@1895
   225
        printf("okay\n");
slouken@1895
   226
    } else {
slouken@1895
   227
        printf("failed\n");
slouken@1895
   228
    }
slouken@1895
   229
    printf("Setting SECOND=VALUE2 in the environment... ");
slouken@1895
   230
    fflush(stdout);
slouken@3591
   231
    if (SDL_setenv("SECOND", "VALUE2", 0) == 0) {
slouken@1895
   232
        printf("okay\n");
slouken@1895
   233
    } else {
slouken@1895
   234
        printf("failed\n");
slouken@1895
   235
    }
slouken@1895
   236
    printf("Getting SECOND from the environment... ");
slouken@1895
   237
    fflush(stdout);
slouken@1895
   238
    value = SDL_getenv("SECOND");
slouken@1895
   239
    if (value && (SDL_strcmp(value, "VALUE2") == 0)) {
slouken@1895
   240
        printf("okay\n");
slouken@1895
   241
    } else {
slouken@1895
   242
        printf("failed\n");
slouken@1895
   243
    }
slouken@1895
   244
    printf("Setting FIRST=NOVALUE in the environment... ");
slouken@1895
   245
    fflush(stdout);
slouken@3591
   246
    if (SDL_setenv("FIRST", "NOVALUE", 1) == 0) {
slouken@1895
   247
        printf("okay\n");
slouken@1895
   248
    } else {
slouken@1895
   249
        printf("failed\n");
slouken@1895
   250
    }
slouken@1895
   251
    printf("Getting FIRST from the environment... ");
slouken@1895
   252
    fflush(stdout);
slouken@1895
   253
    value = SDL_getenv("FIRST");
slouken@1895
   254
    if (value && (SDL_strcmp(value, "NOVALUE") == 0)) {
slouken@1895
   255
        printf("okay\n");
slouken@1895
   256
    } else {
slouken@1895
   257
        printf("failed\n");
slouken@1895
   258
    }
slouken@1895
   259
    printf("Checking for non-existent variable... ");
slouken@1895
   260
    fflush(stdout);
slouken@1895
   261
    if (!SDL_getenv("EXISTS")) {
slouken@1895
   262
        printf("okay\n");
slouken@1895
   263
    } else {
slouken@1895
   264
        printf("failed\n");
slouken@1895
   265
    }
slouken@1895
   266
    return (0);
slouken@1330
   267
}
slouken@1330
   268
#endif /* TEST_MAIN */
slouken@3591
   269
slouken@1895
   270
/* vi: set ts=4 sw=4 expandtab: */