sdl2-compat: env: sync environment variables during subsystem init (#339)

From f58c132840b51aac184d17593ab60d41b54c9ba9 Mon Sep 17 00:00:00 2001
From: Cameron Gutman <[EMAIL REDACTED]>
Date: Sun, 9 Feb 2025 18:06:00 -0600
Subject: [PATCH] env: sync environment variables during subsystem init (#339)

---
 src/sdl2_compat.c | 28 +++++++++++++++++++++++++++-
 src/sdl3_syms.h   |  5 +++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index 64a85da0..ca9ebaeb 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -5567,10 +5567,31 @@ SDL_RemoveTimer(SDL2_TimerID id)
     return SDL3_RemoveTimer((SDL_TimerID)id) ? SDL2_TRUE : SDL2_FALSE;
 }
 
+static void SynchronizeEnvironmentVariables()
+{
+    SDL_Environment *env = SDL3_GetEnvironment();
+    SDL_Environment *fresh_env = SDL3_CreateEnvironment(true);
+
+    /* Sync any changes to the C environment into SDL3's cached copy */
+    char **fresh_envp = SDL3_GetEnvironmentVariables(fresh_env);
+    if (fresh_envp) {
+        for (int i = 0; fresh_envp[i]; i++) {
+            char *sep = SDL3_strchr(fresh_envp[i], '=');
+            *sep = '\0';
+            SDL3_SetEnvironmentVariable(env, fresh_envp[i], sep + 1, true);
+        }
+
+        SDL3_free(fresh_envp);
+    }
+
+    SDL3_DestroyEnvironment(fresh_env);
+}
 
 SDL_DECLSPEC int SDLCALL
 SDL_AudioInit(const char *driver_name)
 {
+    SynchronizeEnvironmentVariables();
+
     if (driver_name) {
         SDL3_SetHint("SDL_AUDIO_DRIVER", driver_name);
     }
@@ -5777,6 +5798,9 @@ SDL_DECLSPEC int SDLCALL
 SDL_VideoInit(const char *driver_name)
 {
     int ret;
+
+    SynchronizeEnvironmentVariables();
+
     if (driver_name) {
         SDL3_SetHint("SDL_VIDEO_DRIVER", driver_name);
     }
@@ -5813,6 +5837,8 @@ SDL_InitSubSystem(Uint32 flags)
         return -1;
     }
 
+    SynchronizeEnvironmentVariables();
+
     /* Update IME UI hint */
     if (flags & SDL_INIT_VIDEO) {
         const char *old_hint;
@@ -6464,7 +6490,7 @@ SDL_OpenAudio(SDL2_AudioSpec *desired2, SDL2_AudioSpec *obtained2)
 
     /* Start up the audio driver, if necessary. This is legacy behaviour! */
     if (!SDL3_WasInit(SDL_INIT_AUDIO)) {
-        if (!SDL3_InitSubSystem(SDL_INIT_AUDIO)) {
+        if (SDL_AudioInit(NULL) < 0) {
             return -1;
         }
     }
diff --git a/src/sdl3_syms.h b/src/sdl3_syms.h
index 3738e55b..16a9ba06 100644
--- a/src/sdl3_syms.h
+++ b/src/sdl3_syms.h
@@ -139,6 +139,7 @@ SDL3_SYM(SDL_AudioStream*,CreateAudioStream,(const SDL_AudioSpec *a, const SDL_A
 SDL3_SYM(SDL_Cursor*,CreateColorCursor,(SDL_Surface *a, int b, int c),(a,b,c),return)
 SDL3_SYM_RENAMED(SDL_Condition*,CreateCond,CreateCondition,(void),(),return)
 SDL3_SYM_PASSTHROUGH(SDL_Cursor*,CreateCursor,(const Uint8 *a, const Uint8 *b, int c, int d, int e, int f),(a,b,c,d,e,f),return)
+SDL3_SYM(SDL_Environment*,CreateEnvironment,(bool a),(a),return)
 SDL3_SYM(int,CreateHapticEffect,(SDL_Haptic *a, const SDL_HapticEffect *b),(a,b),return)
 SDL3_SYM_PASSTHROUGH(SDL_Mutex*,CreateMutex,(void),(),return)
 SDL3_SYM(SDL_Window*,CreatePopupWindow,(SDL_Window *a, int b, int c, int d, int e, SDL_WindowFlags f),(a,b,c,d,e,f),return)
@@ -159,6 +160,7 @@ SDL3_SYM(void,RemoveHintCallback,(const char *a, SDL_HintCallback b, void *c),(a
 SDL3_SYM_PASSTHROUGH(void,Delay,(Uint32 a),(a),)
 SDL3_SYM(void,DestroyAudioStream,(SDL_AudioStream *a),(a),)
 SDL3_SYM_RENAMED(void,DestroyCond,DestroyCondition,(SDL_Condition *a),(a),)
+SDL3_SYM(void,DestroyEnvironment,(SDL_Environment *a),(a),)
 SDL3_SYM_PASSTHROUGH(void,DestroyMutex,(SDL_Mutex *a),(a),)
 SDL3_SYM(void,DestroyPalette,(SDL_Palette *a),(a),)
 SDL3_SYM(void,DestroyProperties,(SDL_PropertiesID a),(a),)
@@ -273,6 +275,8 @@ SDL3_SYM(SDL_DisplayID,GetDisplayForWindow,(SDL_Window *a),(a),return)
 SDL3_SYM(const char*,GetDisplayName,(SDL_DisplayID a),(a),return)
 SDL3_SYM(bool,GetDisplayUsableBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return)
 SDL3_SYM(SDL_DisplayID*,GetDisplays,(int *a),(a),return)
+SDL3_SYM(SDL_Environment*,GetEnvironment,(void),(),return)
+SDL3_SYM(char**,GetEnvironmentVariables,(SDL_Environment *a),(a),return)
 SDL3_SYM_PASSTHROUGH(const char*,GetError,(void),(),return)
 SDL3_SYM(bool,GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),)
 SDL3_SYM(float,GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return)
@@ -607,6 +611,7 @@ SDL3_SYM(bool,SetAudioStreamPutCallback,(SDL_AudioStream *a, SDL_AudioStreamCall
 SDL3_SYM(bool,SetBooleanProperty,(SDL_PropertiesID a, const char *b, bool c),(a,b,c),return)
 SDL3_SYM_PASSTHROUGH_RETCODE(bool,SetClipboardText,(const char *a),(a),return)
 SDL3_SYM(bool,SetCursor,(SDL_Cursor *a),(a),return)
+SDL3_SYM(bool,SetEnvironmentVariable,(SDL_Environment *a, const char *b, const char *c, bool d),(a,b,c,d),return)
 SDL3_SYM(void,SetEventEnabled,(Uint32 a, bool b),(a,b),)
 SDL3_SYM(void,SetEventFilter,(SDL_EventFilter a, void *b),(a,b),)
 SDL3_SYM(void,SetGamepadEventsEnabled,(bool a),(a),)