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