src/stdlib/SDL_getenv.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 24 Oct 2017 00:17:07 -0700
changeset 11653 4130b92b6be4
parent 11232 b26929d6ca20
child 11678 1f10a52295e3
permissions -rw-r--r--
Added the ability to set SDL hints from AndroidManifest.xml (thanks Rachel!)
This is especially useful for things like the accelerometer hint which could be needed before application main().
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 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(__ANDROID__)
   175 char *
   176 SDL_getenv(const char *name)
   177 {
   178     /* Input validation */
   179     if (!name || SDL_strlen(name)==0) {
   180         return NULL;
   181     }
   182 
   183     return SDL_AndroidGetManifestEnvironmentVariable(name);    
   184 }
   185 #elif defined(HAVE_GETENV)
   186 char *
   187 SDL_getenv(const char *name)
   188 {
   189     /* Input validation */
   190     if (!name || SDL_strlen(name)==0) {
   191         return NULL;
   192     }
   193 
   194     return getenv(name);
   195 }
   196 #elif defined(__WIN32__)
   197 char *
   198 SDL_getenv(const char *name)
   199 {
   200     size_t bufferlen;
   201 
   202     /* Input validation */
   203     if (!name || SDL_strlen(name)==0) {
   204         return NULL;
   205     }
   206     
   207     bufferlen =
   208         GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
   209     if (bufferlen == 0) {
   210         return NULL;
   211     }
   212     if (bufferlen > SDL_envmemlen) {
   213         char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
   214         if (newmem == NULL) {
   215             return NULL;
   216         }
   217         SDL_envmem = newmem;
   218         SDL_envmemlen = bufferlen;
   219         GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
   220     }
   221     return SDL_envmem;
   222 }
   223 #else
   224 char *
   225 SDL_getenv(const char *name)
   226 {
   227     int len, i;
   228     char *value;
   229 
   230     /* Input validation */
   231     if (!name || SDL_strlen(name)==0) {
   232         return NULL;
   233     }
   234     
   235     value = (char *) 0;
   236     if (SDL_env) {
   237         len = SDL_strlen(name);
   238         for (i = 0; SDL_env[i] && !value; ++i) {
   239             if ((SDL_strncmp(SDL_env[i], name, len) == 0) &&
   240                 (SDL_env[i][len] == '=')) {
   241                 value = &SDL_env[i][len + 1];
   242             }
   243         }
   244     }
   245     return value;
   246 }
   247 #endif
   248 
   249 
   250 #ifdef TEST_MAIN
   251 #include <stdio.h>
   252 
   253 int
   254 main(int argc, char *argv[])
   255 {
   256     char *value;
   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     printf("Setting FIRST=VALUE1 in the environment... ");
   266     fflush(stdout);
   267     if (SDL_setenv("FIRST", "VALUE1", 0) == 0) {
   268         printf("okay\n");
   269     } else {
   270         printf("failed\n");
   271     }
   272     printf("Getting FIRST from the environment... ");
   273     fflush(stdout);
   274     value = SDL_getenv("FIRST");
   275     if (value && (SDL_strcmp(value, "VALUE1") == 0)) {
   276         printf("okay\n");
   277     } else {
   278         printf("failed\n");
   279     }
   280     printf("Setting SECOND=VALUE2 in the environment... ");
   281     fflush(stdout);
   282     if (SDL_setenv("SECOND", "VALUE2", 0) == 0) {
   283         printf("okay\n");
   284     } else {
   285         printf("failed\n");
   286     }
   287     printf("Getting SECOND from the environment... ");
   288     fflush(stdout);
   289     value = SDL_getenv("SECOND");
   290     if (value && (SDL_strcmp(value, "VALUE2") == 0)) {
   291         printf("okay\n");
   292     } else {
   293         printf("failed\n");
   294     }
   295     printf("Setting FIRST=NOVALUE in the environment... ");
   296     fflush(stdout);
   297     if (SDL_setenv("FIRST", "NOVALUE", 1) == 0) {
   298         printf("okay\n");
   299     } else {
   300         printf("failed\n");
   301     }
   302     printf("Getting FIRST from the environment... ");
   303     fflush(stdout);
   304     value = SDL_getenv("FIRST");
   305     if (value && (SDL_strcmp(value, "NOVALUE") == 0)) {
   306         printf("okay\n");
   307     } else {
   308         printf("failed\n");
   309     }
   310     printf("Checking for non-existent variable... ");
   311     fflush(stdout);
   312     if (!SDL_getenv("EXISTS")) {
   313         printf("okay\n");
   314     } else {
   315         printf("failed\n");
   316     }
   317     return (0);
   318 }
   319 #endif /* TEST_MAIN */
   320 
   321 /* vi: set ts=4 sw=4 expandtab: */