Implemented SDL_setenv(), moved SDL_putenv() to compat.
authorRyan C. Gordon <icculus@icculus.org>
Wed, 16 Dec 2009 10:59:51 +0000
changeset 3581 15eea7a1fa97
parent 3580 951dd6a5d1a2
child 3582 ecfc42323d0c
Implemented SDL_setenv(), moved SDL_putenv() to compat. Fixes Bugzilla #779.
configure.in
include/SDL_compat.h
include/SDL_config.h.in
include/SDL_config_iphoneos.h
include/SDL_config_macosx.h
include/SDL_config_nintendods.h
include/SDL_config_pandora.h
include/SDL_config_wiz.h
include/SDL_stdinc.h
src/SDL_compat.c
src/audio/esd/SDL_esdaudio.c
src/stdlib/SDL_getenv.c
test/testime.c
--- a/configure.in	Wed Dec 16 08:17:05 2009 +0000
+++ b/configure.in	Wed Dec 16 10:59:51 2009 +0000
@@ -207,7 +207,7 @@
         AC_DEFINE(HAVE_MPROTECT)
         ]),
     )
-    AC_CHECK_FUNCS(malloc calloc realloc free getenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf sigaction setjmp nanosleep sysctlbyname)
+    AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf sigaction setjmp nanosleep sysctlbyname)
 
     AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"])
     AC_CHECK_FUNCS(ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt)
--- a/include/SDL_compat.h	Wed Dec 16 08:17:05 2009 +0000
+++ b/include/SDL_compat.h	Wed Dec 16 10:59:51 2009 +0000
@@ -297,6 +297,8 @@
 
 #define SDL_RenderFill  SDL_RenderRect
 
+extern DECLSPEC int SDLCALL SDL_putenv(const char *variable);
+
 /*@}*//*Compatibility*/
 
 /* Ends C function definitions when using C++ */
--- a/include/SDL_config.h.in	Wed Dec 16 08:17:05 2009 +0000
+++ b/include/SDL_config.h.in	Wed Dec 16 10:59:51 2009 +0000
@@ -90,6 +90,7 @@
 #undef HAVE_ALLOCA
 #ifndef _WIN32 /* Don't use C runtime versions of these on Windows */
 #undef HAVE_GETENV
+#undef HAVE_SETENV
 #undef HAVE_PUTENV
 #undef HAVE_UNSETENV
 #endif
--- a/include/SDL_config_iphoneos.h	Wed Dec 16 08:17:05 2009 +0000
+++ b/include/SDL_config_iphoneos.h	Wed Dec 16 10:59:51 2009 +0000
@@ -61,7 +61,9 @@
 #define HAVE_FREE	1
 #define HAVE_ALLOCA	1
 #define HAVE_GETENV	1
+#define HAVE_SETENV	1
 #define HAVE_PUTENV	1
+#define HAVE_SETENV	1
 #define HAVE_UNSETENV	1
 #define HAVE_QSORT	1
 #define HAVE_ABS	1
--- a/include/SDL_config_macosx.h	Wed Dec 16 08:17:05 2009 +0000
+++ b/include/SDL_config_macosx.h	Wed Dec 16 10:59:51 2009 +0000
@@ -60,6 +60,7 @@
 #define HAVE_FREE	1
 #define HAVE_ALLOCA	1
 #define HAVE_GETENV	1
+#define HAVE_SETENV	1
 #define HAVE_PUTENV	1
 #define HAVE_UNSETENV	1
 #define HAVE_QSORT	1
--- a/include/SDL_config_nintendods.h	Wed Dec 16 08:17:05 2009 +0000
+++ b/include/SDL_config_nintendods.h	Wed Dec 16 10:59:51 2009 +0000
@@ -62,6 +62,7 @@
 #define HAVE_FREE	1
 #define HAVE_ALLOCA	1
 #define HAVE_GETENV	1
+#define HAVE_SETENV	1
 #define HAVE_PUTENV	1
 #define HAVE_QSORT	1
 #define HAVE_ABS	1
--- a/include/SDL_config_pandora.h	Wed Dec 16 08:17:05 2009 +0000
+++ b/include/SDL_config_pandora.h	Wed Dec 16 10:59:51 2009 +0000
@@ -53,6 +53,7 @@
 #define HAVE_FREE 1
 #define HAVE_ALLOCA 1
 #define HAVE_GETENV 1
+#define HAVE_SETENV	1
 #define HAVE_PUTENV 1
 #define HAVE_UNSETENV 1
 #define HAVE_QSORT 1
--- a/include/SDL_config_wiz.h	Wed Dec 16 08:17:05 2009 +0000
+++ b/include/SDL_config_wiz.h	Wed Dec 16 10:59:51 2009 +0000
@@ -58,6 +58,7 @@
 #define HAVE_FREE 1
 #define HAVE_ALLOCA 1
 #define HAVE_GETENV 1
+#define HAVE_SETENV	1
 #define HAVE_PUTENV 1
 #define HAVE_UNSETENV 1
 #define HAVE_QSORT 1
--- a/include/SDL_stdinc.h	Wed Dec 16 08:17:05 2009 +0000
+++ b/include/SDL_stdinc.h	Wed Dec 16 10:59:51 2009 +0000
@@ -267,20 +267,12 @@
 extern DECLSPEC char *SDLCALL SDL_getenv(const char *name);
 #endif
 
-/**
- * \warning On some platforms, the string you pass to SDL_putenv() becomes
- *          part of the environment table directly...it will use this specific
- *          buffer, and not a copy of it! This means you can't free it, and
- *          other pieces of code may try to write to it. In practice, this
- *          isn't a big deal, but be aware of the possibility.
- *          However, due to this issue, you should be prepared to
- *          pass a (char*), or be willing to cast away the constness of your
- *          string for this call.
- */
-#ifdef HAVE_PUTENV
-#define SDL_putenv	putenv
+/* SDL_putenv() has moved to SDL_compat. */
+#ifdef HAVE_SETENV
+#define SDL_setenv	setenv
 #else
-extern DECLSPEC int SDLCALL SDL_putenv(const char *variable);
+extern DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value,
+                                       int overwrite);
 #endif
 
 #ifdef HAVE_QSORT
--- a/src/SDL_compat.c	Wed Dec 16 08:17:05 2009 +0000
+++ b/src/SDL_compat.c	Wed Dec 16 10:59:51 2009 +0000
@@ -1754,4 +1754,26 @@
     return previous;
 }
 
+
+int
+SDL_putenv(const char *_var)
+{
+    char *ptr = NULL;
+    char *var = SDL_strdup(_var);
+    if (var == NULL) {
+        return -1;  /* we don't set errno. */
+    }
+
+    ptr = strchr(var, '=');
+    if (ptr == NULL) {
+        SDL_free(var);
+        return -1;
+    }
+
+    *ptr = '\0';  /* split the string into name and value. */
+    SDL_setenv(var, ptr + 1, 1);
+    SDL_free(var);
+    return 0;
+}
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/esd/SDL_esdaudio.c	Wed Dec 16 08:17:05 2009 +0000
+++ b/src/audio/esd/SDL_esdaudio.c	Wed Dec 16 10:59:51 2009 +0000
@@ -321,9 +321,7 @@
         int connection = 0;
 
         /* Don't start ESD if it's not running */
-        if (SDL_getenv("ESD_NO_SPAWN") == NULL) {
-            SDL_putenv("ESD_NO_SPAWN=1");
-        }
+        SDL_setenv("ESD_NO_SPAWN", "1", 0);
 
         connection = SDL_NAME(esd_open_sound) (NULL);
         if (connection < 0) {
--- a/src/stdlib/SDL_getenv.c	Wed Dec 16 08:17:05 2009 +0000
+++ b/src/stdlib/SDL_getenv.c	Wed Dec 16 10:59:51 2009 +0000
@@ -35,31 +35,18 @@
 static char *SDL_envmem = NULL; /* Ugh, memory leak */
 static size_t SDL_envmemlen = 0;
 
-/* Put a variable of the form "name=value" into the environment */
+/* Put a variable into the environment */
 int
-SDL_putenv(const char *variable)
+SDL_setenv(const char *name, const char *value, int overwrite)
 {
-    size_t bufferlen;
-    char *value;
-    const char *sep;
-
-    sep = SDL_strchr(variable, '=');
-    if (sep == NULL) {
-        return -1;
+    if (!overwrite) {
+        char ch = 0;
+        const size_t len = GetEnvironmentVariable(name, &ch, sizeof (ch));
+        if (len > 0) {
+            return 0;  /* asked not to overwrite existing value. */
+        }
     }
-    bufferlen = SDL_strlen(variable) + 1;
-    if (bufferlen > SDL_envmemlen) {
-        char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
-        if (newmem == NULL) {
-            return -1;
-        }
-        SDL_envmem = newmem;
-        SDL_envmemlen = bufferlen;
-    }
-    SDL_strlcpy(SDL_envmem, variable, bufferlen);
-    value = SDL_envmem + (sep - variable);
-    *value++ = '\0';
-    if (!SetEnvironmentVariable(SDL_envmem, *value ? value : NULL)) {
+    if (!SetEnvironmentVariable(name, *value ? value : NULL)) {
         return -1;
     }
     return 0;
@@ -92,36 +79,31 @@
 
 static char **SDL_env = (char **) 0;
 
-/* Put a variable of the form "name=value" into the environment */
+/* Put a variable into the environment */
 int
-SDL_putenv(const char *variable)
+SDL_setenv(const char *name, const char *value, int overwrite)
 {
-    const char *name, *value;
     int added;
     int len, i;
     char **new_env;
     char *new_variable;
 
     /* A little error checking */
-    if (!variable) {
-        return (-1);
-    }
-    name = variable;
-    for (value = variable; *value && (*value != '='); ++value) {
-        /* Keep looking for '=' */ ;
-    }
-    if (*value) {
-        ++value;
-    } else {
+    if (!name || !value) {
         return (-1);
     }
 
     /* Allocate memory for the variable */
-    new_variable = SDL_strdup(variable);
+    len = SDL_strlen(name) + SDL_strlen(value) + 2;
+    new_variable = (char *) SDL_malloc(len);
     if (!new_variable) {
         return (-1);
     }
 
+    SDL_snprintf(new_variable, len, "%s=%s", name, value);
+    value = new_variable + SDL_strlen(name) + 1;
+    name = new_variable;
+
     /* Actually put it into the environment */
     added = 0;
     i = 0;
@@ -135,6 +117,10 @@
         }
         /* If we found it, just replace the entry */
         if (SDL_env[i]) {
+            if (!overwrite) {
+                SDL_free(new_variable);
+                return 0;
+            }
             SDL_free(SDL_env[i]);
             SDL_env[i] = new_variable;
             added = 1;
@@ -180,6 +166,36 @@
 
 #endif /* !HAVE_GETENV */
 
+
+/* We have a real environment table, but no real setenv? Fake it w/ putenv. */
+#if (defined(HAVE_GETENV) && defined(HAVE_PUTENV) && !defined(HAVE_SETENV))
+int
+SDL_setenv(const char *name, const char *value, int overwrite)
+{
+    size_t len;
+    char *new_variable;
+
+    if (getenv(name) != NULL) {
+        if (overwrite) {
+            unsetenv(name);
+        } else {
+            return 0;  /* leave the existing one there. */
+        }
+    }
+
+    /* This leaks. Sorry. Get a better OS so we don't have to do this. */
+    len = SDL_strlen(name) + SDL_strlen(value) + 2;
+    new_variable = (char *) SDL_malloc(len);
+    if (!new_variable) {
+        return (-1);
+    }
+
+    SDL_snprintf(new_variable, len, "%s=%s", name, value);
+    return putenv(new_variable);
+}
+#endif
+
+
 #ifdef TEST_MAIN
 #include <stdio.h>
 
--- a/test/testime.c	Wed Dec 16 08:17:05 2009 +0000
+++ b/test/testime.c	Wed Dec 16 10:59:51 2009 +0000
@@ -60,7 +60,7 @@
         }
     }
 
-    SDL_putenv("SDL_VIDEO_WINDOW_POS=center");
+    SDL_setenv("SDL_VIDEO_WINDOW_POS", "center", 1);
     if (SDL_Init(SDL_INIT_VIDEO) < 0)
     {
         fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());