src/stdlib/SDL_getenv.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 25 Sep 2018 08:23:57 -0700
changeset 12220 f10c21b0c0ef
parent 11811 5d94cb6b24d3
permissions -rw-r--r--
Fixed building with newer Android NDK
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 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 
    22 #if defined(__clang_analyzer__) && !defined(SDL_DISABLE_ANALYZE_MACROS)
    23 #define SDL_DISABLE_ANALYZE_MACROS 1
    24 #endif
    25 
    26 #include "../SDL_internal.h"
    27 
    28 #if defined(__WIN32__)
    29 #include "../core/windows/SDL_windows.h"
    30 #endif
    31 
    32 #if defined(__ANDROID__)
    33 #include "../core/android/SDL_android.h"
    34 #endif
    35 
    36 #include "SDL_stdinc.h"
    37 
    38 #if defined(__WIN32__) && (!defined(HAVE_SETENV) || !defined(HAVE_GETENV))
    39 /* Note this isn't thread-safe! */
    40 static char *SDL_envmem = NULL; /* Ugh, memory leak */
    41 static size_t SDL_envmemlen = 0;
    42 #endif
    43 
    44 /* Put a variable into the environment */
    45 /* Note: Name may not contain a '=' character. (Reference: http://www.unix.com/man-page/Linux/3/setenv/) */
    46 #if defined(HAVE_SETENV)
    47 int
    48 SDL_setenv(const char *name, const char *value, int overwrite)
    49 {
    50     /* Input validation */
    51     if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
    52         return (-1);
    53     }
    54     
    55     return setenv(name, value, overwrite);
    56 }
    57 #elif defined(__WIN32__)
    58 int
    59 SDL_setenv(const char *name, const char *value, int overwrite)
    60 {
    61     /* Input validation */
    62     if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
    63         return (-1);
    64     }
    65     
    66     if (!overwrite) {
    67         if (GetEnvironmentVariableA(name, NULL, 0) > 0) {
    68             return 0;  /* asked not to overwrite existing value. */
    69         }
    70     }
    71     if (!SetEnvironmentVariableA(name, *value ? value : NULL)) {
    72         return -1;
    73     }
    74     return 0;
    75 }
    76 /* We have a real environment table, but no real setenv? Fake it w/ putenv. */
    77 #elif (defined(HAVE_GETENV) && defined(HAVE_PUTENV) && !defined(HAVE_SETENV))
    78 int
    79 SDL_setenv(const char *name, const char *value, int overwrite)
    80 {
    81     size_t len;
    82     char *new_variable;
    83 
    84     /* Input validation */
    85     if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
    86         return (-1);
    87     }
    88     
    89     if (getenv(name) != NULL) {
    90         if (overwrite) {
    91             unsetenv(name);
    92         } else {
    93             return 0;  /* leave the existing one there. */
    94         }
    95     }
    96 
    97     /* This leaks. Sorry. Get a better OS so we don't have to do this. */
    98     len = SDL_strlen(name) + SDL_strlen(value) + 2;
    99     new_variable = (char *) SDL_malloc(len);
   100     if (!new_variable) {
   101         return (-1);
   102     }
   103 
   104     SDL_snprintf(new_variable, len, "%s=%s", name, value);
   105     return putenv(new_variable);
   106 }
   107 #else /* roll our own */
   108 static char **SDL_env = (char **) 0;
   109 int
   110 SDL_setenv(const char *name, const char *value, int overwrite)
   111 {
   112     int added;
   113     int len, i;
   114     char **new_env;
   115     char *new_variable;
   116 
   117     /* Input validation */
   118     if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
   119         return (-1);
   120     }
   121 
   122     /* See if it already exists */
   123     if (!overwrite && SDL_getenv(name)) {
   124         return 0;
   125     }
   126 
   127     /* Allocate memory for the variable */
   128     len = SDL_strlen(name) + SDL_strlen(value) + 2;
   129     new_variable = (char *) SDL_malloc(len);
   130     if (!new_variable) {
   131         return (-1);
   132     }
   133 
   134     SDL_snprintf(new_variable, len, "%s=%s", name, value);
   135     value = new_variable + SDL_strlen(name) + 1;
   136     name = new_variable;
   137 
   138     /* Actually put it into the environment */
   139     added = 0;
   140     i = 0;
   141     if (SDL_env) {
   142         /* Check to see if it's already there... */
   143         len = (value - name);
   144         for (; SDL_env[i]; ++i) {
   145             if (SDL_strncmp(SDL_env[i], name, len) == 0) {
   146                 break;
   147             }
   148         }
   149         /* If we found it, just replace the entry */
   150         if (SDL_env[i]) {
   151             SDL_free(SDL_env[i]);
   152             SDL_env[i] = new_variable;
   153             added = 1;
   154         }
   155     }
   156 
   157     /* Didn't find it in the environment, expand and add */
   158     if (!added) {
   159         new_env = SDL_realloc(SDL_env, (i + 2) * sizeof(char *));
   160         if (new_env) {
   161             SDL_env = new_env;
   162             SDL_env[i++] = new_variable;
   163             SDL_env[i++] = (char *) 0;
   164             added = 1;
   165         } else {
   166             SDL_free(new_variable);
   167         }
   168     }
   169     return (added ? 0 : -1);
   170 }
   171 #endif
   172 
   173 /* Retrieve a variable named "name" from the environment */
   174 #if defined(HAVE_GETENV)
   175 char *
   176 SDL_getenv(const char *name)
   177 {
   178 #if defined(__ANDROID__)
   179     /* Make sure variables from the application manifest are available */
   180     Android_JNI_GetManifestEnvironmentVariables();
   181 #endif
   182 
   183     /* Input validation */
   184     if (!name || !*name) {
   185         return NULL;
   186     }
   187 
   188     return getenv(name);
   189 }
   190 #elif defined(__WIN32__)
   191 char *
   192 SDL_getenv(const char *name)
   193 {
   194     size_t bufferlen;
   195 
   196     /* Input validation */
   197     if (!name || SDL_strlen(name)==0) {
   198         return NULL;
   199     }
   200     
   201     bufferlen =
   202         GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
   203     if (bufferlen == 0) {
   204         return NULL;
   205     }
   206     if (bufferlen > SDL_envmemlen) {
   207         char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
   208         if (newmem == NULL) {
   209             return NULL;
   210         }
   211         SDL_envmem = newmem;
   212         SDL_envmemlen = bufferlen;
   213         GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
   214     }
   215     return SDL_envmem;
   216 }
   217 #else
   218 char *
   219 SDL_getenv(const char *name)
   220 {
   221     int len, i;
   222     char *value;
   223 
   224     /* Input validation */
   225     if (!name || SDL_strlen(name)==0) {
   226         return NULL;
   227     }
   228     
   229     value = (char *) 0;
   230     if (SDL_env) {
   231         len = SDL_strlen(name);
   232         for (i = 0; SDL_env[i] && !value; ++i) {
   233             if ((SDL_strncmp(SDL_env[i], name, len) == 0) &&
   234                 (SDL_env[i][len] == '=')) {
   235                 value = &SDL_env[i][len + 1];
   236             }
   237         }
   238     }
   239     return value;
   240 }
   241 #endif
   242 
   243 
   244 #ifdef TEST_MAIN
   245 #include <stdio.h>
   246 
   247 int
   248 main(int argc, char *argv[])
   249 {
   250     char *value;
   251 
   252     printf("Checking for non-existent variable... ");
   253     fflush(stdout);
   254     if (!SDL_getenv("EXISTS")) {
   255         printf("okay\n");
   256     } else {
   257         printf("failed\n");
   258     }
   259     printf("Setting FIRST=VALUE1 in the environment... ");
   260     fflush(stdout);
   261     if (SDL_setenv("FIRST", "VALUE1", 0) == 0) {
   262         printf("okay\n");
   263     } else {
   264         printf("failed\n");
   265     }
   266     printf("Getting FIRST from the environment... ");
   267     fflush(stdout);
   268     value = SDL_getenv("FIRST");
   269     if (value && (SDL_strcmp(value, "VALUE1") == 0)) {
   270         printf("okay\n");
   271     } else {
   272         printf("failed\n");
   273     }
   274     printf("Setting SECOND=VALUE2 in the environment... ");
   275     fflush(stdout);
   276     if (SDL_setenv("SECOND", "VALUE2", 0) == 0) {
   277         printf("okay\n");
   278     } else {
   279         printf("failed\n");
   280     }
   281     printf("Getting SECOND from the environment... ");
   282     fflush(stdout);
   283     value = SDL_getenv("SECOND");
   284     if (value && (SDL_strcmp(value, "VALUE2") == 0)) {
   285         printf("okay\n");
   286     } else {
   287         printf("failed\n");
   288     }
   289     printf("Setting FIRST=NOVALUE in the environment... ");
   290     fflush(stdout);
   291     if (SDL_setenv("FIRST", "NOVALUE", 1) == 0) {
   292         printf("okay\n");
   293     } else {
   294         printf("failed\n");
   295     }
   296     printf("Getting FIRST from the environment... ");
   297     fflush(stdout);
   298     value = SDL_getenv("FIRST");
   299     if (value && (SDL_strcmp(value, "NOVALUE") == 0)) {
   300         printf("okay\n");
   301     } else {
   302         printf("failed\n");
   303     }
   304     printf("Checking for non-existent variable... ");
   305     fflush(stdout);
   306     if (!SDL_getenv("EXISTS")) {
   307         printf("okay\n");
   308     } else {
   309         printf("failed\n");
   310     }
   311     return (0);
   312 }
   313 #endif /* TEST_MAIN */
   314 
   315 /* vi: set ts=4 sw=4 expandtab: */