src/stdlib/SDL_getenv.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 16 Dec 2009 10:59:51 +0000
changeset 3581 15eea7a1fa97
parent 2859 99210400e8b9
child 3583 65f66674b7fb
permissions -rw-r--r--
Implemented SDL_setenv(), moved SDL_putenv() to compat.

Fixes Bugzilla #779.
slouken@1330
     1
/*
slouken@1330
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@1330
     4
slouken@1330
     5
    This library is free software; you can redistribute it and/or
slouken@1330
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1330
     7
    License as published by the Free Software Foundation; either
slouken@1330
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1330
     9
slouken@1330
    10
    This library is distributed in the hope that it will be useful,
slouken@1330
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1330
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1330
    13
    Lesser General Public License for more details.
slouken@1330
    14
slouken@1330
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1330
    16
    License along with this library; if not, write to the Free Software
slouken@1330
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1330
    18
slouken@1330
    19
    Sam Lantinga
slouken@1330
    20
    slouken@libsdl.org
slouken@1330
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@1330
    23
slouken@1354
    24
#include "SDL_stdinc.h"
slouken@1330
    25
slouken@1331
    26
#ifndef HAVE_GETENV
slouken@1330
    27
slouken@1402
    28
#if defined(__WIN32__) && !defined(_WIN32_WCE)
slouken@1330
    29
slouken@1433
    30
#define WIN32_LEAN_AND_MEAN
slouken@1433
    31
#include <windows.h>
slouken@1330
    32
slouken@1330
    33
/* Note this isn't thread-safe! */
slouken@1330
    34
slouken@1895
    35
static char *SDL_envmem = NULL; /* Ugh, memory leak */
slouken@1456
    36
static size_t SDL_envmemlen = 0;
slouken@1330
    37
icculus@3581
    38
/* Put a variable into the environment */
slouken@1895
    39
int
icculus@3581
    40
SDL_setenv(const char *name, const char *value, int overwrite)
slouken@1330
    41
{
icculus@3581
    42
    if (!overwrite) {
icculus@3581
    43
        char ch = 0;
icculus@3581
    44
        const size_t len = GetEnvironmentVariable(name, &ch, sizeof (ch));
icculus@3581
    45
        if (len > 0) {
icculus@3581
    46
            return 0;  /* asked not to overwrite existing value. */
icculus@3581
    47
        }
slouken@1895
    48
    }
icculus@3581
    49
    if (!SetEnvironmentVariable(name, *value ? value : NULL)) {
slouken@1895
    50
        return -1;
slouken@1895
    51
    }
slouken@1895
    52
    return 0;
slouken@1330
    53
}
slouken@1330
    54
slouken@1330
    55
/* Retrieve a variable named "name" from the environment */
slouken@1895
    56
char *
slouken@1895
    57
SDL_getenv(const char *name)
slouken@1330
    58
{
slouken@1895
    59
    size_t bufferlen;
slouken@1330
    60
slouken@1895
    61
    bufferlen =
slouken@1895
    62
        GetEnvironmentVariable(name, SDL_envmem, (DWORD) SDL_envmemlen);
slouken@1895
    63
    if (bufferlen == 0) {
slouken@1895
    64
        return NULL;
slouken@1895
    65
    }
slouken@1895
    66
    if (bufferlen > SDL_envmemlen) {
slouken@1895
    67
        char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
slouken@1895
    68
        if (newmem == NULL) {
slouken@1895
    69
            return NULL;
slouken@1895
    70
        }
slouken@1895
    71
        SDL_envmem = newmem;
slouken@1895
    72
        SDL_envmemlen = bufferlen;
slouken@1895
    73
        GetEnvironmentVariable(name, SDL_envmem, (DWORD) SDL_envmemlen);
slouken@1895
    74
    }
slouken@1895
    75
    return SDL_envmem;
slouken@1330
    76
}
slouken@1330
    77
slouken@1330
    78
#else /* roll our own */
slouken@1330
    79
slouken@1895
    80
static char **SDL_env = (char **) 0;
slouken@1330
    81
icculus@3581
    82
/* Put a variable into the environment */
slouken@1895
    83
int
icculus@3581
    84
SDL_setenv(const char *name, const char *value, int overwrite)
slouken@1330
    85
{
slouken@1895
    86
    int added;
slouken@1895
    87
    int len, i;
slouken@1895
    88
    char **new_env;
slouken@1895
    89
    char *new_variable;
slouken@1330
    90
slouken@1895
    91
    /* A little error checking */
icculus@3581
    92
    if (!name || !value) {
slouken@1895
    93
        return (-1);
slouken@1895
    94
    }
slouken@1330
    95
slouken@1895
    96
    /* Allocate memory for the variable */
icculus@3581
    97
    len = SDL_strlen(name) + SDL_strlen(value) + 2;
icculus@3581
    98
    new_variable = (char *) SDL_malloc(len);
slouken@1895
    99
    if (!new_variable) {
slouken@1895
   100
        return (-1);
slouken@1895
   101
    }
slouken@1330
   102
icculus@3581
   103
    SDL_snprintf(new_variable, len, "%s=%s", name, value);
icculus@3581
   104
    value = new_variable + SDL_strlen(name) + 1;
icculus@3581
   105
    name = new_variable;
icculus@3581
   106
slouken@1895
   107
    /* Actually put it into the environment */
slouken@1895
   108
    added = 0;
slouken@1895
   109
    i = 0;
slouken@1895
   110
    if (SDL_env) {
slouken@1895
   111
        /* Check to see if it's already there... */
slouken@1895
   112
        len = (value - name);
slouken@1895
   113
        for (; SDL_env[i]; ++i) {
slouken@1895
   114
            if (SDL_strncmp(SDL_env[i], name, len) == 0) {
slouken@1895
   115
                break;
slouken@1895
   116
            }
slouken@1895
   117
        }
slouken@1895
   118
        /* If we found it, just replace the entry */
slouken@1895
   119
        if (SDL_env[i]) {
icculus@3581
   120
            if (!overwrite) {
icculus@3581
   121
                SDL_free(new_variable);
icculus@3581
   122
                return 0;
icculus@3581
   123
            }
slouken@1895
   124
            SDL_free(SDL_env[i]);
slouken@1895
   125
            SDL_env[i] = new_variable;
slouken@1895
   126
            added = 1;
slouken@1895
   127
        }
slouken@1895
   128
    }
slouken@1330
   129
slouken@1895
   130
    /* Didn't find it in the environment, expand and add */
slouken@1895
   131
    if (!added) {
slouken@1895
   132
        new_env = SDL_realloc(SDL_env, (i + 2) * sizeof(char *));
slouken@1895
   133
        if (new_env) {
slouken@1895
   134
            SDL_env = new_env;
slouken@1895
   135
            SDL_env[i++] = new_variable;
slouken@1895
   136
            SDL_env[i++] = (char *) 0;
slouken@1895
   137
            added = 1;
slouken@1895
   138
        } else {
slouken@1895
   139
            SDL_free(new_variable);
slouken@1895
   140
        }
slouken@1895
   141
    }
slouken@1895
   142
    return (added ? 0 : -1);
slouken@1330
   143
}
slouken@1330
   144
slouken@1330
   145
/* Retrieve a variable named "name" from the environment */
slouken@1895
   146
char *
slouken@1895
   147
SDL_getenv(const char *name)
slouken@1330
   148
{
slouken@1895
   149
    int len, i;
slouken@1895
   150
    char *value;
slouken@1330
   151
slouken@1895
   152
    value = (char *) 0;
slouken@1895
   153
    if (SDL_env) {
slouken@1895
   154
        len = SDL_strlen(name);
slouken@1895
   155
        for (i = 0; SDL_env[i] && !value; ++i) {
slouken@1895
   156
            if ((SDL_strncmp(SDL_env[i], name, len) == 0) &&
slouken@1895
   157
                (SDL_env[i][len] == '=')) {
slouken@1895
   158
                value = &SDL_env[i][len + 1];
slouken@1895
   159
            }
slouken@1895
   160
        }
slouken@1895
   161
    }
slouken@1895
   162
    return value;
slouken@1330
   163
}
slouken@1330
   164
slouken@1402
   165
#endif /* __WIN32__ */
slouken@1330
   166
slouken@1331
   167
#endif /* !HAVE_GETENV */
slouken@1331
   168
icculus@3581
   169
icculus@3581
   170
/* We have a real environment table, but no real setenv? Fake it w/ putenv. */
icculus@3581
   171
#if (defined(HAVE_GETENV) && defined(HAVE_PUTENV) && !defined(HAVE_SETENV))
icculus@3581
   172
int
icculus@3581
   173
SDL_setenv(const char *name, const char *value, int overwrite)
icculus@3581
   174
{
icculus@3581
   175
    size_t len;
icculus@3581
   176
    char *new_variable;
icculus@3581
   177
icculus@3581
   178
    if (getenv(name) != NULL) {
icculus@3581
   179
        if (overwrite) {
icculus@3581
   180
            unsetenv(name);
icculus@3581
   181
        } else {
icculus@3581
   182
            return 0;  /* leave the existing one there. */
icculus@3581
   183
        }
icculus@3581
   184
    }
icculus@3581
   185
icculus@3581
   186
    /* This leaks. Sorry. Get a better OS so we don't have to do this. */
icculus@3581
   187
    len = SDL_strlen(name) + SDL_strlen(value) + 2;
icculus@3581
   188
    new_variable = (char *) SDL_malloc(len);
icculus@3581
   189
    if (!new_variable) {
icculus@3581
   190
        return (-1);
icculus@3581
   191
    }
icculus@3581
   192
icculus@3581
   193
    SDL_snprintf(new_variable, len, "%s=%s", name, value);
icculus@3581
   194
    return putenv(new_variable);
icculus@3581
   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@1895
   216
    if (SDL_putenv("FIRST=VALUE1") == 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@1895
   231
    if (SDL_putenv("SECOND=VALUE2") == 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@1895
   246
    if (SDL_putenv("FIRST=NOVALUE") == 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@1895
   269
/* vi: set ts=4 sw=4 expandtab: */