Implemented SDL_setenv(), moved SDL_putenv() to compat.
authorRyan C. Gordon <icculus@icculus.org>
Wed, 16 Dec 2009 10:59:51 +0000
changeset 358115eea7a1fa97
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
     1.1 --- a/configure.in	Wed Dec 16 08:17:05 2009 +0000
     1.2 +++ b/configure.in	Wed Dec 16 10:59:51 2009 +0000
     1.3 @@ -207,7 +207,7 @@
     1.4          AC_DEFINE(HAVE_MPROTECT)
     1.5          ]),
     1.6      )
     1.7 -    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)
     1.8 +    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)
     1.9  
    1.10      AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"])
    1.11      AC_CHECK_FUNCS(ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt)
     2.1 --- a/include/SDL_compat.h	Wed Dec 16 08:17:05 2009 +0000
     2.2 +++ b/include/SDL_compat.h	Wed Dec 16 10:59:51 2009 +0000
     2.3 @@ -297,6 +297,8 @@
     2.4  
     2.5  #define SDL_RenderFill  SDL_RenderRect
     2.6  
     2.7 +extern DECLSPEC int SDLCALL SDL_putenv(const char *variable);
     2.8 +
     2.9  /*@}*//*Compatibility*/
    2.10  
    2.11  /* Ends C function definitions when using C++ */
     3.1 --- a/include/SDL_config.h.in	Wed Dec 16 08:17:05 2009 +0000
     3.2 +++ b/include/SDL_config.h.in	Wed Dec 16 10:59:51 2009 +0000
     3.3 @@ -90,6 +90,7 @@
     3.4  #undef HAVE_ALLOCA
     3.5  #ifndef _WIN32 /* Don't use C runtime versions of these on Windows */
     3.6  #undef HAVE_GETENV
     3.7 +#undef HAVE_SETENV
     3.8  #undef HAVE_PUTENV
     3.9  #undef HAVE_UNSETENV
    3.10  #endif
     4.1 --- a/include/SDL_config_iphoneos.h	Wed Dec 16 08:17:05 2009 +0000
     4.2 +++ b/include/SDL_config_iphoneos.h	Wed Dec 16 10:59:51 2009 +0000
     4.3 @@ -61,7 +61,9 @@
     4.4  #define HAVE_FREE	1
     4.5  #define HAVE_ALLOCA	1
     4.6  #define HAVE_GETENV	1
     4.7 +#define HAVE_SETENV	1
     4.8  #define HAVE_PUTENV	1
     4.9 +#define HAVE_SETENV	1
    4.10  #define HAVE_UNSETENV	1
    4.11  #define HAVE_QSORT	1
    4.12  #define HAVE_ABS	1
     5.1 --- a/include/SDL_config_macosx.h	Wed Dec 16 08:17:05 2009 +0000
     5.2 +++ b/include/SDL_config_macosx.h	Wed Dec 16 10:59:51 2009 +0000
     5.3 @@ -60,6 +60,7 @@
     5.4  #define HAVE_FREE	1
     5.5  #define HAVE_ALLOCA	1
     5.6  #define HAVE_GETENV	1
     5.7 +#define HAVE_SETENV	1
     5.8  #define HAVE_PUTENV	1
     5.9  #define HAVE_UNSETENV	1
    5.10  #define HAVE_QSORT	1
     6.1 --- a/include/SDL_config_nintendods.h	Wed Dec 16 08:17:05 2009 +0000
     6.2 +++ b/include/SDL_config_nintendods.h	Wed Dec 16 10:59:51 2009 +0000
     6.3 @@ -62,6 +62,7 @@
     6.4  #define HAVE_FREE	1
     6.5  #define HAVE_ALLOCA	1
     6.6  #define HAVE_GETENV	1
     6.7 +#define HAVE_SETENV	1
     6.8  #define HAVE_PUTENV	1
     6.9  #define HAVE_QSORT	1
    6.10  #define HAVE_ABS	1
     7.1 --- a/include/SDL_config_pandora.h	Wed Dec 16 08:17:05 2009 +0000
     7.2 +++ b/include/SDL_config_pandora.h	Wed Dec 16 10:59:51 2009 +0000
     7.3 @@ -53,6 +53,7 @@
     7.4  #define HAVE_FREE 1
     7.5  #define HAVE_ALLOCA 1
     7.6  #define HAVE_GETENV 1
     7.7 +#define HAVE_SETENV	1
     7.8  #define HAVE_PUTENV 1
     7.9  #define HAVE_UNSETENV 1
    7.10  #define HAVE_QSORT 1
     8.1 --- a/include/SDL_config_wiz.h	Wed Dec 16 08:17:05 2009 +0000
     8.2 +++ b/include/SDL_config_wiz.h	Wed Dec 16 10:59:51 2009 +0000
     8.3 @@ -58,6 +58,7 @@
     8.4  #define HAVE_FREE 1
     8.5  #define HAVE_ALLOCA 1
     8.6  #define HAVE_GETENV 1
     8.7 +#define HAVE_SETENV	1
     8.8  #define HAVE_PUTENV 1
     8.9  #define HAVE_UNSETENV 1
    8.10  #define HAVE_QSORT 1
     9.1 --- a/include/SDL_stdinc.h	Wed Dec 16 08:17:05 2009 +0000
     9.2 +++ b/include/SDL_stdinc.h	Wed Dec 16 10:59:51 2009 +0000
     9.3 @@ -267,20 +267,12 @@
     9.4  extern DECLSPEC char *SDLCALL SDL_getenv(const char *name);
     9.5  #endif
     9.6  
     9.7 -/**
     9.8 - * \warning On some platforms, the string you pass to SDL_putenv() becomes
     9.9 - *          part of the environment table directly...it will use this specific
    9.10 - *          buffer, and not a copy of it! This means you can't free it, and
    9.11 - *          other pieces of code may try to write to it. In practice, this
    9.12 - *          isn't a big deal, but be aware of the possibility.
    9.13 - *          However, due to this issue, you should be prepared to
    9.14 - *          pass a (char*), or be willing to cast away the constness of your
    9.15 - *          string for this call.
    9.16 - */
    9.17 -#ifdef HAVE_PUTENV
    9.18 -#define SDL_putenv	putenv
    9.19 +/* SDL_putenv() has moved to SDL_compat. */
    9.20 +#ifdef HAVE_SETENV
    9.21 +#define SDL_setenv	setenv
    9.22  #else
    9.23 -extern DECLSPEC int SDLCALL SDL_putenv(const char *variable);
    9.24 +extern DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value,
    9.25 +                                       int overwrite);
    9.26  #endif
    9.27  
    9.28  #ifdef HAVE_QSORT
    10.1 --- a/src/SDL_compat.c	Wed Dec 16 08:17:05 2009 +0000
    10.2 +++ b/src/SDL_compat.c	Wed Dec 16 10:59:51 2009 +0000
    10.3 @@ -1754,4 +1754,26 @@
    10.4      return previous;
    10.5  }
    10.6  
    10.7 +
    10.8 +int
    10.9 +SDL_putenv(const char *_var)
   10.10 +{
   10.11 +    char *ptr = NULL;
   10.12 +    char *var = SDL_strdup(_var);
   10.13 +    if (var == NULL) {
   10.14 +        return -1;  /* we don't set errno. */
   10.15 +    }
   10.16 +
   10.17 +    ptr = strchr(var, '=');
   10.18 +    if (ptr == NULL) {
   10.19 +        SDL_free(var);
   10.20 +        return -1;
   10.21 +    }
   10.22 +
   10.23 +    *ptr = '\0';  /* split the string into name and value. */
   10.24 +    SDL_setenv(var, ptr + 1, 1);
   10.25 +    SDL_free(var);
   10.26 +    return 0;
   10.27 +}
   10.28 +
   10.29  /* vi: set ts=4 sw=4 expandtab: */
    11.1 --- a/src/audio/esd/SDL_esdaudio.c	Wed Dec 16 08:17:05 2009 +0000
    11.2 +++ b/src/audio/esd/SDL_esdaudio.c	Wed Dec 16 10:59:51 2009 +0000
    11.3 @@ -321,9 +321,7 @@
    11.4          int connection = 0;
    11.5  
    11.6          /* Don't start ESD if it's not running */
    11.7 -        if (SDL_getenv("ESD_NO_SPAWN") == NULL) {
    11.8 -            SDL_putenv("ESD_NO_SPAWN=1");
    11.9 -        }
   11.10 +        SDL_setenv("ESD_NO_SPAWN", "1", 0);
   11.11  
   11.12          connection = SDL_NAME(esd_open_sound) (NULL);
   11.13          if (connection < 0) {
    12.1 --- a/src/stdlib/SDL_getenv.c	Wed Dec 16 08:17:05 2009 +0000
    12.2 +++ b/src/stdlib/SDL_getenv.c	Wed Dec 16 10:59:51 2009 +0000
    12.3 @@ -35,31 +35,18 @@
    12.4  static char *SDL_envmem = NULL; /* Ugh, memory leak */
    12.5  static size_t SDL_envmemlen = 0;
    12.6  
    12.7 -/* Put a variable of the form "name=value" into the environment */
    12.8 +/* Put a variable into the environment */
    12.9  int
   12.10 -SDL_putenv(const char *variable)
   12.11 +SDL_setenv(const char *name, const char *value, int overwrite)
   12.12  {
   12.13 -    size_t bufferlen;
   12.14 -    char *value;
   12.15 -    const char *sep;
   12.16 -
   12.17 -    sep = SDL_strchr(variable, '=');
   12.18 -    if (sep == NULL) {
   12.19 -        return -1;
   12.20 +    if (!overwrite) {
   12.21 +        char ch = 0;
   12.22 +        const size_t len = GetEnvironmentVariable(name, &ch, sizeof (ch));
   12.23 +        if (len > 0) {
   12.24 +            return 0;  /* asked not to overwrite existing value. */
   12.25 +        }
   12.26      }
   12.27 -    bufferlen = SDL_strlen(variable) + 1;
   12.28 -    if (bufferlen > SDL_envmemlen) {
   12.29 -        char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
   12.30 -        if (newmem == NULL) {
   12.31 -            return -1;
   12.32 -        }
   12.33 -        SDL_envmem = newmem;
   12.34 -        SDL_envmemlen = bufferlen;
   12.35 -    }
   12.36 -    SDL_strlcpy(SDL_envmem, variable, bufferlen);
   12.37 -    value = SDL_envmem + (sep - variable);
   12.38 -    *value++ = '\0';
   12.39 -    if (!SetEnvironmentVariable(SDL_envmem, *value ? value : NULL)) {
   12.40 +    if (!SetEnvironmentVariable(name, *value ? value : NULL)) {
   12.41          return -1;
   12.42      }
   12.43      return 0;
   12.44 @@ -92,36 +79,31 @@
   12.45  
   12.46  static char **SDL_env = (char **) 0;
   12.47  
   12.48 -/* Put a variable of the form "name=value" into the environment */
   12.49 +/* Put a variable into the environment */
   12.50  int
   12.51 -SDL_putenv(const char *variable)
   12.52 +SDL_setenv(const char *name, const char *value, int overwrite)
   12.53  {
   12.54 -    const char *name, *value;
   12.55      int added;
   12.56      int len, i;
   12.57      char **new_env;
   12.58      char *new_variable;
   12.59  
   12.60      /* A little error checking */
   12.61 -    if (!variable) {
   12.62 -        return (-1);
   12.63 -    }
   12.64 -    name = variable;
   12.65 -    for (value = variable; *value && (*value != '='); ++value) {
   12.66 -        /* Keep looking for '=' */ ;
   12.67 -    }
   12.68 -    if (*value) {
   12.69 -        ++value;
   12.70 -    } else {
   12.71 +    if (!name || !value) {
   12.72          return (-1);
   12.73      }
   12.74  
   12.75      /* Allocate memory for the variable */
   12.76 -    new_variable = SDL_strdup(variable);
   12.77 +    len = SDL_strlen(name) + SDL_strlen(value) + 2;
   12.78 +    new_variable = (char *) SDL_malloc(len);
   12.79      if (!new_variable) {
   12.80          return (-1);
   12.81      }
   12.82  
   12.83 +    SDL_snprintf(new_variable, len, "%s=%s", name, value);
   12.84 +    value = new_variable + SDL_strlen(name) + 1;
   12.85 +    name = new_variable;
   12.86 +
   12.87      /* Actually put it into the environment */
   12.88      added = 0;
   12.89      i = 0;
   12.90 @@ -135,6 +117,10 @@
   12.91          }
   12.92          /* If we found it, just replace the entry */
   12.93          if (SDL_env[i]) {
   12.94 +            if (!overwrite) {
   12.95 +                SDL_free(new_variable);
   12.96 +                return 0;
   12.97 +            }
   12.98              SDL_free(SDL_env[i]);
   12.99              SDL_env[i] = new_variable;
  12.100              added = 1;
  12.101 @@ -180,6 +166,36 @@
  12.102  
  12.103  #endif /* !HAVE_GETENV */
  12.104  
  12.105 +
  12.106 +/* We have a real environment table, but no real setenv? Fake it w/ putenv. */
  12.107 +#if (defined(HAVE_GETENV) && defined(HAVE_PUTENV) && !defined(HAVE_SETENV))
  12.108 +int
  12.109 +SDL_setenv(const char *name, const char *value, int overwrite)
  12.110 +{
  12.111 +    size_t len;
  12.112 +    char *new_variable;
  12.113 +
  12.114 +    if (getenv(name) != NULL) {
  12.115 +        if (overwrite) {
  12.116 +            unsetenv(name);
  12.117 +        } else {
  12.118 +            return 0;  /* leave the existing one there. */
  12.119 +        }
  12.120 +    }
  12.121 +
  12.122 +    /* This leaks. Sorry. Get a better OS so we don't have to do this. */
  12.123 +    len = SDL_strlen(name) + SDL_strlen(value) + 2;
  12.124 +    new_variable = (char *) SDL_malloc(len);
  12.125 +    if (!new_variable) {
  12.126 +        return (-1);
  12.127 +    }
  12.128 +
  12.129 +    SDL_snprintf(new_variable, len, "%s=%s", name, value);
  12.130 +    return putenv(new_variable);
  12.131 +}
  12.132 +#endif
  12.133 +
  12.134 +
  12.135  #ifdef TEST_MAIN
  12.136  #include <stdio.h>
  12.137  
    13.1 --- a/test/testime.c	Wed Dec 16 08:17:05 2009 +0000
    13.2 +++ b/test/testime.c	Wed Dec 16 10:59:51 2009 +0000
    13.3 @@ -60,7 +60,7 @@
    13.4          }
    13.5      }
    13.6  
    13.7 -    SDL_putenv("SDL_VIDEO_WINDOW_POS=center");
    13.8 +    SDL_setenv("SDL_VIDEO_WINDOW_POS", "center", 1);
    13.9      if (SDL_Init(SDL_INIT_VIDEO) < 0)
   13.10      {
   13.11          fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());