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