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