src/stdlib/SDL_getenv.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 15 Mar 2013 01:01:20 -0400
changeset 7003 eeaf77005c30
parent 6885 700f1b25f77f
child 7351 668a3dc28361
permissions -rw-r--r--
Improvements to stdlib.

All SDL_* functions are always available as real symbols, so you can always
link against them as a stable ABI. By default, however, all the things that
might have dithered down to macros in your application are now force-inlined,
to give you the same effect as before and theoretically better performance,
but still solve the classic macro problems.

Elsewhere, we provide real functions for these things that simply wrap the
inline functions, in case one needs to have a real function available.

Also: this exposed bugs: SDL_abs() does something different if you had the
macro vs the libc function, SDL_memcpy() returns a void* in the function
but not the macro, etc.
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 */
icculus@7003
    34
#ifdef SDL_setenv
icculus@7003
    35
#undef SDL_setenv
icculus@7003
    36
int SDL_setenv(const char *name, const char *value, int overwrite) { return SDL_setenv_inline(name, value, overwrite); }
icculus@7003
    37
#elif defined(__WIN32__)
slouken@1895
    38
int
icculus@3581
    39
SDL_setenv(const char *name, const char *value, int overwrite)
slouken@1330
    40
{
icculus@3581
    41
    if (!overwrite) {
icculus@3581
    42
        char ch = 0;
slouken@5090
    43
        const size_t len = GetEnvironmentVariableA(name, &ch, sizeof (ch));
icculus@3581
    44
        if (len > 0) {
icculus@3581
    45
            return 0;  /* asked not to overwrite existing value. */
icculus@3581
    46
        }
slouken@1895
    47
    }
slouken@5090
    48
    if (!SetEnvironmentVariableA(name, *value ? value : NULL)) {
slouken@1895
    49
        return -1;
slouken@1895
    50
    }
slouken@1895
    51
    return 0;
slouken@1330
    52
}
icculus@7003
    53
/* We have a real environment table, but no real setenv? Fake it w/ putenv. */
icculus@7003
    54
#elif (defined(HAVE_GETENV) && defined(HAVE_PUTENV) && !defined(HAVE_SETENV))
icculus@7003
    55
int
icculus@7003
    56
SDL_setenv(const char *name, const char *value, int overwrite)
icculus@7003
    57
{
icculus@7003
    58
    size_t len;
icculus@7003
    59
    char *new_variable;
slouken@1330
    60
icculus@7003
    61
    if (getenv(name) != NULL) {
icculus@7003
    62
        if (overwrite) {
icculus@7003
    63
            unsetenv(name);
icculus@7003
    64
        } else {
icculus@7003
    65
            return 0;  /* leave the existing one there. */
icculus@7003
    66
        }
icculus@7003
    67
    }
slouken@1330
    68
icculus@7003
    69
    /* This leaks. Sorry. Get a better OS so we don't have to do this. */
icculus@7003
    70
    len = SDL_strlen(name) + SDL_strlen(value) + 2;
icculus@7003
    71
    new_variable = (char *) SDL_malloc(len);
icculus@7003
    72
    if (!new_variable) {
icculus@7003
    73
        return (-1);
slouken@1895
    74
    }
icculus@7003
    75
icculus@7003
    76
    SDL_snprintf(new_variable, len, "%s=%s", name, value);
icculus@7003
    77
    return putenv(new_variable);
slouken@1330
    78
}
slouken@1330
    79
#else /* roll our own */
slouken@1895
    80
static char **SDL_env = (char **) 0;
slouken@1895
    81
int
icculus@3581
    82
SDL_setenv(const char *name, const char *value, int overwrite)
slouken@1330
    83
{
slouken@1895
    84
    int added;
slouken@1895
    85
    int len, i;
slouken@1895
    86
    char **new_env;
slouken@1895
    87
    char *new_variable;
slouken@1330
    88
slouken@1895
    89
    /* A little error checking */
icculus@3581
    90
    if (!name || !value) {
slouken@1895
    91
        return (-1);
slouken@1895
    92
    }
slouken@1330
    93
slouken@3583
    94
    /* See if it already exists */
slouken@3583
    95
    if (!overwrite && SDL_getenv(name)) {
slouken@3583
    96
        return 0;
slouken@3583
    97
    }
slouken@3583
    98
slouken@1895
    99
    /* Allocate memory for the variable */
icculus@3581
   100
    len = SDL_strlen(name) + SDL_strlen(value) + 2;
icculus@3581
   101
    new_variable = (char *) SDL_malloc(len);
slouken@1895
   102
    if (!new_variable) {
slouken@1895
   103
        return (-1);
slouken@1895
   104
    }
slouken@1330
   105
icculus@3581
   106
    SDL_snprintf(new_variable, len, "%s=%s", name, value);
icculus@3581
   107
    value = new_variable + SDL_strlen(name) + 1;
icculus@3581
   108
    name = new_variable;
icculus@3581
   109
slouken@1895
   110
    /* Actually put it into the environment */
slouken@1895
   111
    added = 0;
slouken@1895
   112
    i = 0;
slouken@1895
   113
    if (SDL_env) {
slouken@1895
   114
        /* Check to see if it's already there... */
slouken@1895
   115
        len = (value - name);
slouken@1895
   116
        for (; SDL_env[i]; ++i) {
slouken@1895
   117
            if (SDL_strncmp(SDL_env[i], name, len) == 0) {
slouken@1895
   118
                break;
slouken@1895
   119
            }
slouken@1895
   120
        }
slouken@1895
   121
        /* If we found it, just replace the entry */
slouken@1895
   122
        if (SDL_env[i]) {
slouken@1895
   123
            SDL_free(SDL_env[i]);
slouken@1895
   124
            SDL_env[i] = new_variable;
slouken@1895
   125
            added = 1;
slouken@1895
   126
        }
slouken@1895
   127
    }
slouken@1330
   128
slouken@1895
   129
    /* Didn't find it in the environment, expand and add */
slouken@1895
   130
    if (!added) {
slouken@1895
   131
        new_env = SDL_realloc(SDL_env, (i + 2) * sizeof(char *));
slouken@1895
   132
        if (new_env) {
slouken@1895
   133
            SDL_env = new_env;
slouken@1895
   134
            SDL_env[i++] = new_variable;
slouken@1895
   135
            SDL_env[i++] = (char *) 0;
slouken@1895
   136
            added = 1;
slouken@1895
   137
        } else {
slouken@1895
   138
            SDL_free(new_variable);
slouken@1895
   139
        }
slouken@1895
   140
    }
slouken@1895
   141
    return (added ? 0 : -1);
slouken@1330
   142
}
icculus@7003
   143
#endif
slouken@1330
   144
slouken@1330
   145
/* Retrieve a variable named "name" from the environment */
icculus@7003
   146
#ifdef SDL_getenv
icculus@7003
   147
#undef SDL_getenv
icculus@7003
   148
char *SDL_getenv(const char *name) { return SDL_getenv_inline(name); }
icculus@7003
   149
#elif defined(__WIN32__)
icculus@7003
   150
char *
icculus@7003
   151
SDL_getenv(const char *name)
icculus@7003
   152
{
icculus@7003
   153
    size_t bufferlen;
icculus@7003
   154
icculus@7003
   155
    bufferlen =
icculus@7003
   156
        GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
icculus@7003
   157
    if (bufferlen == 0) {
icculus@7003
   158
        return NULL;
icculus@7003
   159
    }
icculus@7003
   160
    if (bufferlen > SDL_envmemlen) {
icculus@7003
   161
        char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
icculus@7003
   162
        if (newmem == NULL) {
icculus@7003
   163
            return NULL;
icculus@7003
   164
        }
icculus@7003
   165
        SDL_envmem = newmem;
icculus@7003
   166
        SDL_envmemlen = bufferlen;
icculus@7003
   167
        GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
icculus@7003
   168
    }
icculus@7003
   169
    return SDL_envmem;
icculus@7003
   170
}
icculus@7003
   171
#else
slouken@1895
   172
char *
slouken@1895
   173
SDL_getenv(const char *name)
slouken@1330
   174
{
slouken@1895
   175
    int len, i;
slouken@1895
   176
    char *value;
slouken@1330
   177
slouken@1895
   178
    value = (char *) 0;
slouken@1895
   179
    if (SDL_env) {
slouken@1895
   180
        len = SDL_strlen(name);
slouken@1895
   181
        for (i = 0; SDL_env[i] && !value; ++i) {
slouken@1895
   182
            if ((SDL_strncmp(SDL_env[i], name, len) == 0) &&
slouken@1895
   183
                (SDL_env[i][len] == '=')) {
slouken@1895
   184
                value = &SDL_env[i][len + 1];
slouken@1895
   185
            }
slouken@1895
   186
        }
slouken@1895
   187
    }
slouken@1895
   188
    return value;
slouken@1330
   189
}
icculus@3581
   190
#endif
icculus@3581
   191
icculus@3581
   192
slouken@1330
   193
#ifdef TEST_MAIN
slouken@1330
   194
#include <stdio.h>
slouken@1330
   195
slouken@1895
   196
int
slouken@1895
   197
main(int argc, char *argv[])
slouken@1330
   198
{
slouken@1895
   199
    char *value;
slouken@1330
   200
slouken@1895
   201
    printf("Checking for non-existent variable... ");
slouken@1895
   202
    fflush(stdout);
slouken@1895
   203
    if (!SDL_getenv("EXISTS")) {
slouken@1895
   204
        printf("okay\n");
slouken@1895
   205
    } else {
slouken@1895
   206
        printf("failed\n");
slouken@1895
   207
    }
slouken@1895
   208
    printf("Setting FIRST=VALUE1 in the environment... ");
slouken@1895
   209
    fflush(stdout);
slouken@3591
   210
    if (SDL_setenv("FIRST", "VALUE1", 0) == 0) {
slouken@1895
   211
        printf("okay\n");
slouken@1895
   212
    } else {
slouken@1895
   213
        printf("failed\n");
slouken@1895
   214
    }
slouken@1895
   215
    printf("Getting FIRST from the environment... ");
slouken@1895
   216
    fflush(stdout);
slouken@1895
   217
    value = SDL_getenv("FIRST");
slouken@1895
   218
    if (value && (SDL_strcmp(value, "VALUE1") == 0)) {
slouken@1895
   219
        printf("okay\n");
slouken@1895
   220
    } else {
slouken@1895
   221
        printf("failed\n");
slouken@1895
   222
    }
slouken@1895
   223
    printf("Setting SECOND=VALUE2 in the environment... ");
slouken@1895
   224
    fflush(stdout);
slouken@3591
   225
    if (SDL_setenv("SECOND", "VALUE2", 0) == 0) {
slouken@1895
   226
        printf("okay\n");
slouken@1895
   227
    } else {
slouken@1895
   228
        printf("failed\n");
slouken@1895
   229
    }
slouken@1895
   230
    printf("Getting SECOND from the environment... ");
slouken@1895
   231
    fflush(stdout);
slouken@1895
   232
    value = SDL_getenv("SECOND");
slouken@1895
   233
    if (value && (SDL_strcmp(value, "VALUE2") == 0)) {
slouken@1895
   234
        printf("okay\n");
slouken@1895
   235
    } else {
slouken@1895
   236
        printf("failed\n");
slouken@1895
   237
    }
slouken@1895
   238
    printf("Setting FIRST=NOVALUE in the environment... ");
slouken@1895
   239
    fflush(stdout);
slouken@3591
   240
    if (SDL_setenv("FIRST", "NOVALUE", 1) == 0) {
slouken@1895
   241
        printf("okay\n");
slouken@1895
   242
    } else {
slouken@1895
   243
        printf("failed\n");
slouken@1895
   244
    }
slouken@1895
   245
    printf("Getting FIRST from the environment... ");
slouken@1895
   246
    fflush(stdout);
slouken@1895
   247
    value = SDL_getenv("FIRST");
slouken@1895
   248
    if (value && (SDL_strcmp(value, "NOVALUE") == 0)) {
slouken@1895
   249
        printf("okay\n");
slouken@1895
   250
    } else {
slouken@1895
   251
        printf("failed\n");
slouken@1895
   252
    }
slouken@1895
   253
    printf("Checking for non-existent variable... ");
slouken@1895
   254
    fflush(stdout);
slouken@1895
   255
    if (!SDL_getenv("EXISTS")) {
slouken@1895
   256
        printf("okay\n");
slouken@1895
   257
    } else {
slouken@1895
   258
        printf("failed\n");
slouken@1895
   259
    }
slouken@1895
   260
    return (0);
slouken@1330
   261
}
slouken@1330
   262
#endif /* TEST_MAIN */
slouken@3591
   263
slouken@1895
   264
/* vi: set ts=4 sw=4 expandtab: */