Simple Directmedia Layer

Added thread-safe environment functions

Also marked the existing functions as unsafe, as they can cause crashes if used in multi-threaded applications.

As a bonus, since the new functions are hashtable based, hint environment lookups are much faster.

+3 -3
docs/README-vita.md
··· 21 21 ----- 22 22 * gles1/gles2 support and renderers are disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PVR=ON` 23 23 These renderers support 720p and 1080i resolutions. These can be specified with: 24 - `SDL_setenv("VITA_RESOLUTION", "720", 1);` and `SDL_setenv("VITA_RESOLUTION", "1080", 1);` 24 + `SDL_SetHint(SDL_HINT_VITA_RESOLUTION, "720");` and `SDL_SetHint(SDL_HINT_VITA_RESOLUTION, "1080");` 25 25 * Desktop GL 1.X and 2.X support and renderers are also disabled by default and also can be enabled with `-DVIDEO_VITA_PVR=ON` as long as gl4es4vita is present in your SDK. 26 - They support the same resolutions as the gles1/gles2 backends and require specifying `SDL_setenv("VITA_PVR_OGL", "1", 1);` 26 + They support the same resolutions as the gles1/gles2 backends and require specifying `SDL_SetHint(SDL_HINT_VITA_PVR_OPENGL, "1");` 27 27 anytime before video subsystem initialization. 28 28 * gles2 support via PIB is disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PIB=ON` 29 29 * By default SDL emits mouse events for touch events on every touchscreen. 30 30 Vita has two touchscreens, so it's recommended to use `SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");` and handle touch events instead. 31 31 Individual touchscreens can be disabled with: 32 - `SDL_setenv("VITA_DISABLE_TOUCH_FRONT", "1", 1);` and `SDL_setenv("VITA_DISABLE_TOUCH_BACK", "1", 1);` 32 + `SDL_SetHint(SDL_HINT_VITA_ENABLE_FRONT_TOUCH, "0");` and `SDL_SetHint(SDL_HINT_VITA_ENABLE_BACK_TOUCH, "0");` 33 33 * Support for L2/R2/R3/R3 buttons, haptic feedback and gamepad led only available on PSTV, or when using external ds4 gamepad on vita.
+207 -3
include/SDL3/SDL_stdinc.h
··· 978 978 */ 979 979 extern SDL_DECLSPEC int SDLCALL SDL_GetNumAllocations(void); 980 980 981 - extern SDL_DECLSPEC const char * SDLCALL SDL_getenv(const char *name); 982 - extern SDL_DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int overwrite); 983 - extern SDL_DECLSPEC int SDLCALL SDL_unsetenv(const char *name); 981 + /** 982 + * A thread-safe set of environment variables 983 + * 984 + * \since This struct is available since SDL 3.0.0. 985 + * 986 + * \sa SDL_GetEnvironment 987 + * \sa SDL_CleanupEnvironment 988 + * \sa SDL_CreateEnvironment 989 + * \sa SDL_GetEnvironmentVariable 990 + * \sa SDL_GetEnvironmentVariables 991 + * \sa SDL_SetEnvironmentVariable 992 + * \sa SDL_UnsetEnvironmentVariable 993 + * \sa SDL_DestroyEnvironment 994 + */ 995 + typedef struct SDL_Environment SDL_Environment; 996 + 997 + /** 998 + * Get the process environment. 999 + * 1000 + * This is initialized at application start and is not affected by setenv() and unsetenv() calls after that point. Use SDL_SetEnvironmentVariable() and SDL_UnsetEnvironmentVariable() if you want to modify this environment. 1001 + * 1002 + * \returns a pointer to the environment for the process or NULL on failure; call SDL_GetError() 1003 + * for more information. 1004 + * 1005 + * \threadsafety It is safe to call this function from any thread. 1006 + * 1007 + * \since This function is available since SDL 3.0.0. 1008 + * 1009 + * \sa SDL_CleanupEnvironment 1010 + * \sa SDL_GetEnvironmentVariable 1011 + * \sa SDL_GetEnvironmentVariables 1012 + * \sa SDL_SetEnvironmentVariable 1013 + * \sa SDL_UnsetEnvironmentVariable 1014 + */ 1015 + extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_GetEnvironment(void); 1016 + 1017 + /** 1018 + * Cleanup the process environment. 1019 + * 1020 + * This is called during SDL_Quit() to free the process environment. If SDL_GetEnvironment() is called afterwards, it will automatically create a new environment copied from the C runtime environment. 1021 + * 1022 + * \threadsafety This function is not thread-safe. 1023 + * 1024 + * \since This function is available since SDL 3.0.0. 1025 + * 1026 + * \sa SDL_GetEnvironment 1027 + */ 1028 + extern SDL_DECLSPEC void SDLCALL SDL_CleanupEnvironment(void); 1029 + 1030 + /** 1031 + * Create a set of environment variables 1032 + * 1033 + * \param empty SDL_TRUE to create an empty environment, SDL_FALSE to initialize it from the C runtime environment. 1034 + * \returns a pointer to the new environment or NULL on failure; call SDL_GetError() 1035 + * for more information. 1036 + * 1037 + * \threadsafety If `empty` is SDL_TRUE, it is safe to call this function from any thread, otherwise it is safe if no other threads are calling setenv() or unsetenv() 1038 + * 1039 + * \since This function is available since SDL 3.0.0. 1040 + * 1041 + * \sa SDL_GetEnvironmentVariable 1042 + * \sa SDL_GetEnvironmentVariables 1043 + * \sa SDL_SetEnvironmentVariable 1044 + * \sa SDL_UnsetEnvironmentVariable 1045 + * \sa SDL_DestroyEnvironment 1046 + */ 1047 + extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_CreateEnvironment(SDL_bool empty); 1048 + 1049 + /** 1050 + * Get the value of a variable in the environment. 1051 + * 1052 + * \param env the environment to query. 1053 + * \param name the name of the variable to get. 1054 + * \returns a pointer to the value of the variable or NULL if it can't be found. 1055 + * 1056 + * \threadsafety It is safe to call this function from any thread. 1057 + * 1058 + * \since This function is available since SDL 3.0.0. 1059 + * 1060 + * \sa SDL_GetEnvironment 1061 + * \sa SDL_CreateEnvironment 1062 + * \sa SDL_GetEnvironmentVariables 1063 + * \sa SDL_SetEnvironmentVariable 1064 + * \sa SDL_UnsetEnvironmentVariable 1065 + */ 1066 + extern SDL_DECLSPEC const char * SDLCALL SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name); 1067 + 1068 + /** 1069 + * Get all variables in the environment. 1070 + * 1071 + * \param env the environment to query. 1072 + * \returns a NULL terminated array of pointers to environment variables in the form "variable=value" or NULL on 1073 + * failure; call SDL_GetError() for more information. This is a 1074 + * single allocation that should be freed with SDL_free() when it is 1075 + * no longer needed. 1076 + * 1077 + * \threadsafety It is safe to call this function from any thread. 1078 + * 1079 + * \since This function is available since SDL 3.0.0. 1080 + * 1081 + * \sa SDL_GetEnvironment 1082 + * \sa SDL_CreateEnvironment 1083 + * \sa SDL_GetEnvironmentVariables 1084 + * \sa SDL_SetEnvironmentVariable 1085 + * \sa SDL_UnsetEnvironmentVariable 1086 + */ 1087 + extern SDL_DECLSPEC char ** SDLCALL SDL_GetEnvironmentVariables(SDL_Environment *env); 1088 + 1089 + /** 1090 + * Set the value of a variable in the environment. 1091 + * 1092 + * \param env the environment to modify. 1093 + * \param name the name of the variable to set. 1094 + * \param value the value of the variable to set. 1095 + * \param overwrite SDL_TRUE to overwrite the variable if it exists, SDL_FALSE to return success without setting the variable if it already exists. 1096 + * \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError() 1097 + * for more information. 1098 + * 1099 + * \threadsafety It is safe to call this function from any thread. 1100 + * 1101 + * \since This function is available since SDL 3.0.0. 1102 + * 1103 + * \sa SDL_GetEnvironment 1104 + * \sa SDL_CreateEnvironment 1105 + * \sa SDL_GetEnvironmentVariable 1106 + * \sa SDL_GetEnvironmentVariables 1107 + * \sa SDL_UnsetEnvironmentVariable 1108 + */ 1109 + extern SDL_DECLSPEC SDL_bool SDLCALL SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, SDL_bool overwrite); 1110 + 1111 + /** 1112 + * Clear a variable from the environment. 1113 + * 1114 + * \param env the environment to modify. 1115 + * \param name the name of the variable to unset. 1116 + * \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError() 1117 + * for more information. 1118 + * 1119 + * \threadsafety It is safe to call this function from any thread. 1120 + * 1121 + * \since This function is available since SDL 3.0.0. 1122 + * 1123 + * \sa SDL_GetEnvironment 1124 + * \sa SDL_CreateEnvironment 1125 + * \sa SDL_GetEnvironmentVariable 1126 + * \sa SDL_GetEnvironmentVariables 1127 + * \sa SDL_SetEnvironmentVariable 1128 + * \sa SDL_UnsetEnvironmentVariable 1129 + */ 1130 + extern SDL_DECLSPEC SDL_bool SDLCALL SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name); 1131 + 1132 + /** 1133 + * Destroy a set of environment variables. 1134 + * 1135 + * \param env the environment to destroy. 1136 + * 1137 + * \threadsafety It is safe to call this function from any thread, as long as the environment is no longer in use. 1138 + * 1139 + * \since This function is available since SDL 3.0.0. 1140 + * 1141 + * \sa SDL_CreateEnvironment 1142 + */ 1143 + extern SDL_DECLSPEC void SDLCALL SDL_DestroyEnvironment(SDL_Environment *env); 1144 + 1145 + /** 1146 + * Get the value of a variable in the environment. 1147 + * 1148 + * \param name the name of the variable to get. 1149 + * \returns a pointer to the value of the variable or NULL if it can't be found. 1150 + * 1151 + * \threadsafety This function is not thread safe, consider using SDL_GetEnvironmentVariable() instead. 1152 + * 1153 + * \since This function is available since SDL 3.0.0. 1154 + * 1155 + * \sa SDL_GetEnvironmentVariable 1156 + */ 1157 + extern SDL_DECLSPEC const char * SDLCALL SDL_getenv_unsafe(const char *name); 1158 + 1159 + /** 1160 + * Set the value of a variable in the environment. 1161 + * 1162 + * \param name the name of the variable to set. 1163 + * \param value the value of the variable to set. 1164 + * \param overwrite 1 to overwrite the variable if it exists, 0 to return success without setting the variable if it already exists. 1165 + * \returns 0 on success, -1 on error. 1166 + * 1167 + * \threadsafety This function is not thread safe, consider using SDL_SetEnvironmentVariable() instead. 1168 + * 1169 + * \since This function is available since SDL 3.0.0. 1170 + * 1171 + * \sa SDL_SetEnvironmentVariable 1172 + */ 1173 + extern SDL_DECLSPEC int SDLCALL SDL_setenv_unsafe(const char *name, const char *value, int overwrite); 1174 + 1175 + /** 1176 + * Clear a variable from the environment. 1177 + * 1178 + * \param name the name of the variable to unset. 1179 + * \returns 0 on success, -1 on error. 1180 + * 1181 + * \threadsafety This function is not thread safe, consider using SDL_UnsetEnvironmentVariable() instead.. 1182 + * 1183 + * \since This function is available since SDL 3.0.0. 1184 + * 1185 + * \sa SDL_UnsetEnvironmentVariable 1186 + */ 1187 + extern SDL_DECLSPEC int SDLCALL SDL_unsetenv_unsafe(const char *name); 984 1188 985 1189 typedef int (SDLCALL *SDL_CompareCallback)(const void *a, const void *b); 986 1190 extern SDL_DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, SDL_CompareCallback compare);
+2
src/SDL.c
··· 255 255 SDL_InitLog(); 256 256 SDL_InitProperties(); 257 257 SDL_GetGlobalProperties(); 258 + SDL_GetEnvironment(); 258 259 SDL_InitHints(); 259 260 } 260 261 261 262 static void SDL_QuitMainThread(void) 262 263 { 263 264 SDL_QuitHints(); 265 + SDL_CleanupEnvironment(); 264 266 SDL_QuitProperties(); 265 267 SDL_QuitLog(); 266 268 SDL_QuitFilesystem();
+5
src/SDL_hashtable.c
··· 318 318 return false; 319 319 } 320 320 321 + void SDL_NukeFreeKey(const void *key, const void *value, void *unused) 322 + { 323 + SDL_free((void *)key); 324 + } 325 + 321 326 void SDL_NukeFreeValue(const void *key, const void *value, void *unused) 322 327 { 323 328 SDL_free((void *)value);
+1
src/SDL_hashtable.h
··· 55 55 extern Uint32 SDL_HashID(const void *key, void *unused); 56 56 extern bool SDL_KeyMatchID(const void *a, const void *b, void *unused); 57 57 58 + extern void SDL_NukeFreeKey(const void *key, const void *value, void *unused); 58 59 extern void SDL_NukeFreeValue(const void *key, const void *value, void *unused); 59 60 60 61 #endif // SDL_hashtable_h_
+4 -4
src/SDL_hints.c
··· 72 72 return SDL_InvalidParamError("name"); 73 73 } 74 74 75 - const char *env = SDL_getenv(name); 75 + const char *env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name); 76 76 if (env && (priority < SDL_HINT_OVERRIDE)) { 77 77 return SDL_SetError("An environment variable is taking priority"); 78 78 } ··· 126 126 return SDL_InvalidParamError("name"); 127 127 } 128 128 129 - const char *env = SDL_getenv(name); 129 + const char *env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name); 130 130 131 131 const SDL_PropertiesID hints = GetHintProperties(false); 132 132 if (!hints) { ··· 165 165 return; // uh...okay. 166 166 } 167 167 168 - const char *env = SDL_getenv(name); 168 + const char *env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name); 169 169 if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) { 170 170 SDL_HintWatch *entry = hint->callbacks; 171 171 while (entry) { ··· 196 196 return NULL; 197 197 } 198 198 199 - const char *result = SDL_getenv(name); 199 + const char *result = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name); 200 200 201 201 const SDL_PropertiesID hints = GetHintProperties(false); 202 202 if (hints) {
+1 -1
src/audio/SDL_audiodev.c
··· 87 87 } 88 88 89 89 // Figure out what our audio device is 90 - audiodev = SDL_getenv("AUDIODEV"); 90 + audiodev = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "AUDIODEV"); 91 91 if (!audiodev) { 92 92 if (classic) { 93 93 audiodev = SDL_PATH_DEV_AUDIO;
+2 -1
src/core/android/SDL_android.c
··· 1524 1524 const char *utfname = (*env)->GetStringUTFChars(env, name, NULL); 1525 1525 const char *utfvalue = (*env)->GetStringUTFChars(env, value, NULL); 1526 1526 1527 - SDL_setenv(utfname, utfvalue, 1); 1527 + // This is only called at startup, to initialize the environment 1528 + SDL_setenv_unsafe(utfname, utfvalue, 1); 1528 1529 1529 1530 (*env)->ReleaseStringUTFChars(env, name, utfname); 1530 1531 (*env)->ReleaseStringUTFChars(env, value, utfvalue);
+5 -5
src/core/linux/SDL_ibus.c
··· 331 331 } 332 332 333 333 // Use this environment variable if it exists. 334 - addr = SDL_getenv("IBUS_ADDRESS"); 334 + addr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "IBUS_ADDRESS"); 335 335 if (addr && *addr) { 336 336 return SDL_strdup(addr); 337 337 } 338 338 339 339 /* Otherwise, we have to get the hostname, display, machine id, config dir 340 340 and look up the address from a filepath using all those bits, eek. */ 341 - disp_env = SDL_getenv("DISPLAY"); 341 + disp_env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "DISPLAY"); 342 342 343 343 if (!disp_env || !*disp_env) { 344 344 display = SDL_strdup(":0.0"); ··· 363 363 } 364 364 365 365 if (!*host) { 366 - const char *session = SDL_getenv("XDG_SESSION_TYPE"); 366 + const char *session = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE"); 367 367 if (session && SDL_strcmp(session, "wayland") == 0) { 368 368 host = "unix-wayland"; 369 369 } else { ··· 373 373 374 374 SDL_memset(config_dir, 0, sizeof(config_dir)); 375 375 376 - conf_env = SDL_getenv("XDG_CONFIG_HOME"); 376 + conf_env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_CONFIG_HOME"); 377 377 if (conf_env && *conf_env) { 378 378 SDL_strlcpy(config_dir, conf_env, sizeof(config_dir)); 379 379 } else { 380 - const char *home_env = SDL_getenv("HOME"); 380 + const char *home_env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME"); 381 381 if (!home_env || !*home_env) { 382 382 SDL_free(display); 383 383 return NULL;
+2 -2
src/core/linux/SDL_ime.c
··· 44 44 { 45 45 static bool inited = false; 46 46 #ifdef HAVE_FCITX 47 - const char *im_module = SDL_getenv("SDL_IM_MODULE"); 48 - const char *xmodifiers = SDL_getenv("XMODIFIERS"); 47 + const char *im_module = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_IM_MODULE"); 48 + const char *xmodifiers = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XMODIFIERS"); 49 49 #endif 50 50 51 51 if (inited == true) {
+3 -1
src/core/linux/SDL_sandbox.c
··· 33 33 34 34 /* For Snap, we check multiple variables because they might be set for 35 35 * unrelated reasons. This is the same thing WebKitGTK does. */ 36 - if (SDL_getenv("SNAP") != NULL && SDL_getenv("SNAP_NAME") != NULL && SDL_getenv("SNAP_REVISION") != NULL) { 36 + if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SNAP") != NULL && 37 + SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SNAP_NAME") != NULL && 38 + SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SNAP_REVISION") != NULL) { 37 39 return SDL_SANDBOX_SNAP; 38 40 } 39 41
+6 -6
src/dialog/unix/SDL_zenitydialog.c
··· 229 229 230 230 /* Recent versions of Zenity have different exit codes, but picks up 231 231 different codes from the environment */ 232 - SDL_setenv("ZENITY_OK", "0", 1); 233 - SDL_setenv("ZENITY_CANCEL", "1", 1); 234 - SDL_setenv("ZENITY_ESC", "1", 1); 235 - SDL_setenv("ZENITY_EXTRA", "2", 1); 236 - SDL_setenv("ZENITY_ERROR", "2", 1); 237 - SDL_setenv("ZENITY_TIMEOUT", "2", 1); 232 + SDL_setenv_unsafe("ZENITY_OK", "0", 1); 233 + SDL_setenv_unsafe("ZENITY_CANCEL", "1", 1); 234 + SDL_setenv_unsafe("ZENITY_ESC", "1", 1); 235 + SDL_setenv_unsafe("ZENITY_EXTRA", "2", 1); 236 + SDL_setenv_unsafe("ZENITY_ERROR", "2", 1); 237 + SDL_setenv_unsafe("ZENITY_TIMEOUT", "2", 1); 238 238 239 239 execv(args[0], args); 240 240
+2 -2
src/dynapi/SDL_dynapi.c
··· 351 351 // Init our jump table first. 352 352 #if ENABLE_SDL_CALL_LOGGING 353 353 { 354 - const char *env = SDL_getenv_REAL("SDL_DYNAPI_LOG_CALLS"); 354 + const char *env = SDL_getenv_unsafe_REAL("SDL_DYNAPI_LOG_CALLS"); 355 355 const SDL_bool log_calls = (env && SDL_atoi_REAL(env)); 356 356 if (log_calls) { 357 357 #define SDL_DYNAPI_PROC(rc, fn, params, args, ret) jump_table.fn = fn##_LOGSDLCALLS; ··· 461 461 462 462 static void SDL_InitDynamicAPILocked(void) 463 463 { 464 - const char *libname = SDL_getenv_REAL(SDL_DYNAMIC_API_ENVVAR); 464 + const char *libname = SDL_getenv_unsafe_REAL(SDL_DYNAMIC_API_ENVVAR); 465 465 SDL_DYNAPI_ENTRYFN entry = NULL; // funcs from here by default. 466 466 SDL_bool use_internal = SDL_TRUE; 467 467
+11 -3
src/dynapi/SDL_dynapi.sym
··· 52 52 SDL_BroadcastCondition; 53 53 SDL_CaptureMouse; 54 54 SDL_ClaimWindowForGPUDevice; 55 + SDL_CleanupEnvironment; 55 56 SDL_CleanupTLS; 56 57 SDL_ClearAudioStream; 57 58 SDL_ClearClipboardData; ··· 84 85 SDL_CreateCondition; 85 86 SDL_CreateCursor; 86 87 SDL_CreateDirectory; 88 + SDL_CreateEnvironment; 87 89 SDL_CreateGPUBuffer; 88 90 SDL_CreateGPUComputePipeline; 89 91 SDL_CreateGPUDevice; ··· 125 127 SDL_DestroyAudioStream; 126 128 SDL_DestroyCondition; 127 129 SDL_DestroyCursor; 130 + SDL_DestroyEnvironment; 128 131 SDL_DestroyGPUDevice; 129 132 SDL_DestroyHapticEffect; 130 133 SDL_DestroyMutex; ··· 276 279 SDL_GetDisplayProperties; 277 280 SDL_GetDisplayUsableBounds; 278 281 SDL_GetDisplays; 282 + SDL_GetEnvironment; 283 + SDL_GetEnvironmentVariable; 284 + SDL_GetEnvironmentVariables; 279 285 SDL_GetError; 280 286 SDL_GetEventFilter; 281 287 SDL_GetFloatProperty; ··· 785 791 SDL_SetClipboardData; 786 792 SDL_SetClipboardText; 787 793 SDL_SetCursor; 794 + SDL_SetEnvironmentVariable; 788 795 SDL_SetError; 789 796 SDL_SetEventEnabled; 790 797 SDL_SetEventFilter; ··· 933 940 SDL_UnlockTexture; 934 941 SDL_UnmapGPUTransferBuffer; 935 942 SDL_UnregisterApp; 943 + SDL_UnsetEnvironmentVariable; 936 944 SDL_UpdateGamepads; 937 945 SDL_UpdateHapticEffect; 938 946 SDL_UpdateJoysticks; ··· 1020 1028 SDL_fmod; 1021 1029 SDL_fmodf; 1022 1030 SDL_free; 1023 - SDL_getenv; 1031 + SDL_getenv_unsafe; 1024 1032 SDL_hid_ble_scan; 1025 1033 SDL_hid_close; 1026 1034 SDL_hid_device_change_count; ··· 1095 1103 SDL_roundf; 1096 1104 SDL_scalbn; 1097 1105 SDL_scalbnf; 1098 - SDL_setenv; 1106 + SDL_setenv_unsafe; 1099 1107 SDL_sin; 1100 1108 SDL_sinf; 1101 1109 SDL_snprintf; ··· 1138 1146 SDL_uitoa; 1139 1147 SDL_ulltoa; 1140 1148 SDL_ultoa; 1141 - SDL_unsetenv; 1149 + SDL_unsetenv_unsafe; 1142 1150 SDL_utf8strlcpy; 1143 1151 SDL_utf8strlen; 1144 1152 SDL_utf8strnlen;
+11 -3
src/dynapi/SDL_dynapi_overrides.h
··· 77 77 #define SDL_BroadcastCondition SDL_BroadcastCondition_REAL 78 78 #define SDL_CaptureMouse SDL_CaptureMouse_REAL 79 79 #define SDL_ClaimWindowForGPUDevice SDL_ClaimWindowForGPUDevice_REAL 80 + #define SDL_CleanupEnvironment SDL_CleanupEnvironment_REAL 80 81 #define SDL_CleanupTLS SDL_CleanupTLS_REAL 81 82 #define SDL_ClearAudioStream SDL_ClearAudioStream_REAL 82 83 #define SDL_ClearClipboardData SDL_ClearClipboardData_REAL ··· 109 110 #define SDL_CreateCondition SDL_CreateCondition_REAL 110 111 #define SDL_CreateCursor SDL_CreateCursor_REAL 111 112 #define SDL_CreateDirectory SDL_CreateDirectory_REAL 113 + #define SDL_CreateEnvironment SDL_CreateEnvironment_REAL 112 114 #define SDL_CreateGPUBuffer SDL_CreateGPUBuffer_REAL 113 115 #define SDL_CreateGPUComputePipeline SDL_CreateGPUComputePipeline_REAL 114 116 #define SDL_CreateGPUDevice SDL_CreateGPUDevice_REAL ··· 150 152 #define SDL_DestroyAudioStream SDL_DestroyAudioStream_REAL 151 153 #define SDL_DestroyCondition SDL_DestroyCondition_REAL 152 154 #define SDL_DestroyCursor SDL_DestroyCursor_REAL 155 + #define SDL_DestroyEnvironment SDL_DestroyEnvironment_REAL 153 156 #define SDL_DestroyGPUDevice SDL_DestroyGPUDevice_REAL 154 157 #define SDL_DestroyHapticEffect SDL_DestroyHapticEffect_REAL 155 158 #define SDL_DestroyMutex SDL_DestroyMutex_REAL ··· 301 304 #define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL 302 305 #define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL 303 306 #define SDL_GetDisplays SDL_GetDisplays_REAL 307 + #define SDL_GetEnvironment SDL_GetEnvironment_REAL 308 + #define SDL_GetEnvironmentVariable SDL_GetEnvironmentVariable_REAL 309 + #define SDL_GetEnvironmentVariables SDL_GetEnvironmentVariables_REAL 304 310 #define SDL_GetError SDL_GetError_REAL 305 311 #define SDL_GetEventFilter SDL_GetEventFilter_REAL 306 312 #define SDL_GetFloatProperty SDL_GetFloatProperty_REAL ··· 810 816 #define SDL_SetClipboardData SDL_SetClipboardData_REAL 811 817 #define SDL_SetClipboardText SDL_SetClipboardText_REAL 812 818 #define SDL_SetCursor SDL_SetCursor_REAL 819 + #define SDL_SetEnvironmentVariable SDL_SetEnvironmentVariable_REAL 813 820 #define SDL_SetError SDL_SetError_REAL 814 821 #define SDL_SetEventEnabled SDL_SetEventEnabled_REAL 815 822 #define SDL_SetEventFilter SDL_SetEventFilter_REAL ··· 958 965 #define SDL_UnlockTexture SDL_UnlockTexture_REAL 959 966 #define SDL_UnmapGPUTransferBuffer SDL_UnmapGPUTransferBuffer_REAL 960 967 #define SDL_UnregisterApp SDL_UnregisterApp_REAL 968 + #define SDL_UnsetEnvironmentVariable SDL_UnsetEnvironmentVariable_REAL 961 969 #define SDL_UpdateGamepads SDL_UpdateGamepads_REAL 962 970 #define SDL_UpdateHapticEffect SDL_UpdateHapticEffect_REAL 963 971 #define SDL_UpdateJoysticks SDL_UpdateJoysticks_REAL ··· 1045 1053 #define SDL_fmod SDL_fmod_REAL 1046 1054 #define SDL_fmodf SDL_fmodf_REAL 1047 1055 #define SDL_free SDL_free_REAL 1048 - #define SDL_getenv SDL_getenv_REAL 1056 + #define SDL_getenv_unsafe SDL_getenv_unsafe_REAL 1049 1057 #define SDL_hid_ble_scan SDL_hid_ble_scan_REAL 1050 1058 #define SDL_hid_close SDL_hid_close_REAL 1051 1059 #define SDL_hid_device_change_count SDL_hid_device_change_count_REAL ··· 1120 1128 #define SDL_roundf SDL_roundf_REAL 1121 1129 #define SDL_scalbn SDL_scalbn_REAL 1122 1130 #define SDL_scalbnf SDL_scalbnf_REAL 1123 - #define SDL_setenv SDL_setenv_REAL 1131 + #define SDL_setenv_unsafe SDL_setenv_unsafe_REAL 1124 1132 #define SDL_sin SDL_sin_REAL 1125 1133 #define SDL_sinf SDL_sinf_REAL 1126 1134 #define SDL_snprintf SDL_snprintf_REAL ··· 1163 1171 #define SDL_uitoa SDL_uitoa_REAL 1164 1172 #define SDL_ulltoa SDL_ulltoa_REAL 1165 1173 #define SDL_ultoa SDL_ultoa_REAL 1166 - #define SDL_unsetenv SDL_unsetenv_REAL 1174 + #define SDL_unsetenv_unsafe SDL_unsetenv_unsafe_REAL 1167 1175 #define SDL_utf8strlcpy SDL_utf8strlcpy_REAL 1168 1176 #define SDL_utf8strlen SDL_utf8strlen_REAL 1169 1177 #define SDL_utf8strnlen SDL_utf8strnlen_REAL
+11 -3
src/dynapi/SDL_dynapi_procs.h
··· 97 97 SDL_DYNAPI_PROC(void,SDL_BroadcastCondition,(SDL_Condition *a),(a),) 98 98 SDL_DYNAPI_PROC(SDL_bool,SDL_CaptureMouse,(SDL_bool a),(a),return) 99 99 SDL_DYNAPI_PROC(SDL_bool,SDL_ClaimWindowForGPUDevice,(SDL_GPUDevice *a, SDL_Window *b),(a,b),return) 100 + SDL_DYNAPI_PROC(void,SDL_CleanupEnvironment,(void),(),) 100 101 SDL_DYNAPI_PROC(void,SDL_CleanupTLS,(void),(),) 101 102 SDL_DYNAPI_PROC(SDL_bool,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return) 102 103 SDL_DYNAPI_PROC(SDL_bool,SDL_ClearClipboardData,(void),(),return) ··· 129 130 SDL_DYNAPI_PROC(SDL_Condition*,SDL_CreateCondition,(void),(),return) 130 131 SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateCursor,(const Uint8 *a, const Uint8 *b, int c, int d, int e, int f),(a,b,c,d,e,f),return) 131 132 SDL_DYNAPI_PROC(SDL_bool,SDL_CreateDirectory,(const char *a),(a),return) 133 + SDL_DYNAPI_PROC(SDL_Environment*,SDL_CreateEnvironment,(SDL_bool a),(a),return) 132 134 SDL_DYNAPI_PROC(SDL_GPUBuffer*,SDL_CreateGPUBuffer,(SDL_GPUDevice *a, const SDL_GPUBufferCreateInfo* b),(a,b),return) 133 135 SDL_DYNAPI_PROC(SDL_GPUComputePipeline*,SDL_CreateGPUComputePipeline,(SDL_GPUDevice *a, const SDL_GPUComputePipelineCreateInfo *b),(a,b),return) 134 136 SDL_DYNAPI_PROC(SDL_GPUDevice*,SDL_CreateGPUDevice,(SDL_GPUShaderFormat a, SDL_bool b, const char *c),(a,b,c),return) ··· 170 172 SDL_DYNAPI_PROC(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),) 171 173 SDL_DYNAPI_PROC(void,SDL_DestroyCondition,(SDL_Condition *a),(a),) 172 174 SDL_DYNAPI_PROC(void,SDL_DestroyCursor,(SDL_Cursor *a),(a),) 175 + SDL_DYNAPI_PROC(void,SDL_DestroyEnvironment,(SDL_Environment *a),(a),) 173 176 SDL_DYNAPI_PROC(void,SDL_DestroyGPUDevice,(SDL_GPUDevice *a),(a),) 174 177 SDL_DYNAPI_PROC(void,SDL_DestroyHapticEffect,(SDL_Haptic *a, int b),(a,b),) 175 178 SDL_DYNAPI_PROC(void,SDL_DestroyMutex,(SDL_Mutex *a),(a),) ··· 321 324 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return) 322 325 SDL_DYNAPI_PROC(SDL_bool,SDL_GetDisplayUsableBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return) 323 326 SDL_DYNAPI_PROC(SDL_DisplayID*,SDL_GetDisplays,(int *a),(a),return) 327 + SDL_DYNAPI_PROC(SDL_Environment*,SDL_GetEnvironment,(void),(),return) 328 + SDL_DYNAPI_PROC(const char*,SDL_GetEnvironmentVariable,(SDL_Environment *a, const char *b),(a,b),return) 329 + SDL_DYNAPI_PROC(char**,SDL_GetEnvironmentVariables,(SDL_Environment *a),(a),return) 324 330 SDL_DYNAPI_PROC(const char*,SDL_GetError,(void),(),return) 325 331 SDL_DYNAPI_PROC(SDL_bool,SDL_GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),return) 326 332 SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) ··· 821 827 SDL_DYNAPI_PROC(SDL_bool,SDL_SetClipboardData,(SDL_ClipboardDataCallback a, SDL_ClipboardCleanupCallback b, void *c, const char **d, size_t e),(a,b,c,d,e),return) 822 828 SDL_DYNAPI_PROC(SDL_bool,SDL_SetClipboardText,(const char *a),(a),return) 823 829 SDL_DYNAPI_PROC(SDL_bool,SDL_SetCursor,(SDL_Cursor *a),(a),return) 830 + SDL_DYNAPI_PROC(SDL_bool,SDL_SetEnvironmentVariable,(SDL_Environment *a, const char *b, const char *c, SDL_bool d),(a,b,c,d),return) 824 831 SDL_DYNAPI_PROC(void,SDL_SetEventEnabled,(Uint32 a, SDL_bool b),(a,b),) 825 832 SDL_DYNAPI_PROC(void,SDL_SetEventFilter,(SDL_EventFilter a, void *b),(a,b),) 826 833 SDL_DYNAPI_PROC(SDL_bool,SDL_SetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) ··· 968 975 SDL_DYNAPI_PROC(void,SDL_UnlockTexture,(SDL_Texture *a),(a),) 969 976 SDL_DYNAPI_PROC(void,SDL_UnmapGPUTransferBuffer,(SDL_GPUDevice *a, SDL_GPUTransferBuffer *b),(a,b),) 970 977 SDL_DYNAPI_PROC(void,SDL_UnregisterApp,(void),(),) 978 + SDL_DYNAPI_PROC(SDL_bool,SDL_UnsetEnvironmentVariable,(SDL_Environment *a, const char *b),(a,b),return) 971 979 SDL_DYNAPI_PROC(void,SDL_UpdateGamepads,(void),(),) 972 980 SDL_DYNAPI_PROC(SDL_bool,SDL_UpdateHapticEffect,(SDL_Haptic *a, int b, const SDL_HapticEffect *c),(a,b,c),return) 973 981 SDL_DYNAPI_PROC(void,SDL_UpdateJoysticks,(void),(),) ··· 1054 1062 SDL_DYNAPI_PROC(double,SDL_fmod,(double a, double b),(a,b),return) 1055 1063 SDL_DYNAPI_PROC(float,SDL_fmodf,(float a, float b),(a,b),return) 1056 1064 SDL_DYNAPI_PROC(void,SDL_free,(void *a),(a),) 1057 - SDL_DYNAPI_PROC(const char*,SDL_getenv,(const char *a),(a),return) 1065 + SDL_DYNAPI_PROC(const char*,SDL_getenv_unsafe,(const char *a),(a),return) 1058 1066 SDL_DYNAPI_PROC(void,SDL_hid_ble_scan,(SDL_bool a),(a),) 1059 1067 SDL_DYNAPI_PROC(int,SDL_hid_close,(SDL_hid_device *a),(a),return) 1060 1068 SDL_DYNAPI_PROC(Uint32,SDL_hid_device_change_count,(void),(),return) ··· 1129 1137 SDL_DYNAPI_PROC(float,SDL_roundf,(float a),(a),return) 1130 1138 SDL_DYNAPI_PROC(double,SDL_scalbn,(double a, int b),(a,b),return) 1131 1139 SDL_DYNAPI_PROC(float,SDL_scalbnf,(float a, int b),(a,b),return) 1132 - SDL_DYNAPI_PROC(int,SDL_setenv,(const char *a, const char *b, int c),(a,b,c),return) 1140 + SDL_DYNAPI_PROC(int,SDL_setenv_unsafe,(const char *a, const char *b, int c),(a,b,c),return) 1133 1141 SDL_DYNAPI_PROC(double,SDL_sin,(double a),(a),return) 1134 1142 SDL_DYNAPI_PROC(float,SDL_sinf,(float a),(a),return) 1135 1143 SDL_DYNAPI_PROC(double,SDL_sqrt,(double a),(a),return) ··· 1169 1177 SDL_DYNAPI_PROC(char*,SDL_uitoa,(unsigned int a, char *b, int c),(a,b,c),return) 1170 1178 SDL_DYNAPI_PROC(char*,SDL_ulltoa,(unsigned long long a, char *b, int c),(a,b,c),return) 1171 1179 SDL_DYNAPI_PROC(char*,SDL_ultoa,(unsigned long a, char *b, int c),(a,b,c),return) 1172 - SDL_DYNAPI_PROC(int,SDL_unsetenv,(const char *a),(a),return) 1180 + SDL_DYNAPI_PROC(int,SDL_unsetenv_unsafe,(const char *a),(a),return) 1173 1181 SDL_DYNAPI_PROC(size_t,SDL_utf8strlcpy,(SDL_OUT_Z_CAP(c) char *a, const char *b, size_t c),(a,b,c),return) 1174 1182 SDL_DYNAPI_PROC(size_t,SDL_utf8strlen,(const char *a),(a),return) 1175 1183 SDL_DYNAPI_PROC(size_t,SDL_utf8strnlen,(const char *a, size_t b),(a,b),return)
+1 -1
src/filesystem/cocoa/SDL_sysfilesystem.m
··· 144 144 145 145 switch (folder) { 146 146 case SDL_FOLDER_HOME: 147 - base = SDL_getenv("HOME"); 147 + base = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME"); 148 148 149 149 if (!base) { 150 150 SDL_SetError("No $HOME environment variable available");
+1 -1
src/filesystem/emscripten/SDL_sysfilesystem.c
··· 93 93 return NULL; 94 94 } 95 95 96 - home = SDL_getenv("HOME"); 96 + home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME"); 97 97 if (!home) { 98 98 SDL_SetError("No $HOME environment variable available"); 99 99 return NULL;
+2 -2
src/filesystem/haiku/SDL_sysfilesystem.cc
··· 68 68 char *SDL_SYS_GetPrefPath(const char *org, const char *app) 69 69 { 70 70 // !!! FIXME: is there a better way to do this? 71 - const char *home = SDL_getenv("HOME"); 71 + const char *home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME"); 72 72 const char *append = "/config/settings/"; 73 73 size_t len = SDL_strlen(home); 74 74 ··· 102 102 const char *home = NULL; 103 103 char *result; 104 104 105 - home = SDL_getenv("HOME"); 105 + home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME"); 106 106 if (!home) { 107 107 SDL_SetError("No $HOME environment variable available"); 108 108 return NULL;
+8 -8
src/filesystem/unix/SDL_sysfilesystem.c
··· 74 74 #ifdef SDL_PLATFORM_OPENBSD 75 75 static char *search_path_for_binary(const char *bin) 76 76 { 77 - const char *envr_real = SDL_getenv("PATH"); 77 + const char *envr_real = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "PATH"); 78 78 char *envr; 79 79 size_t alloc_size; 80 80 char *exe = NULL; ··· 163 163 exe = search_path_for_binary(cmdline[0]); 164 164 } else { 165 165 if (exe && *exe == '.') { 166 - const char *pwd = SDL_getenv("PWD"); 166 + const char *pwd = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "PWD"); 167 167 if (pwd && *pwd) { 168 168 SDL_asprintf(&pwddst, "%s/%s", pwd, exe); 169 169 } ··· 265 265 * 266 266 * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html 267 267 */ 268 - const char *envr = SDL_getenv("XDG_DATA_HOME"); 268 + const char *envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_DATA_HOME"); 269 269 const char *append; 270 270 char *result = NULL; 271 271 char *ptr = NULL; ··· 281 281 282 282 if (!envr) { 283 283 // You end up with "$HOME/.local/share/Game Name 2" 284 - envr = SDL_getenv("HOME"); 284 + envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME"); 285 285 if (!envr) { 286 286 // we could take heroic measures with /etc/passwd, but oh well. 287 287 SDL_SetError("neither XDG_DATA_HOME nor HOME environment is set"); ··· 368 368 int relative; 369 369 size_t l; 370 370 371 - home_dir = SDL_getenv ("HOME"); 371 + home_dir = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME"); 372 372 373 373 if (!home_dir) 374 374 goto error; 375 375 376 - config_home = SDL_getenv ("XDG_CONFIG_HOME"); 376 + config_home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_CONFIG_HOME"); 377 377 if (!config_home || config_home[0] == 0) 378 378 { 379 379 l = SDL_strlen (home_dir) + SDL_strlen ("/.config/user-dirs.dirs") + 1; ··· 495 495 if (dir) 496 496 return dir; 497 497 498 - home_dir = SDL_getenv("HOME"); 498 + home_dir = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME"); 499 499 500 500 if (!home_dir) 501 501 return NULL; ··· 533 533 */ 534 534 switch(folder) { 535 535 case SDL_FOLDER_HOME: 536 - param = SDL_getenv("HOME"); 536 + param = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME"); 537 537 538 538 if (!param) { 539 539 SDL_SetError("No $HOME environment variable available");
+1 -1
src/gpu/vulkan/SDL_gpu_vulkan.c
··· 11591 11591 static void VULKAN_INTERNAL_LoadEntryPoints(void) 11592 11592 { 11593 11593 // Required for MoltenVK support 11594 - SDL_setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1); 11594 + SDL_setenv_unsafe("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1); 11595 11595 11596 11596 // Load Vulkan entry points 11597 11597 if (!SDL_Vulkan_LoadLibrary(NULL)) {
+1 -1
src/haptic/SDL_haptic.c
··· 537 537 } 538 538 539 539 // The user can use an environment variable to override the max gain. 540 - env = SDL_getenv("SDL_HAPTIC_GAIN_MAX"); 540 + env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_HAPTIC_GAIN_MAX"); 541 541 if (env) { 542 542 max_gain = SDL_atoi(env); 543 543
+2 -2
src/locale/unix/SDL_syslocale.c
··· 78 78 *tmp = '\0'; 79 79 80 80 // LANG is the primary locale (maybe) 81 - envr = SDL_getenv("LANG"); 81 + envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANG"); 82 82 if (envr) { 83 83 SDL_strlcpy(tmp, envr, buflen); 84 84 } 85 85 86 86 // fallback languages 87 - envr = SDL_getenv("LANGUAGE"); 87 + envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANGUAGE"); 88 88 if (envr) { 89 89 if (*tmp) { 90 90 SDL_strlcat(tmp, ":", buflen);
+1 -1
src/main/emscripten/SDL_sysmain_runapp.c
··· 48 48 _free(cvalue); 49 49 } 50 50 } 51 - }, SDL_setenv); 51 + }, SDL_setenv_unsafe); 52 52 53 53 return mainFunction(argc, argv); 54 54 }
+2 -2
src/misc/unix/SDL_sysurl.c
··· 41 41 pid_t pid2; 42 42 const char *args[] = { "xdg-open", url, NULL }; 43 43 // Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam 44 - SDL_unsetenv("LD_PRELOAD"); 44 + SDL_unsetenv_unsafe("LD_PRELOAD"); 45 45 if (posix_spawnp(&pid2, args[0], NULL, NULL, (char **)args, environ) == 0) { 46 46 // Child process doesn't wait for possibly-blocking grandchild. 47 47 _exit(EXIT_SUCCESS); ··· 51 51 #else 52 52 pid_t pid2; 53 53 // Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam 54 - SDL_unsetenv("LD_PRELOAD"); 54 + SDL_unsetenv_unsafe("LD_PRELOAD"); 55 55 // Notice this is vfork and not fork! 56 56 pid2 = vfork(); 57 57 if (pid2 == 0) { // Grandchild process will try to launch the url
+9 -10
src/process/posix/SDL_posixprocess.c
··· 35 35 #include "../SDL_sysprocess.h" 36 36 #include "../../file/SDL_iostream_c.h" 37 37 38 - #if defined(SDL_PLATFORM_MACOS) 39 - #include <crt_externs.h> 40 - #define environ (*_NSGetEnviron()) 41 - #elif defined(SDL_PLATFORM_FREEBSD) 42 - #include <dlfcn.h> 43 - #define environ ((char **)dlsym(RTLD_DEFAULT, "environ")) 44 - #else 45 - extern char **environ; 46 - #endif 47 38 48 39 #define READ_END 0 49 40 #define WRITE_END 1 ··· 114 105 bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID props) 115 106 { 116 107 char * const *args = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, NULL); 117 - char * const *env = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, environ); 108 + char * const *env = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, NULL); 118 109 SDL_ProcessIO stdin_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL); 119 110 SDL_ProcessIO stdout_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_INHERITED); 120 111 SDL_ProcessIO stderr_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_INHERITED); ··· 124 115 int stdout_pipe[2] = { -1, -1 }; 125 116 int stderr_pipe[2] = { -1, -1 }; 126 117 int fd = -1; 118 + char **env_copy = NULL; 127 119 128 120 // Keep the malloc() before exec() so that an OOM won't run a process at all 129 121 SDL_ProcessData *data = SDL_calloc(1, sizeof(*data)); ··· 278 270 } 279 271 } 280 272 273 + if (!env) { 274 + env_copy = SDL_GetEnvironmentVariables(SDL_GetEnvironment()); 275 + env = env_copy; 276 + } 277 + 281 278 // Spawn the new process 282 279 if (posix_spawnp(&data->pid, args[0], &fa, &attr, args, env) != 0) { 283 280 SDL_SetError("posix_spawn failed: %s", strerror(errno)); ··· 308 305 309 306 posix_spawn_file_actions_destroy(&fa); 310 307 posix_spawnattr_destroy(&attr); 308 + SDL_free(env_copy); 311 309 312 310 return true; 313 311 ··· 338 336 if (stderr_pipe[WRITE_END] >= 0) { 339 337 close(stderr_pipe[WRITE_END]); 340 338 } 339 + SDL_free(env_copy); 341 340 return false; 342 341 } 343 342
+6
src/process/windows/SDL_windowsprocess.c
··· 186 186 HANDLE stdin_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 187 187 HANDLE stdout_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 188 188 HANDLE stderr_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 189 + char **env_copy = NULL; 189 190 bool result = false; 190 191 191 192 // Keep the malloc() before exec() so that an OOM won't run a process at all ··· 199 200 goto done; 200 201 } 201 202 203 + if (!env) { 204 + env_copy = SDL_GetEnvironmentVariables(SDL_GetEnvironment()); 205 + env = (const char * const *)env_copy; 206 + } 202 207 if (!join_env(env, &createprocess_env)) { 203 208 goto done; 204 209 } ··· 381 386 } 382 387 SDL_free(createprocess_cmdline); 383 388 SDL_free(createprocess_env); 389 + SDL_free(env_copy); 384 390 385 391 if (!result) { 386 392 if (stdin_pipe[WRITE_END] != INVALID_HANDLE_VALUE) {
+266 -12
src/stdlib/SDL_getenv.c
··· 21 21 #include "SDL_internal.h" 22 22 23 23 #include "SDL_getenv_c.h" 24 + #include "../SDL_hashtable.h" 24 25 25 26 #if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) 26 27 #include "../core/windows/SDL_windows.h" ··· 40 41 #define HAVE_LOCAL_ENVIRONMENT 41 42 #endif 42 43 44 + #if !defined(SDL_PLATFORM_WINDOWS) 45 + #if defined(SDL_PLATFORM_MACOS) 46 + #include <crt_externs.h> 47 + #define environ (*_NSGetEnviron()) 48 + #elif defined(SDL_PLATFORM_FREEBSD) 49 + #include <dlfcn.h> 50 + #define environ ((char **)dlsym(RTLD_DEFAULT, "environ")) 51 + #else 52 + extern char **environ; 53 + #endif 54 + #endif // !SDL_PLATFORM_WINDOWS 55 + 43 56 // Put a variable into the environment 44 57 // Note: Name may not contain a '=' character. (Reference: http://www.unix.com/man-page/Linux/3/setenv/) 45 58 #ifdef HAVE_LIBC_ENVIRONMENT 46 59 #if defined(HAVE_SETENV) 47 - int SDL_setenv(const char *name, const char *value, int overwrite) 60 + int SDL_setenv_unsafe(const char *name, const char *value, int overwrite) 48 61 { 49 62 // Input validation 50 63 if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) { ··· 55 68 } 56 69 // We have a real environment table, but no real setenv? Fake it w/ putenv. 57 70 #else 58 - int SDL_setenv(const char *name, const char *value, int overwrite) 71 + int SDL_setenv_unsafe(const char *name, const char *value, int overwrite) 59 72 { 60 73 char *new_variable; 61 74 ··· 79 92 } 80 93 #endif 81 94 #elif defined(HAVE_WIN32_ENVIRONMENT) 82 - int SDL_setenv(const char *name, const char *value, int overwrite) 95 + int SDL_setenv_unsafe(const char *name, const char *value, int overwrite) 83 96 { 84 97 // Input validation 85 98 if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) { ··· 101 114 // We'll leak this, as environment variables are intended to persist past SDL_Quit() 102 115 static char **SDL_env; 103 116 104 - int SDL_setenv(const char *name, const char *value, int overwrite) 117 + int SDL_setenv_unsafe(const char *name, const char *value, int overwrite) 105 118 { 106 119 int added; 107 120 size_t len, i; ··· 114 127 } 115 128 116 129 // See if it already exists 117 - if (!overwrite && SDL_getenv(name)) { 130 + if (!overwrite && SDL_getenv_unsafe(name)) { 118 131 return 0; 119 132 } 120 133 ··· 164 177 165 178 #ifdef HAVE_LIBC_ENVIRONMENT 166 179 #if defined(HAVE_UNSETENV) 167 - int SDL_unsetenv(const char *name) 180 + int SDL_unsetenv_unsafe(const char *name) 168 181 { 169 182 // Input validation 170 183 if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) { ··· 175 188 } 176 189 // We have a real environment table, but no unsetenv? Fake it w/ putenv. 177 190 #else 178 - int SDL_unsetenv(const char *name) 191 + int SDL_unsetenv_unsafe(const char *name) 179 192 { 180 193 // Input validation 181 194 if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) { ··· 187 200 } 188 201 #endif 189 202 #elif defined(HAVE_WIN32_ENVIRONMENT) 190 - int SDL_unsetenv(const char *name) 203 + int SDL_unsetenv_unsafe(const char *name) 191 204 { 192 205 // Input validation 193 206 if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) { ··· 200 213 return 0; 201 214 } 202 215 #else 203 - int SDL_unsetenv(const char *name) 216 + int SDL_unsetenv_unsafe(const char *name) 204 217 { 205 218 size_t len, i; 206 219 ··· 226 239 227 240 // Retrieve a variable named "name" from the environment 228 241 #ifdef HAVE_LIBC_ENVIRONMENT 229 - const char *SDL_getenv(const char *name) 242 + const char *SDL_getenv_unsafe(const char *name) 230 243 { 231 244 #ifdef SDL_PLATFORM_ANDROID 232 245 // Make sure variables from the application manifest are available ··· 241 254 return getenv(name); 242 255 } 243 256 #elif defined(HAVE_WIN32_ENVIRONMENT) 244 - const char *SDL_getenv(const char *name) 257 + const char *SDL_getenv_unsafe(const char *name) 245 258 { 246 259 DWORD length, maxlen = 0; 247 260 char *string = NULL; ··· 280 293 return result; 281 294 } 282 295 #else 283 - const char *SDL_getenv(const char *name) 296 + const char *SDL_getenv_unsafe(const char *name) 284 297 { 285 298 size_t len, i; 286 299 char *value; ··· 304 317 return value; 305 318 } 306 319 #endif // HAVE_LIBC_ENVIRONMENT 320 + 321 + 322 + struct SDL_Environment 323 + { 324 + SDL_Mutex *lock; 325 + SDL_HashTable *strings; 326 + }; 327 + static SDL_Environment *SDL_environment; 328 + 329 + SDL_Environment *SDL_GetEnvironment(void) 330 + { 331 + if (!SDL_environment) { 332 + SDL_environment = SDL_CreateEnvironment(false); 333 + } 334 + return SDL_environment; 335 + } 336 + 337 + void SDL_CleanupEnvironment(void) 338 + { 339 + SDL_Environment *env = SDL_environment; 340 + 341 + if (env) { 342 + SDL_environment = NULL; 343 + SDL_DestroyEnvironment(env); 344 + } 345 + } 346 + 347 + SDL_Environment *SDL_CreateEnvironment(SDL_bool empty) 348 + { 349 + SDL_Environment *env = SDL_calloc(1, sizeof(*env)); 350 + if (!env) { 351 + return NULL; 352 + } 353 + 354 + env->strings = SDL_CreateHashTable(NULL, 16, SDL_HashString, SDL_KeyMatchString, SDL_NukeFreeKey, false); 355 + if (!env->strings) { 356 + SDL_free(env); 357 + return NULL; 358 + } 359 + 360 + // Don't fail if we can't create a mutex (e.g. on a single-thread environment) 361 + env->lock = SDL_CreateMutex(); 362 + 363 + if (!empty) { 364 + #ifdef SDL_PLATFORM_WINDOWS 365 + LPWCH strings = GetEnvironmentStringsW(); 366 + if (strings) { 367 + for (LPWCH string = strings; *string; string += SDL_wcslen(string) + 1) { 368 + char *variable = WIN_StringToUTF8W(string); 369 + if (!variable) { 370 + continue; 371 + } 372 + 373 + char *value = SDL_strchr(variable, '='); 374 + if (!value || value == variable) { 375 + SDL_free(variable); 376 + continue; 377 + } 378 + *value++ = '\0'; 379 + 380 + SDL_InsertIntoHashTable(env->strings, variable, value); 381 + } 382 + FreeEnvironmentStringsW(strings); 383 + } 384 + #else 385 + #ifdef SDL_PLATFORM_ANDROID 386 + // Make sure variables from the application manifest are available 387 + Android_JNI_GetManifestEnvironmentVariables(); 388 + #endif 389 + char **strings = environ; 390 + for (int i = 0; strings[i]; ++i) { 391 + char *variable = SDL_strdup(strings[i]); 392 + if (!variable) { 393 + continue; 394 + } 395 + 396 + char *value = SDL_strchr(variable, '='); 397 + if (!value || value == variable) { 398 + SDL_free(variable); 399 + continue; 400 + } 401 + *value++ = '\0'; 402 + 403 + SDL_InsertIntoHashTable(env->strings, variable, value); 404 + } 405 + #endif // SDL_PLATFORM_WINDOWS 406 + } 407 + 408 + return env; 409 + } 410 + 411 + const char *SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name) 412 + { 413 + const char *result = NULL; 414 + 415 + if (!env) { 416 + return NULL; 417 + } else if (!name || *name == '\0') { 418 + return NULL; 419 + } 420 + 421 + SDL_LockMutex(env->lock); 422 + { 423 + const char *value; 424 + 425 + if (SDL_FindInHashTable(env->strings, name, (const void **)&value)) { 426 + result = SDL_GetPersistentString(value); 427 + } 428 + } 429 + SDL_UnlockMutex(env->lock); 430 + 431 + return result; 432 + } 433 + 434 + char **SDL_GetEnvironmentVariables(SDL_Environment *env) 435 + { 436 + char **result = NULL; 437 + 438 + if (!env) { 439 + SDL_InvalidParamError("env"); 440 + return NULL; 441 + } 442 + 443 + SDL_LockMutex(env->lock); 444 + { 445 + size_t count, length = 0; 446 + void *iter; 447 + const char *key, *value; 448 + 449 + // First pass, get the size we need for all the strings 450 + count = 0; 451 + iter = NULL; 452 + while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) { 453 + length += SDL_strlen(key) + 1 + SDL_strlen(value) + 1; 454 + ++count; 455 + } 456 + 457 + // Allocate memory for the strings 458 + result = (char **)SDL_malloc((count + 1) * sizeof(*result) + length); 459 + char *string = (char *)(result + count + 1); 460 + 461 + // Second pass, copy the strings 462 + count = 0; 463 + iter = NULL; 464 + while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) { 465 + size_t len; 466 + 467 + result[count] = string; 468 + len = SDL_strlen(key); 469 + SDL_memcpy(string, key, len); 470 + string += len; 471 + *string++ = '='; 472 + len = SDL_strlen(value); 473 + SDL_memcpy(string, value, len); 474 + string += len; 475 + *string++ = '\0'; 476 + ++count; 477 + } 478 + result[count] = NULL; 479 + } 480 + SDL_UnlockMutex(env->lock); 481 + 482 + return result; 483 + } 484 + 485 + SDL_bool SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, SDL_bool overwrite) 486 + { 487 + bool result = false; 488 + 489 + if (!env) { 490 + return SDL_InvalidParamError("env"); 491 + } else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) { 492 + return SDL_InvalidParamError("name"); 493 + } else if (!value) { 494 + return SDL_InvalidParamError("value"); 495 + } 496 + 497 + SDL_LockMutex(env->lock); 498 + { 499 + const void *existing_value; 500 + bool insert = true; 501 + 502 + if (SDL_FindInHashTable(env->strings, name, &existing_value)) { 503 + if (!overwrite) { 504 + result = true; 505 + insert = false; 506 + } else { 507 + SDL_RemoveFromHashTable(env->strings, name); 508 + } 509 + } 510 + 511 + if (insert) { 512 + char *string = NULL; 513 + if (SDL_asprintf(&string, "%s=%s", name, value) > 0) { 514 + size_t len = SDL_strlen(name); 515 + string[len] = '\0'; 516 + name = string; 517 + value = string + len + 1; 518 + result = SDL_InsertIntoHashTable(env->strings, name, value); 519 + } 520 + } 521 + } 522 + SDL_UnlockMutex(env->lock); 523 + 524 + return result; 525 + } 526 + 527 + SDL_bool SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name) 528 + { 529 + bool result = false; 530 + 531 + if (!env) { 532 + return SDL_InvalidParamError("env"); 533 + } else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) { 534 + return SDL_InvalidParamError("name"); 535 + } 536 + 537 + SDL_LockMutex(env->lock); 538 + { 539 + const void *value; 540 + if (SDL_FindInHashTable(env->strings, name, &value)) { 541 + result = SDL_RemoveFromHashTable(env->strings, name); 542 + } else { 543 + result = true; 544 + } 545 + } 546 + SDL_UnlockMutex(env->lock); 547 + 548 + return result; 549 + } 550 + 551 + void SDL_DestroyEnvironment(SDL_Environment *env) 552 + { 553 + if (!env || env == SDL_environment) { 554 + return; 555 + } 556 + 557 + SDL_DestroyMutex(env->lock); 558 + SDL_DestroyHashTable(env->strings); 559 + SDL_free(env); 560 + }
+4 -4
src/stdlib/SDL_iconv.c
··· 163 163 const char *lang; 164 164 char *ptr; 165 165 166 - lang = SDL_getenv("LC_ALL"); 166 + lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_ALL"); 167 167 if (!lang) { 168 - lang = SDL_getenv("LC_CTYPE"); 168 + lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_CTYPE"); 169 169 } 170 170 if (!lang) { 171 - lang = SDL_getenv("LC_MESSAGES"); 171 + lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_MESSAGES"); 172 172 } 173 173 if (!lang) { 174 - lang = SDL_getenv("LANG"); 174 + lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANG"); 175 175 } 176 176 if (!lang || !*lang || SDL_strcmp(lang, "C") == 0) { 177 177 lang = "ASCII";
+1 -1
src/test/SDL_test_memory.c
··· 299 299 #ifdef SDLTEST_UNWIND_NO_PROC_NAME_BY_IP 300 300 do { 301 301 /* Don't use SDL_GetHint: SDL_malloc is off limits. */ 302 - const char *env_trackmem = SDL_getenv("SDL_TRACKMEM_SYMBOL_NAMES"); 302 + const char *env_trackmem = SDL_getenv_unsafe("SDL_TRACKMEM_SYMBOL_NAMES"); 303 303 if (env_trackmem) { 304 304 if (SDL_strcasecmp(env_trackmem, "1") == 0 || SDL_strcasecmp(env_trackmem, "yes") == 0 || SDL_strcasecmp(env_trackmem, "true") == 0) { 305 305 s_unwind_symbol_names = SDL_TRUE;
+2 -2
src/video/SDL_egl.c
··· 341 341 342 342 #if !defined(SDL_VIDEO_STATIC_ANGLE) && !defined(SDL_VIDEO_DRIVER_VITA) 343 343 /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */ 344 - path = SDL_getenv("SDL_VIDEO_GL_DRIVER"); 344 + path = SDL_getenv_unsafe("SDL_VIDEO_GL_DRIVER"); 345 345 if (path) { 346 346 opengl_dll_handle = SDL_LoadObject(path); 347 347 } ··· 401 401 if (egl_dll_handle) { 402 402 SDL_UnloadObject(egl_dll_handle); 403 403 } 404 - path = SDL_getenv("SDL_VIDEO_EGL_DRIVER"); 404 + path = SDL_getenv_unsafe("SDL_VIDEO_EGL_DRIVER"); 405 405 if (!path) { 406 406 path = DEFAULT_EGL; 407 407 }
+3 -3
src/video/wayland/SDL_waylandevents.c
··· 1292 1292 */ 1293 1293 1294 1294 // Look up the preferred locale, falling back to "C" as default 1295 - locale = SDL_getenv("LC_ALL"); 1295 + locale = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_ALL"); 1296 1296 if (!locale) { 1297 - locale = SDL_getenv("LC_CTYPE"); 1297 + locale = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_CTYPE"); 1298 1298 if (!locale) { 1299 - locale = SDL_getenv("LANG"); 1299 + locale = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANG"); 1300 1300 if (!locale) { 1301 1301 locale = "C"; 1302 1302 }
+2 -2
src/video/wayland/SDL_waylandmessagebox.c
··· 141 141 }; 142 142 143 143 // Are we trying to connect to or are currently in a Wayland session? 144 - if (!SDL_getenv("WAYLAND_DISPLAY")) { 145 - const char *session = SDL_getenv("XDG_SESSION_TYPE"); 144 + if (!SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "WAYLAND_DISPLAY")) { 145 + const char *session = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE"); 146 146 if (session && SDL_strcasecmp(session, "wayland") != 0) { 147 147 return SDL_SetError("Not on a wayland display"); 148 148 }
+2 -2
src/video/wayland/SDL_waylandmouse.c
··· 345 345 346 346 // Fallback envvar if the DBus properties don't exist 347 347 if (size <= 0) { 348 - const char *xcursor_size = SDL_getenv("XCURSOR_SIZE"); 348 + const char *xcursor_size = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XCURSOR_SIZE"); 349 349 if (xcursor_size) { 350 350 size = SDL_atoi(xcursor_size); 351 351 } ··· 381 381 382 382 // Fallback envvar if the DBus properties don't exist 383 383 if (!xcursor_theme) { 384 - xcursor_theme = SDL_getenv("XCURSOR_THEME"); 384 + xcursor_theme = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XCURSOR_THEME"); 385 385 } 386 386 387 387 theme = WAYLAND_wl_cursor_theme_load(xcursor_theme, size, vdata->shm);
+1 -1
src/video/wayland/SDL_waylandshmbuffer.c
··· 80 80 const char *xdg_path; 81 81 char tmp_path[PATH_MAX]; 82 82 83 - xdg_path = SDL_getenv("XDG_RUNTIME_DIR"); 83 + xdg_path = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_RUNTIME_DIR"); 84 84 if (!xdg_path) { 85 85 return -1; 86 86 }
+2 -2
src/video/wayland/SDL_waylandvideo.c
··· 429 429 bool display_is_external = !!display; 430 430 431 431 // Are we trying to connect to or are currently in a Wayland session? 432 - if (!SDL_getenv("WAYLAND_DISPLAY")) { 433 - const char *session = SDL_getenv("XDG_SESSION_TYPE"); 432 + if (!SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "WAYLAND_DISPLAY")) { 433 + const char *session = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE"); 434 434 if (session && SDL_strcasecmp(session, "wayland") != 0) { 435 435 return NULL; 436 436 }
+2 -2
src/video/wayland/SDL_waylandwindow.c
··· 1914 1914 /* Note that we don't check for empty strings, as that is still 1915 1915 * considered a valid activation token! 1916 1916 */ 1917 - const char *activation_token = SDL_getenv("XDG_ACTIVATION_TOKEN"); 1917 + const char *activation_token = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_ACTIVATION_TOKEN"); 1918 1918 if (activation_token) { 1919 1919 xdg_activation_v1_activate(c->activation_manager, 1920 1920 activation_token, 1921 1921 data->surface); 1922 1922 1923 1923 // Clear this variable, per the protocol's request 1924 - SDL_unsetenv("XDG_ACTIVATION_TOKEN"); 1924 + SDL_unsetenv_unsafe("XDG_ACTIVATION_TOKEN"); 1925 1925 } 1926 1926 } 1927 1927
+1 -1
src/video/x11/SDL_x11keyboard.c
··· 169 169 char *prev_locale = setlocale(LC_ALL, NULL); 170 170 char *prev_xmods = X11_XSetLocaleModifiers(NULL); 171 171 const char *new_xmods = ""; 172 - const char *env_xmods = SDL_getenv("XMODIFIERS"); 172 + const char *env_xmods = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XMODIFIERS"); 173 173 bool has_dbus_ime_support = false; 174 174 175 175 if (prev_locale) {
+1 -1
src/video/x11/SDL_x11modes.c
··· 248 248 249 249 // If that failed, try the GDK_SCALE envvar... 250 250 if (scale_factor <= 0.0) { 251 - const char *scale_str = SDL_getenv("GDK_SCALE"); 251 + const char *scale_str = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "GDK_SCALE"); 252 252 if (scale_str) { 253 253 scale_factor = SDL_atoi(scale_str); 254 254 }
+10 -26
test/childprocess.c
··· 5 5 #include <stdio.h> 6 6 #include <errno.h> 7 7 8 - #if defined(SDL_PLATFORM_WINDOWS) 9 - #include <windows.h> 10 - #elif defined(SDL_PLATFORM_MACOS) 11 - #include <crt_externs.h> 12 - #define environ (*_NSGetEnviron()) 13 - #else 14 - extern char **environ; 15 - #endif 16 8 17 9 int main(int argc, char *argv[]) { 18 10 SDLTest_CommonState *state; ··· 95 87 } 96 88 97 89 if (print_environment || expect_environment) { 98 - 99 - #if defined(SDL_PLATFORM_WINDOWS) 100 - char *original_env = GetEnvironmentStrings(); 101 - const char *env = original_env; 102 - for (; env[0]; env += SDL_strlen(env) + 1) { 103 - #else 104 - char **envp = environ; 105 - for (; *envp; envp++) { 106 - const char *env = *envp; 107 - #endif 108 - if (print_environment) { 109 - fprintf(stdout, "%s\n", env); 110 - } 111 - if (expect_environment) { 112 - expect_environment_match |= SDL_strcmp(env, expect_environment) == 0; 90 + char **env = SDL_GetEnvironmentVariables(SDL_GetEnvironment()); 91 + if (env) { 92 + for (i = 0; env[i]; ++i) { 93 + if (print_environment) { 94 + fprintf(stdout, "%s\n", env[i]); 95 + } 96 + if (expect_environment) { 97 + expect_environment_match |= SDL_strcmp(env[i], expect_environment) == 0; 98 + } 113 99 } 100 + SDL_free(env); 114 101 } 115 - #ifdef SDL_PLATFORM_WINDOWS 116 - FreeEnvironmentStringsA(original_env); 117 - #endif 118 102 } 119 103 120 104 if (stdin_to_stdout || stdin_to_stderr) {
+1 -1
test/testatomic.c
··· 740 740 741 741 RunBasicTest(); 742 742 743 - if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { 743 + if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) { 744 744 SDL_Log("Not running slower tests"); 745 745 return 0; 746 746 }
+1 -1
test/testautomation_hints.c
··· 130 130 SDL_free(value); 131 131 132 132 /* Set default value in environment */ 133 - SDL_setenv(testHint, "original", 1); 133 + SDL_SetEnvironmentVariable(SDL_GetEnvironment(), testHint, "original", 1); 134 134 135 135 SDLTest_AssertPass("Call to SDL_GetHint() after saving and restoring hint"); 136 136 originalValue = SDL_GetHint(testHint);
+58 -57
test/testautomation_stdlib.c
··· 542 542 #endif 543 543 544 544 /** 545 - * Call to SDL_getenv and SDL_setenv 545 + * Call to SDL_GetEnvironmentVariable() and SDL_SetEnvironmentVariable() 546 546 */ 547 547 static int SDLCALL stdlib_getsetenv(void *arg) 548 548 { 549 + SDL_Environment *env = SDL_GetEnvironment(); 549 550 const int nameLen = 16; 550 551 char name[17]; 551 552 int counter; ··· 556 557 int overwrite; 557 558 const char *text; 558 559 559 - /* Create a random name. This tests SDL_getenv, since we need to */ 560 + /* Create a random name. This tests SDL_GetEnvironmentVariable, since we need to */ 560 561 /* make sure the variable is not set yet (it shouldn't). */ 561 562 do { 562 563 for (counter = 0; counter < nameLen; counter++) { ··· 564 565 } 565 566 name[nameLen] = '\0'; 566 567 567 - text = SDL_getenv(name); 568 - SDLTest_AssertPass("Call to SDL_getenv('%s')", name); 568 + text = SDL_GetEnvironmentVariable(env, name); 569 + SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name); 569 570 if (text) { 570 571 SDLTest_Log("Expected: NULL, Got: '%s' (%i)", text, (int)SDL_strlen(text)); 571 572 } ··· 578 579 /* Set value 1 without overwrite */ 579 580 overwrite = 0; 580 581 expected = value1; 581 - result = SDL_setenv(name, value1, overwrite); 582 - SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite); 583 - SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); 582 + result = SDL_SetEnvironmentVariable(env, name, value1, overwrite); 583 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value1, overwrite); 584 + SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result); 584 585 585 586 /* Check value */ 586 - text = SDL_getenv(name); 587 - SDLTest_AssertPass("Call to SDL_getenv('%s')", name); 587 + text = SDL_GetEnvironmentVariable(env, name); 588 + SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name); 588 589 SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL"); 589 590 if (text != NULL) { 590 591 SDLTest_AssertCheck( ··· 597 598 /* Set value 2 with overwrite */ 598 599 overwrite = 1; 599 600 expected = value2; 600 - result = SDL_setenv(name, value2, overwrite); 601 - SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value2, overwrite); 602 - SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); 601 + result = SDL_SetEnvironmentVariable(env, name, value2, overwrite); 602 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value2, overwrite); 603 + SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result); 603 604 604 605 /* Check value */ 605 - text = SDL_getenv(name); 606 - SDLTest_AssertPass("Call to SDL_getenv('%s')", name); 606 + text = SDL_GetEnvironmentVariable(env, name); 607 + SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name); 607 608 SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL"); 608 609 if (text != NULL) { 609 610 SDLTest_AssertCheck( ··· 616 617 /* Set value 1 without overwrite */ 617 618 overwrite = 0; 618 619 expected = value2; 619 - result = SDL_setenv(name, value1, overwrite); 620 - SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite); 621 - SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); 620 + result = SDL_SetEnvironmentVariable(env, name, value1, overwrite); 621 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value1, overwrite); 622 + SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result); 622 623 623 624 /* Check value */ 624 - text = SDL_getenv(name); 625 - SDLTest_AssertPass("Call to SDL_getenv('%s')", name); 625 + text = SDL_GetEnvironmentVariable(env, name); 626 + SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name); 626 627 SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL"); 627 628 if (text != NULL) { 628 629 SDLTest_AssertCheck( ··· 635 636 /* Set value 1 with overwrite */ 636 637 overwrite = 1; 637 638 expected = value1; 638 - result = SDL_setenv(name, value1, overwrite); 639 - SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite); 640 - SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); 639 + result = SDL_SetEnvironmentVariable(env, name, value1, overwrite); 640 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value1, overwrite); 641 + SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result); 641 642 642 643 /* Check value */ 643 - text = SDL_getenv(name); 644 - SDLTest_AssertPass("Call to SDL_getenv('%s')", name); 644 + text = SDL_GetEnvironmentVariable(env, name); 645 + SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name); 645 646 SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL"); 646 647 if (text != NULL) { 647 648 SDLTest_AssertCheck( ··· 652 653 } 653 654 654 655 /* Verify setenv() with empty string vs unsetenv() */ 655 - result = SDL_setenv("FOO", "1", 1); 656 - SDLTest_AssertPass("Call to SDL_setenv('FOO','1', 1)"); 657 - SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); 656 + result = SDL_SetEnvironmentVariable(env, "FOO", "1", 1); 657 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, 'FOO','1', 1)"); 658 + SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result); 658 659 expected = "1"; 659 - text = SDL_getenv("FOO"); 660 - SDLTest_AssertPass("Call to SDL_getenv('FOO')"); 660 + text = SDL_GetEnvironmentVariable(env, "FOO"); 661 + SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')"); 661 662 SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: %s, got: %s", expected, text); 662 - result = SDL_setenv("FOO", "", 1); 663 - SDLTest_AssertPass("Call to SDL_setenv('FOO','', 1)"); 664 - SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); 663 + result = SDL_SetEnvironmentVariable(env, "FOO", "", 1); 664 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, 'FOO','', 1)"); 665 + SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result); 665 666 expected = ""; 666 - text = SDL_getenv("FOO"); 667 - SDLTest_AssertPass("Call to SDL_getenv('FOO')"); 667 + text = SDL_GetEnvironmentVariable(env, "FOO"); 668 + SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')"); 668 669 SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: '%s', got: '%s'", expected, text); 669 - result = SDL_unsetenv("FOO"); 670 - SDLTest_AssertPass("Call to SDL_unsetenv('FOO')"); 671 - SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); 672 - text = SDL_getenv("FOO"); 673 - SDLTest_AssertPass("Call to SDL_getenv('FOO')"); 670 + result = SDL_UnsetEnvironmentVariable(env, "FOO"); 671 + SDLTest_AssertPass("Call to SDL_UnsetEnvironmentVariable(env, 'FOO')"); 672 + SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result); 673 + text = SDL_GetEnvironmentVariable(env, "FOO"); 674 + SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')"); 674 675 SDLTest_AssertCheck(text == NULL, "Verify returned text, expected: (null), got: %s", text); 675 - result = SDL_setenv("FOO", "0", 0); 676 - SDLTest_AssertPass("Call to SDL_setenv('FOO','0', 0)"); 677 - SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); 676 + result = SDL_SetEnvironmentVariable(env, "FOO", "0", 0); 677 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, 'FOO','0', 0)"); 678 + SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result); 678 679 expected = "0"; 679 - text = SDL_getenv("FOO"); 680 - SDLTest_AssertPass("Call to SDL_getenv('FOO')"); 680 + text = SDL_GetEnvironmentVariable(env, "FOO"); 681 + SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')"); 681 682 SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: %s, got: %s", expected, text); 682 683 683 684 /* Negative cases */ 684 685 for (overwrite = 0; overwrite <= 1; overwrite++) { 685 - result = SDL_setenv(NULL, value1, overwrite); 686 - SDLTest_AssertPass("Call to SDL_setenv(NULL,'%s', %i)", value1, overwrite); 687 - SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result); 688 - result = SDL_setenv("", value1, overwrite); 689 - SDLTest_AssertPass("Call to SDL_setenv('','%s', %i)", value1, overwrite); 690 - SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result); 691 - result = SDL_setenv("=", value1, overwrite); 692 - SDLTest_AssertPass("Call to SDL_setenv('=','%s', %i)", value1, overwrite); 693 - SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result); 694 - result = SDL_setenv(name, NULL, overwrite); 695 - SDLTest_AssertPass("Call to SDL_setenv('%s', NULL, %i)", name, overwrite); 696 - SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result); 686 + result = SDL_SetEnvironmentVariable(env, NULL, value1, overwrite); 687 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, NULL,'%s', %i)", value1, overwrite); 688 + SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result); 689 + result = SDL_SetEnvironmentVariable(env, "", value1, overwrite); 690 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '','%s', %i)", value1, overwrite); 691 + SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result); 692 + result = SDL_SetEnvironmentVariable(env, "=", value1, overwrite); 693 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '=','%s', %i)", value1, overwrite); 694 + SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result); 695 + result = SDL_SetEnvironmentVariable(env, name, NULL, overwrite); 696 + SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s', NULL, %i)", name, overwrite); 697 + SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result); 697 698 } 698 699 699 700 /* Clean up */ ··· 1402 1403 }; 1403 1404 1404 1405 static const SDLTest_TestCaseReference stdlibTest_getsetenv = { 1405 - stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_getenv and SDL_setenv", TEST_ENABLED 1406 + stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_GetEnvironmentVariable and SDL_SetEnvironmentVariable", TEST_ENABLED 1406 1407 }; 1407 1408 1408 1409 static const SDLTest_TestCaseReference stdlibTest_sscanf = {
+2 -2
test/testautomation_video.c
··· 43 43 needs_renderer = SDL_TRUE; 44 44 } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { 45 45 /* Try to detect if the x11 driver is running under XWayland */ 46 - const char *session_type = SDL_getenv("XDG_SESSION_TYPE"); 46 + const char *session_type = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE"); 47 47 if (session_type && SDL_strcasecmp(session_type, "wayland") == 0) { 48 48 needs_renderer = SDL_TRUE; 49 49 } ··· 1929 1929 * Other desktops can be enabled in the future as required. 1930 1930 */ 1931 1931 if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0 || SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { 1932 - const char *desktop = SDL_getenv("XDG_CURRENT_DESKTOP"); 1932 + const char *desktop = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_CURRENT_DESKTOP"); 1933 1933 if (SDL_strcmp(desktop, "GNOME") != 0 && SDL_strcmp(desktop, "KDE") != 0) { 1934 1934 SDLTest_Log("Skipping test video_getSetWindowState: desktop environment %s not supported", desktop); 1935 1935 return TEST_SKIPPED;
+1 -1
test/testerror.c
··· 93 93 /* Set the error value for the main thread */ 94 94 SDL_SetError("No worries"); 95 95 96 - if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { 96 + if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) { 97 97 SDL_Log("Not running slower tests"); 98 98 SDL_Quit(); 99 99 return 0;
+23 -62
test/testprocess.c
··· 35 35 36 36 static const char *options[] = { "/path/to/childprocess" EXE, NULL }; 37 37 38 - static char *env_key_val_string(const char *key) { 39 - const char *env = SDL_getenv(key); 40 - size_t size_result; 41 - char *result; 42 - 43 - if (env == NULL) { 44 - return NULL; 45 - } 46 - size_result = SDL_strlen(key) + SDL_strlen(env) + 2; 47 - result = SDL_malloc(size_result); 48 - SDL_snprintf(result, size_result, "%s=%s", key, env); 49 - return result; 50 - } 51 - 52 38 static char **DuplicateEnvironment(const char *key0, ...) 53 39 { 54 40 va_list ap; 55 - size_t count = 1; 56 - size_t i; 57 41 const char *keyN; 42 + SDL_Environment *env = SDL_GetEnvironment(); 43 + SDL_Environment *new_env = SDL_CreateEnvironment(SDL_TRUE); 58 44 char **result; 59 45 60 46 if (key0) { 61 - if (SDL_strchr(key0, '=') || SDL_getenv(key0)) { 62 - count += 1; 47 + char *sep = SDL_strchr(key0, '='); 48 + if (sep) { 49 + *sep = '\0'; 50 + SDL_SetEnvironmentVariable(new_env, key0, sep + 1, SDL_TRUE); 51 + *sep = '='; 52 + SDL_SetEnvironmentVariable(new_env, key0, sep, SDL_TRUE); 53 + } else { 54 + SDL_SetEnvironmentVariable(new_env, key0, SDL_GetEnvironmentVariable(env, key0), SDL_TRUE); 63 55 } 64 - 65 56 va_start(ap, key0); 66 57 for (;;) { 67 58 keyN = va_arg(ap, const char *); 68 59 if (keyN) { 69 - if (SDL_strchr(keyN, '=') || SDL_getenv(keyN)) { 70 - count += 1; 60 + sep = SDL_strchr(keyN, '='); 61 + if (sep) { 62 + *sep = '\0'; 63 + SDL_SetEnvironmentVariable(new_env, keyN, sep + 1, SDL_TRUE); 64 + *sep = '='; 65 + } else { 66 + SDL_SetEnvironmentVariable(new_env, keyN, SDL_GetEnvironmentVariable(env, keyN), SDL_TRUE); 71 67 } 72 68 } else { 73 69 break; ··· 76 72 va_end(ap); 77 73 } 78 74 79 - result = SDL_calloc(count, sizeof(char *)); 80 - 81 - i = 0; 82 - if (key0) { 83 - if (SDL_strchr(key0, '=')) { 84 - result[i++] = SDL_strdup(key0); 85 - } else if (SDL_getenv(key0)) { 86 - result[i++] = env_key_val_string(key0); 87 - } 88 - va_start(ap, key0); 89 - for (;;) { 90 - keyN = va_arg(ap, const char *); 91 - if (keyN) { 92 - if (SDL_strchr(keyN, '=')) { 93 - result[i++] = SDL_strdup(keyN); 94 - } else if (SDL_getenv(keyN)) { 95 - result[i++] = env_key_val_string(keyN); 96 - } 97 - } else { 98 - break; 99 - } 100 - } 101 - va_end(ap); 102 - } 75 + result = SDL_GetEnvironmentVariables(new_env); 76 + SDL_DestroyEnvironment(new_env); 103 77 return result; 104 78 } 105 79 106 - static void DestroyEnvironment(char **environment) { 107 - char **envp; 108 - 109 - if (!environment) { 110 - return; 111 - } 112 - for (envp = environment; *envp; envp++) { 113 - SDL_free(*envp); 114 - } 115 - SDL_free(environment); 116 - } 117 - 118 80 static int SDLCALL process_testArguments(void *arg) 119 81 { 120 82 TestProcessData *data = (TestProcessData *)arg; ··· 187 149 188 150 test_env_val = SDLTest_RandomAsciiStringOfSize(32); 189 151 SDLTest_AssertPass("Setting parent environment variable %s=%s", TEST_ENV_KEY, test_env_val); 190 - SDL_setenv(TEST_ENV_KEY, test_env_val, 1); 152 + SDL_SetEnvironmentVariable(SDL_GetEnvironment(), TEST_ENV_KEY, test_env_val, SDL_TRUE); 191 153 SDL_snprintf(buffer, sizeof(buffer), "%s=%s", TEST_ENV_KEY, test_env_val); 192 154 process_args[3] = buffer; 193 155 ··· 312 274 SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code); 313 275 SDLTest_AssertPass("About to destroy process"); 314 276 SDL_DestroyProcess(process); 315 - DestroyEnvironment(process_env); 277 + SDL_free(process_env); 316 278 SDL_free(test_env_val); 317 279 return TEST_COMPLETED; 280 + 318 281 failed: 319 282 SDL_free(test_env_val); 320 283 SDL_DestroyProcess(process); 321 - DestroyEnvironment(process_env); 284 + SDL_free(process_env); 322 285 return TEST_ABORTED; 323 286 } 324 287 ··· 330 293 "--stdin-to-stdout", 331 294 NULL, 332 295 }; 333 - const char **process_env = NULL; 334 296 SDL_PropertiesID props; 335 297 SDL_Process *process = NULL; 336 298 Sint64 pid; ··· 346 308 347 309 props = SDL_CreateProperties(); 348 310 SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args); 349 - SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, (void *)process_env); 350 311 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_APP); 351 312 SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP); 352 313 process = SDL_CreateProcessWithProperties(props);
+1 -1
test/testsurround.c
··· 223 223 SDL_Log("Playing %d Hz test tone on channel: %s\n", sine_freq, get_channel_name(j, total_channels)); 224 224 225 225 /* fill_buffer() will increment the active channel */ 226 - if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { 226 + if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) { 227 227 SDL_Delay(QUICK_TEST_TIME_MSEC); 228 228 } else { 229 229 SDL_Delay(CHANNEL_TEST_TIME_SEC * 1000);
+1 -1
test/testthread.c
··· 127 127 return 1; 128 128 } 129 129 130 - if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { 130 + if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) { 131 131 SDL_Log("Not running slower tests"); 132 132 SDL_Quit(); 133 133 return 0;
+1 -1
test/testtimer.c
··· 124 124 return 1; 125 125 } 126 126 127 - if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { 127 + if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) { 128 128 SDL_Log("Not running slower tests"); 129 129 SDL_Quit(); 130 130 return 0;