|
@@ -20,7 +20,6 @@
|
|
|
*/
|
|
|
#include "SDL_internal.h"
|
|
|
|
|
|
-#include "SDL_getenv_c.h"
|
|
|
#include "../SDL_hashtable.h"
|
|
|
|
|
|
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
|
|
@@ -37,11 +36,6 @@
|
|
|
(defined(HAVE_SETENV) || defined(HAVE_PUTENV)) && \
|
|
|
(defined(HAVE_UNSETENV) || defined(HAVE_PUTENV))
|
|
|
#define HAVE_LIBC_ENVIRONMENT
|
|
|
-#else
|
|
|
-#define HAVE_LOCAL_ENVIRONMENT
|
|
|
-#endif
|
|
|
-
|
|
|
-#if !defined(SDL_PLATFORM_WINDOWS)
|
|
|
#if defined(SDL_PLATFORM_MACOS)
|
|
|
#include <crt_externs.h>
|
|
|
#define environ (*_NSGetEnviron())
|
|
@@ -51,7 +45,253 @@
|
|
|
#else
|
|
|
extern char **environ;
|
|
|
#endif
|
|
|
-#endif // !SDL_PLATFORM_WINDOWS
|
|
|
+#else
|
|
|
+#define HAVE_LOCAL_ENVIRONMENT
|
|
|
+static char **environ;
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+struct SDL_Environment
|
|
|
+{
|
|
|
+ SDL_Mutex *lock;
|
|
|
+ SDL_HashTable *strings;
|
|
|
+};
|
|
|
+static SDL_Environment *SDL_environment;
|
|
|
+
|
|
|
+SDL_Environment *SDL_GetEnvironment(void)
|
|
|
+{
|
|
|
+ if (!SDL_environment) {
|
|
|
+ SDL_environment = SDL_CreateEnvironment(true);
|
|
|
+ }
|
|
|
+ return SDL_environment;
|
|
|
+}
|
|
|
+
|
|
|
+void SDL_CleanupEnvironment(void)
|
|
|
+{
|
|
|
+ SDL_Environment *env = SDL_environment;
|
|
|
+
|
|
|
+ if (env) {
|
|
|
+ SDL_environment = NULL;
|
|
|
+ SDL_DestroyEnvironment(env);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+SDL_Environment *SDL_CreateEnvironment(SDL_bool populated)
|
|
|
+{
|
|
|
+ SDL_Environment *env = SDL_calloc(1, sizeof(*env));
|
|
|
+ if (!env) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ env->strings = SDL_CreateHashTable(NULL, 16, SDL_HashString, SDL_KeyMatchString, SDL_NukeFreeKey, false);
|
|
|
+ if (!env->strings) {
|
|
|
+ SDL_free(env);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Don't fail if we can't create a mutex (e.g. on a single-thread environment)
|
|
|
+ env->lock = SDL_CreateMutex();
|
|
|
+
|
|
|
+ if (populated) {
|
|
|
+#ifdef SDL_PLATFORM_WINDOWS
|
|
|
+ LPWCH strings = GetEnvironmentStringsW();
|
|
|
+ if (strings) {
|
|
|
+ for (LPWCH string = strings; *string; string += SDL_wcslen(string) + 1) {
|
|
|
+ char *variable = WIN_StringToUTF8W(string);
|
|
|
+ if (!variable) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ char *value = SDL_strchr(variable, '=');
|
|
|
+ if (!value || value == variable) {
|
|
|
+ SDL_free(variable);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ *value++ = '\0';
|
|
|
+
|
|
|
+ SDL_InsertIntoHashTable(env->strings, variable, value);
|
|
|
+ }
|
|
|
+ FreeEnvironmentStringsW(strings);
|
|
|
+ }
|
|
|
+#else
|
|
|
+#ifdef SDL_PLATFORM_ANDROID
|
|
|
+ // Make sure variables from the application manifest are available
|
|
|
+ Android_JNI_GetManifestEnvironmentVariables();
|
|
|
+#endif
|
|
|
+ char **strings = environ;
|
|
|
+ if (strings) {
|
|
|
+ for (int i = 0; strings[i]; ++i) {
|
|
|
+ char *variable = SDL_strdup(strings[i]);
|
|
|
+ if (!variable) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ char *value = SDL_strchr(variable, '=');
|
|
|
+ if (!value || value == variable) {
|
|
|
+ SDL_free(variable);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ *value++ = '\0';
|
|
|
+
|
|
|
+ SDL_InsertIntoHashTable(env->strings, variable, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif // SDL_PLATFORM_WINDOWS
|
|
|
+ }
|
|
|
+
|
|
|
+ return env;
|
|
|
+}
|
|
|
+
|
|
|
+const char *SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name)
|
|
|
+{
|
|
|
+ const char *result = NULL;
|
|
|
+
|
|
|
+ if (!env) {
|
|
|
+ return NULL;
|
|
|
+ } else if (!name || *name == '\0') {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_LockMutex(env->lock);
|
|
|
+ {
|
|
|
+ const char *value;
|
|
|
+
|
|
|
+ if (SDL_FindInHashTable(env->strings, name, (const void **)&value)) {
|
|
|
+ result = SDL_GetPersistentString(value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ SDL_UnlockMutex(env->lock);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+char **SDL_GetEnvironmentVariables(SDL_Environment *env)
|
|
|
+{
|
|
|
+ char **result = NULL;
|
|
|
+
|
|
|
+ if (!env) {
|
|
|
+ SDL_InvalidParamError("env");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_LockMutex(env->lock);
|
|
|
+ {
|
|
|
+ size_t count, length = 0;
|
|
|
+ void *iter;
|
|
|
+ const char *key, *value;
|
|
|
+
|
|
|
+ // First pass, get the size we need for all the strings
|
|
|
+ count = 0;
|
|
|
+ iter = NULL;
|
|
|
+ while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) {
|
|
|
+ length += SDL_strlen(key) + 1 + SDL_strlen(value) + 1;
|
|
|
+ ++count;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Allocate memory for the strings
|
|
|
+ result = (char **)SDL_malloc((count + 1) * sizeof(*result) + length);
|
|
|
+ char *string = (char *)(result + count + 1);
|
|
|
+
|
|
|
+ // Second pass, copy the strings
|
|
|
+ count = 0;
|
|
|
+ iter = NULL;
|
|
|
+ while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) {
|
|
|
+ size_t len;
|
|
|
+
|
|
|
+ result[count] = string;
|
|
|
+ len = SDL_strlen(key);
|
|
|
+ SDL_memcpy(string, key, len);
|
|
|
+ string += len;
|
|
|
+ *string++ = '=';
|
|
|
+ len = SDL_strlen(value);
|
|
|
+ SDL_memcpy(string, value, len);
|
|
|
+ string += len;
|
|
|
+ *string++ = '\0';
|
|
|
+ ++count;
|
|
|
+ }
|
|
|
+ result[count] = NULL;
|
|
|
+ }
|
|
|
+ SDL_UnlockMutex(env->lock);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+SDL_bool SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, SDL_bool overwrite)
|
|
|
+{
|
|
|
+ bool result = false;
|
|
|
+
|
|
|
+ if (!env) {
|
|
|
+ return SDL_InvalidParamError("env");
|
|
|
+ } else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
|
|
|
+ return SDL_InvalidParamError("name");
|
|
|
+ } else if (!value) {
|
|
|
+ return SDL_InvalidParamError("value");
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_LockMutex(env->lock);
|
|
|
+ {
|
|
|
+ const void *existing_value;
|
|
|
+ bool insert = true;
|
|
|
+
|
|
|
+ if (SDL_FindInHashTable(env->strings, name, &existing_value)) {
|
|
|
+ if (!overwrite) {
|
|
|
+ result = true;
|
|
|
+ insert = false;
|
|
|
+ } else {
|
|
|
+ SDL_RemoveFromHashTable(env->strings, name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (insert) {
|
|
|
+ char *string = NULL;
|
|
|
+ if (SDL_asprintf(&string, "%s=%s", name, value) > 0) {
|
|
|
+ size_t len = SDL_strlen(name);
|
|
|
+ string[len] = '\0';
|
|
|
+ name = string;
|
|
|
+ value = string + len + 1;
|
|
|
+ result = SDL_InsertIntoHashTable(env->strings, name, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ SDL_UnlockMutex(env->lock);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+SDL_bool SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name)
|
|
|
+{
|
|
|
+ bool result = false;
|
|
|
+
|
|
|
+ if (!env) {
|
|
|
+ return SDL_InvalidParamError("env");
|
|
|
+ } else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
|
|
|
+ return SDL_InvalidParamError("name");
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_LockMutex(env->lock);
|
|
|
+ {
|
|
|
+ const void *value;
|
|
|
+ if (SDL_FindInHashTable(env->strings, name, &value)) {
|
|
|
+ result = SDL_RemoveFromHashTable(env->strings, name);
|
|
|
+ } else {
|
|
|
+ result = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ SDL_UnlockMutex(env->lock);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+void SDL_DestroyEnvironment(SDL_Environment *env)
|
|
|
+{
|
|
|
+ if (!env || env == SDL_environment) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_DestroyMutex(env->lock);
|
|
|
+ SDL_DestroyHashTable(env->strings);
|
|
|
+ SDL_free(env);
|
|
|
+}
|
|
|
|
|
|
// Put a variable into the environment
|
|
|
// Note: Name may not contain a '=' character. (Reference: http://www.unix.com/man-page/Linux/3/setenv/)
|
|
@@ -64,6 +304,8 @@ int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ SDL_SetEnvironmentVariable(SDL_GetEnvironment(), name, value, (overwrite != 0));
|
|
|
+
|
|
|
return setenv(name, value, overwrite);
|
|
|
}
|
|
|
// We have a real environment table, but no real setenv? Fake it w/ putenv.
|
|
@@ -77,6 +319,8 @@ int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ SDL_SetEnvironmentVariable(SDL_GetEnvironment(), name, value, (overwrite != 0));
|
|
|
+
|
|
|
if (getenv(name) != NULL) {
|
|
|
if (!overwrite) {
|
|
|
return 0; // leave the existing one there.
|
|
@@ -99,6 +343,8 @@ int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ SDL_SetEnvironmentVariable(SDL_GetEnvironment(), name, value, (overwrite != 0));
|
|
|
+
|
|
|
if (!overwrite) {
|
|
|
if (GetEnvironmentVariableA(name, NULL, 0) > 0) {
|
|
|
return 0; // asked not to overwrite existing value.
|
|
@@ -111,9 +357,6 @@ int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
|
|
|
}
|
|
|
#else // roll our own
|
|
|
|
|
|
-// We'll leak this, as environment variables are intended to persist past SDL_Quit()
|
|
|
-static char **SDL_env;
|
|
|
-
|
|
|
int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
|
|
|
{
|
|
|
int added;
|
|
@@ -131,6 +374,8 @@ int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+ SDL_SetEnvironmentVariable(SDL_GetEnvironment(), name, value, (overwrite != 0));
|
|
|
+
|
|
|
// Allocate memory for the variable
|
|
|
len = SDL_strlen(name) + SDL_strlen(value) + 2;
|
|
|
new_variable = (char *)SDL_malloc(len);
|
|
@@ -145,14 +390,14 @@ int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
|
|
|
// Actually put it into the environment
|
|
|
added = 0;
|
|
|
i = 0;
|
|
|
- if (SDL_env) {
|
|
|
+ if (environ) {
|
|
|
// Check to see if it's already there...
|
|
|
len = (value - name);
|
|
|
- for (; SDL_env[i]; ++i) {
|
|
|
- if (SDL_strncmp(SDL_env[i], name, len) == 0) {
|
|
|
+ for (; environ[i]; ++i) {
|
|
|
+ if (SDL_strncmp(environ[i], name, len) == 0) {
|
|
|
// If we found it, just replace the entry
|
|
|
- SDL_free(SDL_env[i]);
|
|
|
- SDL_env[i] = new_variable;
|
|
|
+ SDL_free(environ[i]);
|
|
|
+ environ[i] = new_variable;
|
|
|
added = 1;
|
|
|
break;
|
|
|
}
|
|
@@ -161,11 +406,11 @@ int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
|
|
|
|
|
|
// Didn't find it in the environment, expand and add
|
|
|
if (!added) {
|
|
|
- new_env = SDL_realloc(SDL_env, (i + 2) * sizeof(char *));
|
|
|
+ new_env = SDL_realloc(environ, (i + 2) * sizeof(char *));
|
|
|
if (new_env) {
|
|
|
- SDL_env = new_env;
|
|
|
- SDL_env[i++] = new_variable;
|
|
|
- SDL_env[i++] = (char *)0;
|
|
|
+ environ = new_env;
|
|
|
+ environ[i++] = new_variable;
|
|
|
+ environ[i++] = (char *)0;
|
|
|
added = 1;
|
|
|
} else {
|
|
|
SDL_free(new_variable);
|
|
@@ -184,6 +429,8 @@ int SDL_unsetenv_unsafe(const char *name)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ SDL_UnsetEnvironmentVariable(SDL_GetEnvironment(), name);
|
|
|
+
|
|
|
return unsetenv(name);
|
|
|
}
|
|
|
// We have a real environment table, but no unsetenv? Fake it w/ putenv.
|
|
@@ -195,6 +442,8 @@ int SDL_unsetenv_unsafe(const char *name)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ SDL_UnsetEnvironmentVariable(SDL_GetEnvironment(), name);
|
|
|
+
|
|
|
// Hope this environment uses the non-standard extension of removing the environment variable if it has no '='
|
|
|
return putenv(name);
|
|
|
}
|
|
@@ -207,6 +456,8 @@ int SDL_unsetenv_unsafe(const char *name)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ SDL_UnsetEnvironmentVariable(SDL_GetEnvironment(), name);
|
|
|
+
|
|
|
if (!SetEnvironmentVariableA(name, NULL)) {
|
|
|
return -1;
|
|
|
}
|
|
@@ -222,13 +473,15 @@ int SDL_unsetenv_unsafe(const char *name)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- if (SDL_env) {
|
|
|
+ SDL_UnsetEnvironmentVariable(SDL_GetEnvironment(), name);
|
|
|
+
|
|
|
+ if (environ) {
|
|
|
len = SDL_strlen(name);
|
|
|
- for (i = 0; SDL_env[i]; ++i) {
|
|
|
- if ((SDL_strncmp(SDL_env[i], name, len) == 0) &&
|
|
|
- (SDL_env[i][len] == '=')) {
|
|
|
+ for (i = 0; environ[i]; ++i) {
|
|
|
+ if ((SDL_strncmp(environ[i], name, len) == 0) &&
|
|
|
+ (environ[i][len] == '=')) {
|
|
|
// Just clear out this entry for now
|
|
|
- *SDL_env[i] = '\0';
|
|
|
+ *environ[i] = '\0';
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -296,20 +549,19 @@ const char *SDL_getenv_unsafe(const char *name)
|
|
|
const char *SDL_getenv_unsafe(const char *name)
|
|
|
{
|
|
|
size_t len, i;
|
|
|
- char *value;
|
|
|
+ const char *value = NULL;
|
|
|
|
|
|
// Input validation
|
|
|
if (!name || *name == '\0') {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- value = (char *)0;
|
|
|
- if (SDL_env) {
|
|
|
+ if (environ) {
|
|
|
len = SDL_strlen(name);
|
|
|
- for (i = 0; SDL_env[i]; ++i) {
|
|
|
- if ((SDL_strncmp(SDL_env[i], name, len) == 0) &&
|
|
|
- (SDL_env[i][len] == '=')) {
|
|
|
- value = &SDL_env[i][len + 1];
|
|
|
+ for (i = 0; environ[i]; ++i) {
|
|
|
+ if ((SDL_strncmp(environ[i], name, len) == 0) &&
|
|
|
+ (environ[i][len] == '=')) {
|
|
|
+ value = &environ[i][len + 1];
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -318,243 +570,7 @@ const char *SDL_getenv_unsafe(const char *name)
|
|
|
}
|
|
|
#endif // HAVE_LIBC_ENVIRONMENT
|
|
|
|
|
|
-
|
|
|
-struct SDL_Environment
|
|
|
-{
|
|
|
- SDL_Mutex *lock;
|
|
|
- SDL_HashTable *strings;
|
|
|
-};
|
|
|
-static SDL_Environment *SDL_environment;
|
|
|
-
|
|
|
-SDL_Environment *SDL_GetEnvironment(void)
|
|
|
-{
|
|
|
- if (!SDL_environment) {
|
|
|
- SDL_environment = SDL_CreateEnvironment(true);
|
|
|
- }
|
|
|
- return SDL_environment;
|
|
|
-}
|
|
|
-
|
|
|
-void SDL_CleanupEnvironment(void)
|
|
|
-{
|
|
|
- SDL_Environment *env = SDL_environment;
|
|
|
-
|
|
|
- if (env) {
|
|
|
- SDL_environment = NULL;
|
|
|
- SDL_DestroyEnvironment(env);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-SDL_Environment *SDL_CreateEnvironment(SDL_bool populated)
|
|
|
-{
|
|
|
- SDL_Environment *env = SDL_calloc(1, sizeof(*env));
|
|
|
- if (!env) {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- env->strings = SDL_CreateHashTable(NULL, 16, SDL_HashString, SDL_KeyMatchString, SDL_NukeFreeKey, false);
|
|
|
- if (!env->strings) {
|
|
|
- SDL_free(env);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- // Don't fail if we can't create a mutex (e.g. on a single-thread environment)
|
|
|
- env->lock = SDL_CreateMutex();
|
|
|
-
|
|
|
- if (populated) {
|
|
|
-#ifdef SDL_PLATFORM_WINDOWS
|
|
|
- LPWCH strings = GetEnvironmentStringsW();
|
|
|
- if (strings) {
|
|
|
- for (LPWCH string = strings; *string; string += SDL_wcslen(string) + 1) {
|
|
|
- char *variable = WIN_StringToUTF8W(string);
|
|
|
- if (!variable) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- char *value = SDL_strchr(variable, '=');
|
|
|
- if (!value || value == variable) {
|
|
|
- SDL_free(variable);
|
|
|
- continue;
|
|
|
- }
|
|
|
- *value++ = '\0';
|
|
|
-
|
|
|
- SDL_InsertIntoHashTable(env->strings, variable, value);
|
|
|
- }
|
|
|
- FreeEnvironmentStringsW(strings);
|
|
|
- }
|
|
|
-#else
|
|
|
-#ifdef SDL_PLATFORM_ANDROID
|
|
|
- // Make sure variables from the application manifest are available
|
|
|
- Android_JNI_GetManifestEnvironmentVariables();
|
|
|
-#endif
|
|
|
- char **strings = environ;
|
|
|
- for (int i = 0; strings[i]; ++i) {
|
|
|
- char *variable = SDL_strdup(strings[i]);
|
|
|
- if (!variable) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- char *value = SDL_strchr(variable, '=');
|
|
|
- if (!value || value == variable) {
|
|
|
- SDL_free(variable);
|
|
|
- continue;
|
|
|
- }
|
|
|
- *value++ = '\0';
|
|
|
-
|
|
|
- SDL_InsertIntoHashTable(env->strings, variable, value);
|
|
|
- }
|
|
|
-#endif // SDL_PLATFORM_WINDOWS
|
|
|
- }
|
|
|
-
|
|
|
- return env;
|
|
|
-}
|
|
|
-
|
|
|
-const char *SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name)
|
|
|
-{
|
|
|
- const char *result = NULL;
|
|
|
-
|
|
|
- if (!env) {
|
|
|
- return NULL;
|
|
|
- } else if (!name || *name == '\0') {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- SDL_LockMutex(env->lock);
|
|
|
- {
|
|
|
- const char *value;
|
|
|
-
|
|
|
- if (SDL_FindInHashTable(env->strings, name, (const void **)&value)) {
|
|
|
- result = SDL_GetPersistentString(value);
|
|
|
- }
|
|
|
- }
|
|
|
- SDL_UnlockMutex(env->lock);
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-char **SDL_GetEnvironmentVariables(SDL_Environment *env)
|
|
|
-{
|
|
|
- char **result = NULL;
|
|
|
-
|
|
|
- if (!env) {
|
|
|
- SDL_InvalidParamError("env");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- SDL_LockMutex(env->lock);
|
|
|
- {
|
|
|
- size_t count, length = 0;
|
|
|
- void *iter;
|
|
|
- const char *key, *value;
|
|
|
-
|
|
|
- // First pass, get the size we need for all the strings
|
|
|
- count = 0;
|
|
|
- iter = NULL;
|
|
|
- while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) {
|
|
|
- length += SDL_strlen(key) + 1 + SDL_strlen(value) + 1;
|
|
|
- ++count;
|
|
|
- }
|
|
|
-
|
|
|
- // Allocate memory for the strings
|
|
|
- result = (char **)SDL_malloc((count + 1) * sizeof(*result) + length);
|
|
|
- char *string = (char *)(result + count + 1);
|
|
|
-
|
|
|
- // Second pass, copy the strings
|
|
|
- count = 0;
|
|
|
- iter = NULL;
|
|
|
- while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) {
|
|
|
- size_t len;
|
|
|
-
|
|
|
- result[count] = string;
|
|
|
- len = SDL_strlen(key);
|
|
|
- SDL_memcpy(string, key, len);
|
|
|
- string += len;
|
|
|
- *string++ = '=';
|
|
|
- len = SDL_strlen(value);
|
|
|
- SDL_memcpy(string, value, len);
|
|
|
- string += len;
|
|
|
- *string++ = '\0';
|
|
|
- ++count;
|
|
|
- }
|
|
|
- result[count] = NULL;
|
|
|
- }
|
|
|
- SDL_UnlockMutex(env->lock);
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-SDL_bool SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, SDL_bool overwrite)
|
|
|
+const char *SDL_getenv(const char *name)
|
|
|
{
|
|
|
- bool result = false;
|
|
|
-
|
|
|
- if (!env) {
|
|
|
- return SDL_InvalidParamError("env");
|
|
|
- } else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
|
|
|
- return SDL_InvalidParamError("name");
|
|
|
- } else if (!value) {
|
|
|
- return SDL_InvalidParamError("value");
|
|
|
- }
|
|
|
-
|
|
|
- SDL_LockMutex(env->lock);
|
|
|
- {
|
|
|
- const void *existing_value;
|
|
|
- bool insert = true;
|
|
|
-
|
|
|
- if (SDL_FindInHashTable(env->strings, name, &existing_value)) {
|
|
|
- if (!overwrite) {
|
|
|
- result = true;
|
|
|
- insert = false;
|
|
|
- } else {
|
|
|
- SDL_RemoveFromHashTable(env->strings, name);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (insert) {
|
|
|
- char *string = NULL;
|
|
|
- if (SDL_asprintf(&string, "%s=%s", name, value) > 0) {
|
|
|
- size_t len = SDL_strlen(name);
|
|
|
- string[len] = '\0';
|
|
|
- name = string;
|
|
|
- value = string + len + 1;
|
|
|
- result = SDL_InsertIntoHashTable(env->strings, name, value);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- SDL_UnlockMutex(env->lock);
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-SDL_bool SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name)
|
|
|
-{
|
|
|
- bool result = false;
|
|
|
-
|
|
|
- if (!env) {
|
|
|
- return SDL_InvalidParamError("env");
|
|
|
- } else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
|
|
|
- return SDL_InvalidParamError("name");
|
|
|
- }
|
|
|
-
|
|
|
- SDL_LockMutex(env->lock);
|
|
|
- {
|
|
|
- const void *value;
|
|
|
- if (SDL_FindInHashTable(env->strings, name, &value)) {
|
|
|
- result = SDL_RemoveFromHashTable(env->strings, name);
|
|
|
- } else {
|
|
|
- result = true;
|
|
|
- }
|
|
|
- }
|
|
|
- SDL_UnlockMutex(env->lock);
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-void SDL_DestroyEnvironment(SDL_Environment *env)
|
|
|
-{
|
|
|
- if (!env || env == SDL_environment) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- SDL_DestroyMutex(env->lock);
|
|
|
- SDL_DestroyHashTable(env->strings);
|
|
|
- SDL_free(env);
|
|
|
+ return SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name);
|
|
|
}
|