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.
This commit is contained in:
Sam Lantinga 2024-09-13 17:00:15 -07:00
parent 16ff7503b7
commit 90e01040c5
49 changed files with 696 additions and 252 deletions

View File

@ -21,13 +21,13 @@ Notes
-----
* gles1/gles2 support and renderers are disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PVR=ON`
These renderers support 720p and 1080i resolutions. These can be specified with:
`SDL_setenv("VITA_RESOLUTION", "720", 1);` and `SDL_setenv("VITA_RESOLUTION", "1080", 1);`
`SDL_SetHint(SDL_HINT_VITA_RESOLUTION, "720");` and `SDL_SetHint(SDL_HINT_VITA_RESOLUTION, "1080");`
* 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.
They support the same resolutions as the gles1/gles2 backends and require specifying `SDL_setenv("VITA_PVR_OGL", "1", 1);`
They support the same resolutions as the gles1/gles2 backends and require specifying `SDL_SetHint(SDL_HINT_VITA_PVR_OPENGL, "1");`
anytime before video subsystem initialization.
* gles2 support via PIB is disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PIB=ON`
* By default SDL emits mouse events for touch events on every touchscreen.
Vita has two touchscreens, so it's recommended to use `SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");` and handle touch events instead.
Individual touchscreens can be disabled with:
`SDL_setenv("VITA_DISABLE_TOUCH_FRONT", "1", 1);` and `SDL_setenv("VITA_DISABLE_TOUCH_BACK", "1", 1);`
`SDL_SetHint(SDL_HINT_VITA_ENABLE_FRONT_TOUCH, "0");` and `SDL_SetHint(SDL_HINT_VITA_ENABLE_BACK_TOUCH, "0");`
* Support for L2/R2/R3/R3 buttons, haptic feedback and gamepad led only available on PSTV, or when using external ds4 gamepad on vita.

View File

@ -978,9 +978,213 @@ extern SDL_DECLSPEC void SDLCALL SDL_aligned_free(void *mem);
*/
extern SDL_DECLSPEC int SDLCALL SDL_GetNumAllocations(void);
extern SDL_DECLSPEC const char * SDLCALL SDL_getenv(const char *name);
extern SDL_DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int overwrite);
extern SDL_DECLSPEC int SDLCALL SDL_unsetenv(const char *name);
/**
* A thread-safe set of environment variables
*
* \since This struct is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CleanupEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
* \sa SDL_DestroyEnvironment
*/
typedef struct SDL_Environment SDL_Environment;
/**
* Get the process environment.
*
* 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.
*
* \returns a pointer to the environment for the process or NULL on failure; call SDL_GetError()
* for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_CleanupEnvironment
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_GetEnvironment(void);
/**
* Cleanup the process environment.
*
* 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.
*
* \threadsafety This function is not thread-safe.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
*/
extern SDL_DECLSPEC void SDLCALL SDL_CleanupEnvironment(void);
/**
* Create a set of environment variables
*
* \param empty SDL_TRUE to create an empty environment, SDL_FALSE to initialize it from the C runtime environment.
* \returns a pointer to the new environment or NULL on failure; call SDL_GetError()
* for more information.
*
* \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()
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
* \sa SDL_DestroyEnvironment
*/
extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_CreateEnvironment(SDL_bool empty);
/**
* Get the value of a variable in the environment.
*
* \param env the environment to query.
* \param name the name of the variable to get.
* \returns a pointer to the value of the variable or NULL if it can't be found.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC const char * SDLCALL SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name);
/**
* Get all variables in the environment.
*
* \param env the environment to query.
* \returns a NULL terminated array of pointers to environment variables in the form "variable=value" or NULL on
* failure; call SDL_GetError() for more information. This is a
* single allocation that should be freed with SDL_free() when it is
* no longer needed.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC char ** SDLCALL SDL_GetEnvironmentVariables(SDL_Environment *env);
/**
* Set the value of a variable in the environment.
*
* \param env the environment to modify.
* \param name the name of the variable to set.
* \param value the value of the variable to set.
* \param overwrite SDL_TRUE to overwrite the variable if it exists, SDL_FALSE to return success without setting the variable if it already exists.
* \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError()
* for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC SDL_bool SDLCALL SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, SDL_bool overwrite);
/**
* Clear a variable from the environment.
*
* \param env the environment to modify.
* \param name the name of the variable to unset.
* \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError()
* for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC SDL_bool SDLCALL SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name);
/**
* Destroy a set of environment variables.
*
* \param env the environment to destroy.
*
* \threadsafety It is safe to call this function from any thread, as long as the environment is no longer in use.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_CreateEnvironment
*/
extern SDL_DECLSPEC void SDLCALL SDL_DestroyEnvironment(SDL_Environment *env);
/**
* Get the value of a variable in the environment.
*
* \param name the name of the variable to get.
* \returns a pointer to the value of the variable or NULL if it can't be found.
*
* \threadsafety This function is not thread safe, consider using SDL_GetEnvironmentVariable() instead.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironmentVariable
*/
extern SDL_DECLSPEC const char * SDLCALL SDL_getenv_unsafe(const char *name);
/**
* Set the value of a variable in the environment.
*
* \param name the name of the variable to set.
* \param value the value of the variable to set.
* \param overwrite 1 to overwrite the variable if it exists, 0 to return success without setting the variable if it already exists.
* \returns 0 on success, -1 on error.
*
* \threadsafety This function is not thread safe, consider using SDL_SetEnvironmentVariable() instead.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_SetEnvironmentVariable
*/
extern SDL_DECLSPEC int SDLCALL SDL_setenv_unsafe(const char *name, const char *value, int overwrite);
/**
* Clear a variable from the environment.
*
* \param name the name of the variable to unset.
* \returns 0 on success, -1 on error.
*
* \threadsafety This function is not thread safe, consider using SDL_UnsetEnvironmentVariable() instead..
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC int SDLCALL SDL_unsetenv_unsafe(const char *name);
typedef int (SDLCALL *SDL_CompareCallback)(const void *a, const void *b);
extern SDL_DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, SDL_CompareCallback compare);

View File

@ -255,12 +255,14 @@ void SDL_InitMainThread(void)
SDL_InitLog();
SDL_InitProperties();
SDL_GetGlobalProperties();
SDL_GetEnvironment();
SDL_InitHints();
}
static void SDL_QuitMainThread(void)
{
SDL_QuitHints();
SDL_CleanupEnvironment();
SDL_QuitProperties();
SDL_QuitLog();
SDL_QuitFilesystem();

View File

@ -318,6 +318,11 @@ bool SDL_KeyMatchID(const void *a, const void *b, void *unused)
return false;
}
void SDL_NukeFreeKey(const void *key, const void *value, void *unused)
{
SDL_free((void *)key);
}
void SDL_NukeFreeValue(const void *key, const void *value, void *unused)
{
SDL_free((void *)value);

View File

@ -55,6 +55,7 @@ extern bool SDL_KeyMatchString(const void *a, const void *b, void *unused);
extern Uint32 SDL_HashID(const void *key, void *unused);
extern bool SDL_KeyMatchID(const void *a, const void *b, void *unused);
extern void SDL_NukeFreeKey(const void *key, const void *value, void *unused);
extern void SDL_NukeFreeValue(const void *key, const void *value, void *unused);
#endif // SDL_hashtable_h_

View File

@ -72,7 +72,7 @@ SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPr
return SDL_InvalidParamError("name");
}
const char *env = SDL_getenv(name);
const char *env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name);
if (env && (priority < SDL_HINT_OVERRIDE)) {
return SDL_SetError("An environment variable is taking priority");
}
@ -126,7 +126,7 @@ SDL_bool SDL_ResetHint(const char *name)
return SDL_InvalidParamError("name");
}
const char *env = SDL_getenv(name);
const char *env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name);
const SDL_PropertiesID hints = GetHintProperties(false);
if (!hints) {
@ -165,7 +165,7 @@ static void SDLCALL ResetHintsCallback(void *userdata, SDL_PropertiesID hints, c
return; // uh...okay.
}
const char *env = SDL_getenv(name);
const char *env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name);
if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) {
SDL_HintWatch *entry = hint->callbacks;
while (entry) {
@ -196,7 +196,7 @@ const char *SDL_GetHint(const char *name)
return NULL;
}
const char *result = SDL_getenv(name);
const char *result = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name);
const SDL_PropertiesID hints = GetHintProperties(false);
if (hints) {

View File

@ -87,7 +87,7 @@ static void SDL_EnumUnixAudioDevices_Internal(const bool recording, const bool c
}
// Figure out what our audio device is
audiodev = SDL_getenv("AUDIODEV");
audiodev = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "AUDIODEV");
if (!audiodev) {
if (classic) {
audiodev = SDL_PATH_DEV_AUDIO;

View File

@ -1524,7 +1524,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
const char *utfname = (*env)->GetStringUTFChars(env, name, NULL);
const char *utfvalue = (*env)->GetStringUTFChars(env, value, NULL);
SDL_setenv(utfname, utfvalue, 1);
// This is only called at startup, to initialize the environment
SDL_setenv_unsafe(utfname, utfvalue, 1);
(*env)->ReleaseStringUTFChars(env, name, utfname);
(*env)->ReleaseStringUTFChars(env, value, utfvalue);

View File

@ -331,14 +331,14 @@ static char *IBus_GetDBusAddressFilename(void)
}
// Use this environment variable if it exists.
addr = SDL_getenv("IBUS_ADDRESS");
addr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "IBUS_ADDRESS");
if (addr && *addr) {
return SDL_strdup(addr);
}
/* Otherwise, we have to get the hostname, display, machine id, config dir
and look up the address from a filepath using all those bits, eek. */
disp_env = SDL_getenv("DISPLAY");
disp_env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "DISPLAY");
if (!disp_env || !*disp_env) {
display = SDL_strdup(":0.0");
@ -363,7 +363,7 @@ static char *IBus_GetDBusAddressFilename(void)
}
if (!*host) {
const char *session = SDL_getenv("XDG_SESSION_TYPE");
const char *session = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE");
if (session && SDL_strcmp(session, "wayland") == 0) {
host = "unix-wayland";
} else {
@ -373,11 +373,11 @@ static char *IBus_GetDBusAddressFilename(void)
SDL_memset(config_dir, 0, sizeof(config_dir));
conf_env = SDL_getenv("XDG_CONFIG_HOME");
conf_env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_CONFIG_HOME");
if (conf_env && *conf_env) {
SDL_strlcpy(config_dir, conf_env, sizeof(config_dir));
} else {
const char *home_env = SDL_getenv("HOME");
const char *home_env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home_env || !*home_env) {
SDL_free(display);
return NULL;

View File

@ -44,8 +44,8 @@ static void InitIME(void)
{
static bool inited = false;
#ifdef HAVE_FCITX
const char *im_module = SDL_getenv("SDL_IM_MODULE");
const char *xmodifiers = SDL_getenv("XMODIFIERS");
const char *im_module = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_IM_MODULE");
const char *xmodifiers = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XMODIFIERS");
#endif
if (inited == true) {

View File

@ -33,7 +33,9 @@ SDL_Sandbox SDL_DetectSandbox(void)
/* For Snap, we check multiple variables because they might be set for
* unrelated reasons. This is the same thing WebKitGTK does. */
if (SDL_getenv("SNAP") != NULL && SDL_getenv("SNAP_NAME") != NULL && SDL_getenv("SNAP_REVISION") != NULL) {
if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SNAP") != NULL &&
SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SNAP_NAME") != NULL &&
SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SNAP_REVISION") != NULL) {
return SDL_SANDBOX_SNAP;
}

View File

@ -229,12 +229,12 @@ static void run_zenity(zenityArgs* arg_struct)
/* Recent versions of Zenity have different exit codes, but picks up
different codes from the environment */
SDL_setenv("ZENITY_OK", "0", 1);
SDL_setenv("ZENITY_CANCEL", "1", 1);
SDL_setenv("ZENITY_ESC", "1", 1);
SDL_setenv("ZENITY_EXTRA", "2", 1);
SDL_setenv("ZENITY_ERROR", "2", 1);
SDL_setenv("ZENITY_TIMEOUT", "2", 1);
SDL_setenv_unsafe("ZENITY_OK", "0", 1);
SDL_setenv_unsafe("ZENITY_CANCEL", "1", 1);
SDL_setenv_unsafe("ZENITY_ESC", "1", 1);
SDL_setenv_unsafe("ZENITY_EXTRA", "2", 1);
SDL_setenv_unsafe("ZENITY_ERROR", "2", 1);
SDL_setenv_unsafe("ZENITY_TIMEOUT", "2", 1);
execv(args[0], args);

View File

@ -351,7 +351,7 @@ static Sint32 initialize_jumptable(Uint32 apiver, void *table, Uint32 tablesize)
// Init our jump table first.
#if ENABLE_SDL_CALL_LOGGING
{
const char *env = SDL_getenv_REAL("SDL_DYNAPI_LOG_CALLS");
const char *env = SDL_getenv_unsafe_REAL("SDL_DYNAPI_LOG_CALLS");
const SDL_bool log_calls = (env && SDL_atoi_REAL(env));
if (log_calls) {
#define SDL_DYNAPI_PROC(rc, fn, params, args, ret) jump_table.fn = fn##_LOGSDLCALLS;
@ -461,7 +461,7 @@ extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
static void SDL_InitDynamicAPILocked(void)
{
const char *libname = SDL_getenv_REAL(SDL_DYNAMIC_API_ENVVAR);
const char *libname = SDL_getenv_unsafe_REAL(SDL_DYNAMIC_API_ENVVAR);
SDL_DYNAPI_ENTRYFN entry = NULL; // funcs from here by default.
SDL_bool use_internal = SDL_TRUE;

View File

@ -52,6 +52,7 @@ SDL3_0.0.0 {
SDL_BroadcastCondition;
SDL_CaptureMouse;
SDL_ClaimWindowForGPUDevice;
SDL_CleanupEnvironment;
SDL_CleanupTLS;
SDL_ClearAudioStream;
SDL_ClearClipboardData;
@ -84,6 +85,7 @@ SDL3_0.0.0 {
SDL_CreateCondition;
SDL_CreateCursor;
SDL_CreateDirectory;
SDL_CreateEnvironment;
SDL_CreateGPUBuffer;
SDL_CreateGPUComputePipeline;
SDL_CreateGPUDevice;
@ -125,6 +127,7 @@ SDL3_0.0.0 {
SDL_DestroyAudioStream;
SDL_DestroyCondition;
SDL_DestroyCursor;
SDL_DestroyEnvironment;
SDL_DestroyGPUDevice;
SDL_DestroyHapticEffect;
SDL_DestroyMutex;
@ -276,6 +279,9 @@ SDL3_0.0.0 {
SDL_GetDisplayProperties;
SDL_GetDisplayUsableBounds;
SDL_GetDisplays;
SDL_GetEnvironment;
SDL_GetEnvironmentVariable;
SDL_GetEnvironmentVariables;
SDL_GetError;
SDL_GetEventFilter;
SDL_GetFloatProperty;
@ -785,6 +791,7 @@ SDL3_0.0.0 {
SDL_SetClipboardData;
SDL_SetClipboardText;
SDL_SetCursor;
SDL_SetEnvironmentVariable;
SDL_SetError;
SDL_SetEventEnabled;
SDL_SetEventFilter;
@ -933,6 +940,7 @@ SDL3_0.0.0 {
SDL_UnlockTexture;
SDL_UnmapGPUTransferBuffer;
SDL_UnregisterApp;
SDL_UnsetEnvironmentVariable;
SDL_UpdateGamepads;
SDL_UpdateHapticEffect;
SDL_UpdateJoysticks;
@ -1020,7 +1028,7 @@ SDL3_0.0.0 {
SDL_fmod;
SDL_fmodf;
SDL_free;
SDL_getenv;
SDL_getenv_unsafe;
SDL_hid_ble_scan;
SDL_hid_close;
SDL_hid_device_change_count;
@ -1095,7 +1103,7 @@ SDL3_0.0.0 {
SDL_roundf;
SDL_scalbn;
SDL_scalbnf;
SDL_setenv;
SDL_setenv_unsafe;
SDL_sin;
SDL_sinf;
SDL_snprintf;
@ -1138,7 +1146,7 @@ SDL3_0.0.0 {
SDL_uitoa;
SDL_ulltoa;
SDL_ultoa;
SDL_unsetenv;
SDL_unsetenv_unsafe;
SDL_utf8strlcpy;
SDL_utf8strlen;
SDL_utf8strnlen;

View File

@ -77,6 +77,7 @@
#define SDL_BroadcastCondition SDL_BroadcastCondition_REAL
#define SDL_CaptureMouse SDL_CaptureMouse_REAL
#define SDL_ClaimWindowForGPUDevice SDL_ClaimWindowForGPUDevice_REAL
#define SDL_CleanupEnvironment SDL_CleanupEnvironment_REAL
#define SDL_CleanupTLS SDL_CleanupTLS_REAL
#define SDL_ClearAudioStream SDL_ClearAudioStream_REAL
#define SDL_ClearClipboardData SDL_ClearClipboardData_REAL
@ -109,6 +110,7 @@
#define SDL_CreateCondition SDL_CreateCondition_REAL
#define SDL_CreateCursor SDL_CreateCursor_REAL
#define SDL_CreateDirectory SDL_CreateDirectory_REAL
#define SDL_CreateEnvironment SDL_CreateEnvironment_REAL
#define SDL_CreateGPUBuffer SDL_CreateGPUBuffer_REAL
#define SDL_CreateGPUComputePipeline SDL_CreateGPUComputePipeline_REAL
#define SDL_CreateGPUDevice SDL_CreateGPUDevice_REAL
@ -150,6 +152,7 @@
#define SDL_DestroyAudioStream SDL_DestroyAudioStream_REAL
#define SDL_DestroyCondition SDL_DestroyCondition_REAL
#define SDL_DestroyCursor SDL_DestroyCursor_REAL
#define SDL_DestroyEnvironment SDL_DestroyEnvironment_REAL
#define SDL_DestroyGPUDevice SDL_DestroyGPUDevice_REAL
#define SDL_DestroyHapticEffect SDL_DestroyHapticEffect_REAL
#define SDL_DestroyMutex SDL_DestroyMutex_REAL
@ -301,6 +304,9 @@
#define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL
#define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL
#define SDL_GetDisplays SDL_GetDisplays_REAL
#define SDL_GetEnvironment SDL_GetEnvironment_REAL
#define SDL_GetEnvironmentVariable SDL_GetEnvironmentVariable_REAL
#define SDL_GetEnvironmentVariables SDL_GetEnvironmentVariables_REAL
#define SDL_GetError SDL_GetError_REAL
#define SDL_GetEventFilter SDL_GetEventFilter_REAL
#define SDL_GetFloatProperty SDL_GetFloatProperty_REAL
@ -810,6 +816,7 @@
#define SDL_SetClipboardData SDL_SetClipboardData_REAL
#define SDL_SetClipboardText SDL_SetClipboardText_REAL
#define SDL_SetCursor SDL_SetCursor_REAL
#define SDL_SetEnvironmentVariable SDL_SetEnvironmentVariable_REAL
#define SDL_SetError SDL_SetError_REAL
#define SDL_SetEventEnabled SDL_SetEventEnabled_REAL
#define SDL_SetEventFilter SDL_SetEventFilter_REAL
@ -958,6 +965,7 @@
#define SDL_UnlockTexture SDL_UnlockTexture_REAL
#define SDL_UnmapGPUTransferBuffer SDL_UnmapGPUTransferBuffer_REAL
#define SDL_UnregisterApp SDL_UnregisterApp_REAL
#define SDL_UnsetEnvironmentVariable SDL_UnsetEnvironmentVariable_REAL
#define SDL_UpdateGamepads SDL_UpdateGamepads_REAL
#define SDL_UpdateHapticEffect SDL_UpdateHapticEffect_REAL
#define SDL_UpdateJoysticks SDL_UpdateJoysticks_REAL
@ -1045,7 +1053,7 @@
#define SDL_fmod SDL_fmod_REAL
#define SDL_fmodf SDL_fmodf_REAL
#define SDL_free SDL_free_REAL
#define SDL_getenv SDL_getenv_REAL
#define SDL_getenv_unsafe SDL_getenv_unsafe_REAL
#define SDL_hid_ble_scan SDL_hid_ble_scan_REAL
#define SDL_hid_close SDL_hid_close_REAL
#define SDL_hid_device_change_count SDL_hid_device_change_count_REAL
@ -1120,7 +1128,7 @@
#define SDL_roundf SDL_roundf_REAL
#define SDL_scalbn SDL_scalbn_REAL
#define SDL_scalbnf SDL_scalbnf_REAL
#define SDL_setenv SDL_setenv_REAL
#define SDL_setenv_unsafe SDL_setenv_unsafe_REAL
#define SDL_sin SDL_sin_REAL
#define SDL_sinf SDL_sinf_REAL
#define SDL_snprintf SDL_snprintf_REAL
@ -1163,7 +1171,7 @@
#define SDL_uitoa SDL_uitoa_REAL
#define SDL_ulltoa SDL_ulltoa_REAL
#define SDL_ultoa SDL_ultoa_REAL
#define SDL_unsetenv SDL_unsetenv_REAL
#define SDL_unsetenv_unsafe SDL_unsetenv_unsafe_REAL
#define SDL_utf8strlcpy SDL_utf8strlcpy_REAL
#define SDL_utf8strlen SDL_utf8strlen_REAL
#define SDL_utf8strnlen SDL_utf8strnlen_REAL

View File

@ -97,6 +97,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_BlitSurfaceUncheckedScaled,(SDL_Surface *a, const S
SDL_DYNAPI_PROC(void,SDL_BroadcastCondition,(SDL_Condition *a),(a),)
SDL_DYNAPI_PROC(SDL_bool,SDL_CaptureMouse,(SDL_bool a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_ClaimWindowForGPUDevice,(SDL_GPUDevice *a, SDL_Window *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_CleanupEnvironment,(void),(),)
SDL_DYNAPI_PROC(void,SDL_CleanupTLS,(void),(),)
SDL_DYNAPI_PROC(SDL_bool,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_ClearClipboardData,(void),(),return)
@ -129,6 +130,7 @@ SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateColorCursor,(SDL_Surface *a, int b, int c)
SDL_DYNAPI_PROC(SDL_Condition*,SDL_CreateCondition,(void),(),return)
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)
SDL_DYNAPI_PROC(SDL_bool,SDL_CreateDirectory,(const char *a),(a),return)
SDL_DYNAPI_PROC(SDL_Environment*,SDL_CreateEnvironment,(SDL_bool a),(a),return)
SDL_DYNAPI_PROC(SDL_GPUBuffer*,SDL_CreateGPUBuffer,(SDL_GPUDevice *a, const SDL_GPUBufferCreateInfo* b),(a,b),return)
SDL_DYNAPI_PROC(SDL_GPUComputePipeline*,SDL_CreateGPUComputePipeline,(SDL_GPUDevice *a, const SDL_GPUComputePipelineCreateInfo *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_GPUDevice*,SDL_CreateGPUDevice,(SDL_GPUShaderFormat a, SDL_bool b, const char *c),(a,b,c),return)
@ -170,6 +172,7 @@ SDL_DYNAPI_PROC(void,SDL_DelayNS,(Uint64 a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyCondition,(SDL_Condition *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyCursor,(SDL_Cursor *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyEnvironment,(SDL_Environment *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyGPUDevice,(SDL_GPUDevice *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyHapticEffect,(SDL_Haptic *a, int b),(a,b),)
SDL_DYNAPI_PROC(void,SDL_DestroyMutex,(SDL_Mutex *a),(a),)
@ -321,6 +324,9 @@ SDL_DYNAPI_PROC(const char*,SDL_GetDisplayName,(SDL_DisplayID a),(a),return)
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_GetDisplayUsableBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_DisplayID*,SDL_GetDisplays,(int *a),(a),return)
SDL_DYNAPI_PROC(SDL_Environment*,SDL_GetEnvironment,(void),(),return)
SDL_DYNAPI_PROC(const char*,SDL_GetEnvironmentVariable,(SDL_Environment *a, const char *b),(a,b),return)
SDL_DYNAPI_PROC(char**,SDL_GetEnvironmentVariables,(SDL_Environment *a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_GetError,(void),(),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),return)
SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return)
@ -821,6 +827,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_SetBooleanProperty,(SDL_PropertiesID a, const char
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)
SDL_DYNAPI_PROC(SDL_bool,SDL_SetClipboardText,(const char *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_SetCursor,(SDL_Cursor *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_SetEnvironmentVariable,(SDL_Environment *a, const char *b, const char *c, SDL_bool d),(a,b,c,d),return)
SDL_DYNAPI_PROC(void,SDL_SetEventEnabled,(Uint32 a, SDL_bool b),(a,b),)
SDL_DYNAPI_PROC(void,SDL_SetEventFilter,(SDL_EventFilter a, void *b),(a,b),)
SDL_DYNAPI_PROC(SDL_bool,SDL_SetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return)
@ -968,6 +975,7 @@ SDL_DYNAPI_PROC(void,SDL_UnlockSurface,(SDL_Surface *a),(a),)
SDL_DYNAPI_PROC(void,SDL_UnlockTexture,(SDL_Texture *a),(a),)
SDL_DYNAPI_PROC(void,SDL_UnmapGPUTransferBuffer,(SDL_GPUDevice *a, SDL_GPUTransferBuffer *b),(a,b),)
SDL_DYNAPI_PROC(void,SDL_UnregisterApp,(void),(),)
SDL_DYNAPI_PROC(SDL_bool,SDL_UnsetEnvironmentVariable,(SDL_Environment *a, const char *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_UpdateGamepads,(void),(),)
SDL_DYNAPI_PROC(SDL_bool,SDL_UpdateHapticEffect,(SDL_Haptic *a, int b, const SDL_HapticEffect *c),(a,b,c),return)
SDL_DYNAPI_PROC(void,SDL_UpdateJoysticks,(void),(),)
@ -1054,7 +1062,7 @@ SDL_DYNAPI_PROC(float,SDL_floorf,(float a),(a),return)
SDL_DYNAPI_PROC(double,SDL_fmod,(double a, double b),(a,b),return)
SDL_DYNAPI_PROC(float,SDL_fmodf,(float a, float b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_free,(void *a),(a),)
SDL_DYNAPI_PROC(const char*,SDL_getenv,(const char *a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_getenv_unsafe,(const char *a),(a),return)
SDL_DYNAPI_PROC(void,SDL_hid_ble_scan,(SDL_bool a),(a),)
SDL_DYNAPI_PROC(int,SDL_hid_close,(SDL_hid_device *a),(a),return)
SDL_DYNAPI_PROC(Uint32,SDL_hid_device_change_count,(void),(),return)
@ -1129,7 +1137,7 @@ SDL_DYNAPI_PROC(double,SDL_round,(double a),(a),return)
SDL_DYNAPI_PROC(float,SDL_roundf,(float a),(a),return)
SDL_DYNAPI_PROC(double,SDL_scalbn,(double a, int b),(a,b),return)
SDL_DYNAPI_PROC(float,SDL_scalbnf,(float a, int b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_setenv,(const char *a, const char *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_setenv_unsafe,(const char *a, const char *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(double,SDL_sin,(double a),(a),return)
SDL_DYNAPI_PROC(float,SDL_sinf,(float a),(a),return)
SDL_DYNAPI_PROC(double,SDL_sqrt,(double a),(a),return)
@ -1169,7 +1177,7 @@ SDL_DYNAPI_PROC(float,SDL_truncf,(float a),(a),return)
SDL_DYNAPI_PROC(char*,SDL_uitoa,(unsigned int a, char *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(char*,SDL_ulltoa,(unsigned long long a, char *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(char*,SDL_ultoa,(unsigned long a, char *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_unsetenv,(const char *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_unsetenv_unsafe,(const char *a),(a),return)
SDL_DYNAPI_PROC(size_t,SDL_utf8strlcpy,(SDL_OUT_Z_CAP(c) char *a, const char *b, size_t c),(a,b,c),return)
SDL_DYNAPI_PROC(size_t,SDL_utf8strlen,(const char *a),(a),return)
SDL_DYNAPI_PROC(size_t,SDL_utf8strnlen,(const char *a, size_t b),(a,b),return)

View File

@ -144,7 +144,7 @@ char *SDL_SYS_GetUserFolder(SDL_Folder folder)
switch (folder) {
case SDL_FOLDER_HOME:
base = SDL_getenv("HOME");
base = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!base) {
SDL_SetError("No $HOME environment variable available");

View File

@ -93,7 +93,7 @@ char *SDL_SYS_GetUserFolder(SDL_Folder folder)
return NULL;
}
home = SDL_getenv("HOME");
home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home) {
SDL_SetError("No $HOME environment variable available");
return NULL;

View File

@ -68,7 +68,7 @@ char *SDL_SYS_GetBasePath(void)
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
{
// !!! FIXME: is there a better way to do this?
const char *home = SDL_getenv("HOME");
const char *home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
const char *append = "/config/settings/";
size_t len = SDL_strlen(home);
@ -102,7 +102,7 @@ char *SDL_SYS_GetUserFolder(SDL_Folder folder)
const char *home = NULL;
char *result;
home = SDL_getenv("HOME");
home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home) {
SDL_SetError("No $HOME environment variable available");
return NULL;

View File

@ -74,7 +74,7 @@ static char *readSymLink(const char *path)
#ifdef SDL_PLATFORM_OPENBSD
static char *search_path_for_binary(const char *bin)
{
const char *envr_real = SDL_getenv("PATH");
const char *envr_real = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "PATH");
char *envr;
size_t alloc_size;
char *exe = NULL;
@ -163,7 +163,7 @@ char *SDL_SYS_GetBasePath(void)
exe = search_path_for_binary(cmdline[0]);
} else {
if (exe && *exe == '.') {
const char *pwd = SDL_getenv("PWD");
const char *pwd = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "PWD");
if (pwd && *pwd) {
SDL_asprintf(&pwddst, "%s/%s", pwd, exe);
}
@ -265,7 +265,7 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
*
* http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
*/
const char *envr = SDL_getenv("XDG_DATA_HOME");
const char *envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_DATA_HOME");
const char *append;
char *result = NULL;
char *ptr = NULL;
@ -281,7 +281,7 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
if (!envr) {
// You end up with "$HOME/.local/share/Game Name 2"
envr = SDL_getenv("HOME");
envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!envr) {
// we could take heroic measures with /etc/passwd, but oh well.
SDL_SetError("neither XDG_DATA_HOME nor HOME environment is set");
@ -368,12 +368,12 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa
int relative;
size_t l;
home_dir = SDL_getenv ("HOME");
home_dir = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home_dir)
goto error;
config_home = SDL_getenv ("XDG_CONFIG_HOME");
config_home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_CONFIG_HOME");
if (!config_home || config_home[0] == 0)
{
l = SDL_strlen (home_dir) + SDL_strlen ("/.config/user-dirs.dirs") + 1;
@ -495,7 +495,7 @@ static char *xdg_user_dir_lookup (const char *type)
if (dir)
return dir;
home_dir = SDL_getenv("HOME");
home_dir = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home_dir)
return NULL;
@ -533,7 +533,7 @@ char *SDL_SYS_GetUserFolder(SDL_Folder folder)
*/
switch(folder) {
case SDL_FOLDER_HOME:
param = SDL_getenv("HOME");
param = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!param) {
SDL_SetError("No $HOME environment variable available");

View File

@ -11591,7 +11591,7 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
static void VULKAN_INTERNAL_LoadEntryPoints(void)
{
// Required for MoltenVK support
SDL_setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
SDL_setenv_unsafe("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
// Load Vulkan entry points
if (!SDL_Vulkan_LoadLibrary(NULL)) {

View File

@ -537,7 +537,7 @@ SDL_bool SDL_SetHapticGain(SDL_Haptic *haptic, int gain)
}
// The user can use an environment variable to override the max gain.
env = SDL_getenv("SDL_HAPTIC_GAIN_MAX");
env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_HAPTIC_GAIN_MAX");
if (env) {
max_gain = SDL_atoi(env);

View File

@ -78,13 +78,13 @@ bool SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
*tmp = '\0';
// LANG is the primary locale (maybe)
envr = SDL_getenv("LANG");
envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANG");
if (envr) {
SDL_strlcpy(tmp, envr, buflen);
}
// fallback languages
envr = SDL_getenv("LANGUAGE");
envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANGUAGE");
if (envr) {
if (*tmp) {
SDL_strlcat(tmp, ":", buflen);

View File

@ -48,7 +48,7 @@ int SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserv
_free(cvalue);
}
}
}, SDL_setenv);
}, SDL_setenv_unsafe);
return mainFunction(argc, argv);
}

View File

@ -41,7 +41,7 @@ bool SDL_SYS_OpenURL(const char *url)
pid_t pid2;
const char *args[] = { "xdg-open", url, NULL };
// Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam
SDL_unsetenv("LD_PRELOAD");
SDL_unsetenv_unsafe("LD_PRELOAD");
if (posix_spawnp(&pid2, args[0], NULL, NULL, (char **)args, environ) == 0) {
// Child process doesn't wait for possibly-blocking grandchild.
_exit(EXIT_SUCCESS);
@ -51,7 +51,7 @@ bool SDL_SYS_OpenURL(const char *url)
#else
pid_t pid2;
// Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam
SDL_unsetenv("LD_PRELOAD");
SDL_unsetenv_unsafe("LD_PRELOAD");
// Notice this is vfork and not fork!
pid2 = vfork();
if (pid2 == 0) { // Grandchild process will try to launch the url

View File

@ -35,15 +35,6 @@
#include "../SDL_sysprocess.h"
#include "../../file/SDL_iostream_c.h"
#if defined(SDL_PLATFORM_MACOS)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#elif defined(SDL_PLATFORM_FREEBSD)
#include <dlfcn.h>
#define environ ((char **)dlsym(RTLD_DEFAULT, "environ"))
#else
extern char **environ;
#endif
#define READ_END 0
#define WRITE_END 1
@ -114,7 +105,7 @@ static bool GetStreamFD(SDL_PropertiesID props, const char *property, int *resul
bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID props)
{
char * const *args = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, NULL);
char * const *env = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, environ);
char * const *env = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, NULL);
SDL_ProcessIO stdin_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL);
SDL_ProcessIO stdout_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_INHERITED);
SDL_ProcessIO stderr_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_INHERITED);
@ -124,6 +115,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
int stdout_pipe[2] = { -1, -1 };
int stderr_pipe[2] = { -1, -1 };
int fd = -1;
char **env_copy = NULL;
// Keep the malloc() before exec() so that an OOM won't run a process at all
SDL_ProcessData *data = SDL_calloc(1, sizeof(*data));
@ -278,6 +270,11 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
}
}
if (!env) {
env_copy = SDL_GetEnvironmentVariables(SDL_GetEnvironment());
env = env_copy;
}
// Spawn the new process
if (posix_spawnp(&data->pid, args[0], &fa, &attr, args, env) != 0) {
SDL_SetError("posix_spawn failed: %s", strerror(errno));
@ -308,6 +305,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
posix_spawn_file_actions_destroy(&fa);
posix_spawnattr_destroy(&attr);
SDL_free(env_copy);
return true;
@ -338,6 +336,7 @@ posix_spawn_fail_none:
if (stderr_pipe[WRITE_END] >= 0) {
close(stderr_pipe[WRITE_END]);
}
SDL_free(env_copy);
return false;
}

View File

@ -186,6 +186,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
HANDLE stdin_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
HANDLE stdout_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
HANDLE stderr_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
char **env_copy = NULL;
bool result = false;
// Keep the malloc() before exec() so that an OOM won't run a process at all
@ -199,6 +200,10 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
goto done;
}
if (!env) {
env_copy = SDL_GetEnvironmentVariables(SDL_GetEnvironment());
env = (const char * const *)env_copy;
}
if (!join_env(env, &createprocess_env)) {
goto done;
}
@ -381,6 +386,7 @@ done:
}
SDL_free(createprocess_cmdline);
SDL_free(createprocess_env);
SDL_free(env_copy);
if (!result) {
if (stdin_pipe[WRITE_END] != INVALID_HANDLE_VALUE) {

View File

@ -21,6 +21,7 @@
#include "SDL_internal.h"
#include "SDL_getenv_c.h"
#include "../SDL_hashtable.h"
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
#include "../core/windows/SDL_windows.h"
@ -40,11 +41,23 @@
#define HAVE_LOCAL_ENVIRONMENT
#endif
#if !defined(SDL_PLATFORM_WINDOWS)
#if defined(SDL_PLATFORM_MACOS)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#elif defined(SDL_PLATFORM_FREEBSD)
#include <dlfcn.h>
#define environ ((char **)dlsym(RTLD_DEFAULT, "environ"))
#else
extern char **environ;
#endif
#endif // !SDL_PLATFORM_WINDOWS
// Put a variable into the environment
// Note: Name may not contain a '=' character. (Reference: http://www.unix.com/man-page/Linux/3/setenv/)
#ifdef HAVE_LIBC_ENVIRONMENT
#if defined(HAVE_SETENV)
int SDL_setenv(const char *name, const char *value, int overwrite)
int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
{
// Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) {
@ -55,7 +68,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
}
// We have a real environment table, but no real setenv? Fake it w/ putenv.
#else
int SDL_setenv(const char *name, const char *value, int overwrite)
int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
{
char *new_variable;
@ -79,7 +92,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
}
#endif
#elif defined(HAVE_WIN32_ENVIRONMENT)
int SDL_setenv(const char *name, const char *value, int overwrite)
int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
{
// Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) {
@ -101,7 +114,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
// We'll leak this, as environment variables are intended to persist past SDL_Quit()
static char **SDL_env;
int SDL_setenv(const char *name, const char *value, int overwrite)
int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
{
int added;
size_t len, i;
@ -114,7 +127,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
}
// See if it already exists
if (!overwrite && SDL_getenv(name)) {
if (!overwrite && SDL_getenv_unsafe(name)) {
return 0;
}
@ -164,7 +177,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
#ifdef HAVE_LIBC_ENVIRONMENT
#if defined(HAVE_UNSETENV)
int SDL_unsetenv(const char *name)
int SDL_unsetenv_unsafe(const char *name)
{
// Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
@ -175,7 +188,7 @@ int SDL_unsetenv(const char *name)
}
// We have a real environment table, but no unsetenv? Fake it w/ putenv.
#else
int SDL_unsetenv(const char *name)
int SDL_unsetenv_unsafe(const char *name)
{
// Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
@ -187,7 +200,7 @@ int SDL_unsetenv(const char *name)
}
#endif
#elif defined(HAVE_WIN32_ENVIRONMENT)
int SDL_unsetenv(const char *name)
int SDL_unsetenv_unsafe(const char *name)
{
// Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
@ -200,7 +213,7 @@ int SDL_unsetenv(const char *name)
return 0;
}
#else
int SDL_unsetenv(const char *name)
int SDL_unsetenv_unsafe(const char *name)
{
size_t len, i;
@ -226,7 +239,7 @@ int SDL_unsetenv(const char *name)
// Retrieve a variable named "name" from the environment
#ifdef HAVE_LIBC_ENVIRONMENT
const char *SDL_getenv(const char *name)
const char *SDL_getenv_unsafe(const char *name)
{
#ifdef SDL_PLATFORM_ANDROID
// Make sure variables from the application manifest are available
@ -241,7 +254,7 @@ const char *SDL_getenv(const char *name)
return getenv(name);
}
#elif defined(HAVE_WIN32_ENVIRONMENT)
const char *SDL_getenv(const char *name)
const char *SDL_getenv_unsafe(const char *name)
{
DWORD length, maxlen = 0;
char *string = NULL;
@ -280,7 +293,7 @@ const char *SDL_getenv(const char *name)
return result;
}
#else
const char *SDL_getenv(const char *name)
const char *SDL_getenv_unsafe(const char *name)
{
size_t len, i;
char *value;
@ -304,3 +317,244 @@ const char *SDL_getenv(const char *name)
return value;
}
#endif // HAVE_LIBC_ENVIRONMENT
struct SDL_Environment
{
SDL_Mutex *lock;
SDL_HashTable *strings;
};
static SDL_Environment *SDL_environment;
SDL_Environment *SDL_GetEnvironment(void)
{
if (!SDL_environment) {
SDL_environment = SDL_CreateEnvironment(false);
}
return SDL_environment;
}
void SDL_CleanupEnvironment(void)
{
SDL_Environment *env = SDL_environment;
if (env) {
SDL_environment = NULL;
SDL_DestroyEnvironment(env);
}
}
SDL_Environment *SDL_CreateEnvironment(SDL_bool empty)
{
SDL_Environment *env = SDL_calloc(1, sizeof(*env));
if (!env) {
return NULL;
}
env->strings = SDL_CreateHashTable(NULL, 16, SDL_HashString, SDL_KeyMatchString, SDL_NukeFreeKey, false);
if (!env->strings) {
SDL_free(env);
return NULL;
}
// Don't fail if we can't create a mutex (e.g. on a single-thread environment)
env->lock = SDL_CreateMutex();
if (!empty) {
#ifdef SDL_PLATFORM_WINDOWS
LPWCH strings = GetEnvironmentStringsW();
if (strings) {
for (LPWCH string = strings; *string; string += SDL_wcslen(string) + 1) {
char *variable = WIN_StringToUTF8W(string);
if (!variable) {
continue;
}
char *value = SDL_strchr(variable, '=');
if (!value || value == variable) {
SDL_free(variable);
continue;
}
*value++ = '\0';
SDL_InsertIntoHashTable(env->strings, variable, value);
}
FreeEnvironmentStringsW(strings);
}
#else
#ifdef SDL_PLATFORM_ANDROID
// Make sure variables from the application manifest are available
Android_JNI_GetManifestEnvironmentVariables();
#endif
char **strings = environ;
for (int i = 0; strings[i]; ++i) {
char *variable = SDL_strdup(strings[i]);
if (!variable) {
continue;
}
char *value = SDL_strchr(variable, '=');
if (!value || value == variable) {
SDL_free(variable);
continue;
}
*value++ = '\0';
SDL_InsertIntoHashTable(env->strings, variable, value);
}
#endif // SDL_PLATFORM_WINDOWS
}
return env;
}
const char *SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name)
{
const char *result = NULL;
if (!env) {
return NULL;
} else if (!name || *name == '\0') {
return NULL;
}
SDL_LockMutex(env->lock);
{
const char *value;
if (SDL_FindInHashTable(env->strings, name, (const void **)&value)) {
result = SDL_GetPersistentString(value);
}
}
SDL_UnlockMutex(env->lock);
return result;
}
char **SDL_GetEnvironmentVariables(SDL_Environment *env)
{
char **result = NULL;
if (!env) {
SDL_InvalidParamError("env");
return NULL;
}
SDL_LockMutex(env->lock);
{
size_t count, length = 0;
void *iter;
const char *key, *value;
// First pass, get the size we need for all the strings
count = 0;
iter = NULL;
while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) {
length += SDL_strlen(key) + 1 + SDL_strlen(value) + 1;
++count;
}
// Allocate memory for the strings
result = (char **)SDL_malloc((count + 1) * sizeof(*result) + length);
char *string = (char *)(result + count + 1);
// Second pass, copy the strings
count = 0;
iter = NULL;
while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) {
size_t len;
result[count] = string;
len = SDL_strlen(key);
SDL_memcpy(string, key, len);
string += len;
*string++ = '=';
len = SDL_strlen(value);
SDL_memcpy(string, value, len);
string += len;
*string++ = '\0';
++count;
}
result[count] = NULL;
}
SDL_UnlockMutex(env->lock);
return result;
}
SDL_bool SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, SDL_bool overwrite)
{
bool result = false;
if (!env) {
return SDL_InvalidParamError("env");
} else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
return SDL_InvalidParamError("name");
} else if (!value) {
return SDL_InvalidParamError("value");
}
SDL_LockMutex(env->lock);
{
const void *existing_value;
bool insert = true;
if (SDL_FindInHashTable(env->strings, name, &existing_value)) {
if (!overwrite) {
result = true;
insert = false;
} else {
SDL_RemoveFromHashTable(env->strings, name);
}
}
if (insert) {
char *string = NULL;
if (SDL_asprintf(&string, "%s=%s", name, value) > 0) {
size_t len = SDL_strlen(name);
string[len] = '\0';
name = string;
value = string + len + 1;
result = SDL_InsertIntoHashTable(env->strings, name, value);
}
}
}
SDL_UnlockMutex(env->lock);
return result;
}
SDL_bool SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name)
{
bool result = false;
if (!env) {
return SDL_InvalidParamError("env");
} else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
return SDL_InvalidParamError("name");
}
SDL_LockMutex(env->lock);
{
const void *value;
if (SDL_FindInHashTable(env->strings, name, &value)) {
result = SDL_RemoveFromHashTable(env->strings, name);
} else {
result = true;
}
}
SDL_UnlockMutex(env->lock);
return result;
}
void SDL_DestroyEnvironment(SDL_Environment *env)
{
if (!env || env == SDL_environment) {
return;
}
SDL_DestroyMutex(env->lock);
SDL_DestroyHashTable(env->strings);
SDL_free(env);
}

View File

@ -163,15 +163,15 @@ static const char *getlocale(char *buffer, size_t bufsize)
const char *lang;
char *ptr;
lang = SDL_getenv("LC_ALL");
lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_ALL");
if (!lang) {
lang = SDL_getenv("LC_CTYPE");
lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_CTYPE");
}
if (!lang) {
lang = SDL_getenv("LC_MESSAGES");
lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_MESSAGES");
}
if (!lang) {
lang = SDL_getenv("LANG");
lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANG");
}
if (!lang || !*lang || SDL_strcmp(lang, "C") == 0) {
lang = "ASCII";

View File

@ -299,7 +299,7 @@ void SDLTest_TrackAllocations(void)
#ifdef SDLTEST_UNWIND_NO_PROC_NAME_BY_IP
do {
/* Don't use SDL_GetHint: SDL_malloc is off limits. */
const char *env_trackmem = SDL_getenv("SDL_TRACKMEM_SYMBOL_NAMES");
const char *env_trackmem = SDL_getenv_unsafe("SDL_TRACKMEM_SYMBOL_NAMES");
if (env_trackmem) {
if (SDL_strcasecmp(env_trackmem, "1") == 0 || SDL_strcasecmp(env_trackmem, "yes") == 0 || SDL_strcasecmp(env_trackmem, "true") == 0) {
s_unwind_symbol_names = SDL_TRUE;

View File

@ -341,7 +341,7 @@ static bool SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_
#if !defined(SDL_VIDEO_STATIC_ANGLE) && !defined(SDL_VIDEO_DRIVER_VITA)
/* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
path = SDL_getenv_unsafe("SDL_VIDEO_GL_DRIVER");
if (path) {
opengl_dll_handle = SDL_LoadObject(path);
}
@ -401,7 +401,7 @@ static bool SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_
if (egl_dll_handle) {
SDL_UnloadObject(egl_dll_handle);
}
path = SDL_getenv("SDL_VIDEO_EGL_DRIVER");
path = SDL_getenv_unsafe("SDL_VIDEO_EGL_DRIVER");
if (!path) {
path = DEFAULT_EGL;
}

View File

@ -1292,11 +1292,11 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
*/
// Look up the preferred locale, falling back to "C" as default
locale = SDL_getenv("LC_ALL");
locale = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_ALL");
if (!locale) {
locale = SDL_getenv("LC_CTYPE");
locale = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_CTYPE");
if (!locale) {
locale = SDL_getenv("LANG");
locale = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANG");
if (!locale) {
locale = "C";
}

View File

@ -141,8 +141,8 @@ bool Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *butto
};
// Are we trying to connect to or are currently in a Wayland session?
if (!SDL_getenv("WAYLAND_DISPLAY")) {
const char *session = SDL_getenv("XDG_SESSION_TYPE");
if (!SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "WAYLAND_DISPLAY")) {
const char *session = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE");
if (session && SDL_strcasecmp(session, "wayland") != 0) {
return SDL_SetError("Not on a wayland display");
}

View File

@ -345,7 +345,7 @@ static bool wayland_get_system_cursor(SDL_VideoData *vdata, SDL_CursorData *cdat
// Fallback envvar if the DBus properties don't exist
if (size <= 0) {
const char *xcursor_size = SDL_getenv("XCURSOR_SIZE");
const char *xcursor_size = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XCURSOR_SIZE");
if (xcursor_size) {
size = SDL_atoi(xcursor_size);
}
@ -381,7 +381,7 @@ static bool wayland_get_system_cursor(SDL_VideoData *vdata, SDL_CursorData *cdat
// Fallback envvar if the DBus properties don't exist
if (!xcursor_theme) {
xcursor_theme = SDL_getenv("XCURSOR_THEME");
xcursor_theme = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XCURSOR_THEME");
}
theme = WAYLAND_wl_cursor_theme_load(xcursor_theme, size, vdata->shm);

View File

@ -80,7 +80,7 @@ static int CreateTempFD(off_t size)
const char *xdg_path;
char tmp_path[PATH_MAX];
xdg_path = SDL_getenv("XDG_RUNTIME_DIR");
xdg_path = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_RUNTIME_DIR");
if (!xdg_path) {
return -1;
}

View File

@ -429,8 +429,8 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
bool display_is_external = !!display;
// Are we trying to connect to or are currently in a Wayland session?
if (!SDL_getenv("WAYLAND_DISPLAY")) {
const char *session = SDL_getenv("XDG_SESSION_TYPE");
if (!SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "WAYLAND_DISPLAY")) {
const char *session = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE");
if (session && SDL_strcasecmp(session, "wayland") != 0) {
return NULL;
}

View File

@ -1914,14 +1914,14 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
/* Note that we don't check for empty strings, as that is still
* considered a valid activation token!
*/
const char *activation_token = SDL_getenv("XDG_ACTIVATION_TOKEN");
const char *activation_token = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_ACTIVATION_TOKEN");
if (activation_token) {
xdg_activation_v1_activate(c->activation_manager,
activation_token,
data->surface);
// Clear this variable, per the protocol's request
SDL_unsetenv("XDG_ACTIVATION_TOKEN");
SDL_unsetenv_unsafe("XDG_ACTIVATION_TOKEN");
}
}

View File

@ -169,7 +169,7 @@ bool X11_InitKeyboard(SDL_VideoDevice *_this)
char *prev_locale = setlocale(LC_ALL, NULL);
char *prev_xmods = X11_XSetLocaleModifiers(NULL);
const char *new_xmods = "";
const char *env_xmods = SDL_getenv("XMODIFIERS");
const char *env_xmods = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XMODIFIERS");
bool has_dbus_ime_support = false;
if (prev_locale) {

View File

@ -248,7 +248,7 @@ static float GetGlobalContentScale(SDL_VideoDevice *_this)
// If that failed, try the GDK_SCALE envvar...
if (scale_factor <= 0.0) {
const char *scale_str = SDL_getenv("GDK_SCALE");
const char *scale_str = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "GDK_SCALE");
if (scale_str) {
scale_factor = SDL_atoi(scale_str);
}

View File

@ -5,14 +5,6 @@
#include <stdio.h>
#include <errno.h>
#if defined(SDL_PLATFORM_WINDOWS)
#include <windows.h>
#elif defined(SDL_PLATFORM_MACOS)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char **environ;
#endif
int main(int argc, char *argv[]) {
SDLTest_CommonState *state;
@ -95,26 +87,18 @@ int main(int argc, char *argv[]) {
}
if (print_environment || expect_environment) {
#if defined(SDL_PLATFORM_WINDOWS)
char *original_env = GetEnvironmentStrings();
const char *env = original_env;
for (; env[0]; env += SDL_strlen(env) + 1) {
#else
char **envp = environ;
for (; *envp; envp++) {
const char *env = *envp;
#endif
if (print_environment) {
fprintf(stdout, "%s\n", env);
}
if (expect_environment) {
expect_environment_match |= SDL_strcmp(env, expect_environment) == 0;
char **env = SDL_GetEnvironmentVariables(SDL_GetEnvironment());
if (env) {
for (i = 0; env[i]; ++i) {
if (print_environment) {
fprintf(stdout, "%s\n", env[i]);
}
if (expect_environment) {
expect_environment_match |= SDL_strcmp(env[i], expect_environment) == 0;
}
}
SDL_free(env);
}
#ifdef SDL_PLATFORM_WINDOWS
FreeEnvironmentStringsA(original_env);
#endif
}
if (stdin_to_stdout || stdin_to_stderr) {

View File

@ -740,7 +740,7 @@ int main(int argc, char *argv[])
RunBasicTest();
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) {
if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Log("Not running slower tests");
return 0;
}

View File

@ -130,7 +130,7 @@ static int SDLCALL hints_setHint(void *arg)
SDL_free(value);
/* Set default value in environment */
SDL_setenv(testHint, "original", 1);
SDL_SetEnvironmentVariable(SDL_GetEnvironment(), testHint, "original", 1);
SDLTest_AssertPass("Call to SDL_GetHint() after saving and restoring hint");
originalValue = SDL_GetHint(testHint);

View File

@ -542,10 +542,11 @@ static int SDLCALL stdlib_swprintf(void *arg)
#endif
/**
* Call to SDL_getenv and SDL_setenv
* Call to SDL_GetEnvironmentVariable() and SDL_SetEnvironmentVariable()
*/
static int SDLCALL stdlib_getsetenv(void *arg)
{
SDL_Environment *env = SDL_GetEnvironment();
const int nameLen = 16;
char name[17];
int counter;
@ -556,7 +557,7 @@ static int SDLCALL stdlib_getsetenv(void *arg)
int overwrite;
const char *text;
/* Create a random name. This tests SDL_getenv, since we need to */
/* Create a random name. This tests SDL_GetEnvironmentVariable, since we need to */
/* make sure the variable is not set yet (it shouldn't). */
do {
for (counter = 0; counter < nameLen; counter++) {
@ -564,8 +565,8 @@ static int SDLCALL stdlib_getsetenv(void *arg)
}
name[nameLen] = '\0';
text = SDL_getenv(name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
if (text) {
SDLTest_Log("Expected: NULL, Got: '%s' (%i)", text, (int)SDL_strlen(text));
}
@ -578,13 +579,13 @@ static int SDLCALL stdlib_getsetenv(void *arg)
/* Set value 1 without overwrite */
overwrite = 0;
expected = value1;
result = SDL_setenv(name, value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite);
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, name, value1, overwrite);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value1, overwrite);
SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
/* Check value */
text = SDL_getenv(name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
if (text != NULL) {
SDLTest_AssertCheck(
@ -597,13 +598,13 @@ static int SDLCALL stdlib_getsetenv(void *arg)
/* Set value 2 with overwrite */
overwrite = 1;
expected = value2;
result = SDL_setenv(name, value2, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value2, overwrite);
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, name, value2, overwrite);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value2, overwrite);
SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
/* Check value */
text = SDL_getenv(name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
if (text != NULL) {
SDLTest_AssertCheck(
@ -616,13 +617,13 @@ static int SDLCALL stdlib_getsetenv(void *arg)
/* Set value 1 without overwrite */
overwrite = 0;
expected = value2;
result = SDL_setenv(name, value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite);
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, name, value1, overwrite);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value1, overwrite);
SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
/* Check value */
text = SDL_getenv(name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
if (text != NULL) {
SDLTest_AssertCheck(
@ -635,13 +636,13 @@ static int SDLCALL stdlib_getsetenv(void *arg)
/* Set value 1 with overwrite */
overwrite = 1;
expected = value1;
result = SDL_setenv(name, value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite);
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, name, value1, overwrite);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value1, overwrite);
SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
/* Check value */
text = SDL_getenv(name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
if (text != NULL) {
SDLTest_AssertCheck(
@ -652,48 +653,48 @@ static int SDLCALL stdlib_getsetenv(void *arg)
}
/* Verify setenv() with empty string vs unsetenv() */
result = SDL_setenv("FOO", "1", 1);
SDLTest_AssertPass("Call to SDL_setenv('FOO','1', 1)");
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, "FOO", "1", 1);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, 'FOO','1', 1)");
SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
expected = "1";
text = SDL_getenv("FOO");
SDLTest_AssertPass("Call to SDL_getenv('FOO')");
text = SDL_GetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: %s, got: %s", expected, text);
result = SDL_setenv("FOO", "", 1);
SDLTest_AssertPass("Call to SDL_setenv('FOO','', 1)");
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, "FOO", "", 1);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, 'FOO','', 1)");
SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
expected = "";
text = SDL_getenv("FOO");
SDLTest_AssertPass("Call to SDL_getenv('FOO')");
text = SDL_GetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: '%s', got: '%s'", expected, text);
result = SDL_unsetenv("FOO");
SDLTest_AssertPass("Call to SDL_unsetenv('FOO')");
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
text = SDL_getenv("FOO");
SDLTest_AssertPass("Call to SDL_getenv('FOO')");
result = SDL_UnsetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_UnsetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
text = SDL_GetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(text == NULL, "Verify returned text, expected: (null), got: %s", text);
result = SDL_setenv("FOO", "0", 0);
SDLTest_AssertPass("Call to SDL_setenv('FOO','0', 0)");
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, "FOO", "0", 0);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, 'FOO','0', 0)");
SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
expected = "0";
text = SDL_getenv("FOO");
SDLTest_AssertPass("Call to SDL_getenv('FOO')");
text = SDL_GetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: %s, got: %s", expected, text);
/* Negative cases */
for (overwrite = 0; overwrite <= 1; overwrite++) {
result = SDL_setenv(NULL, value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv(NULL,'%s', %i)", value1, overwrite);
SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result);
result = SDL_setenv("", value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('','%s', %i)", value1, overwrite);
SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result);
result = SDL_setenv("=", value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('=','%s', %i)", value1, overwrite);
SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result);
result = SDL_setenv(name, NULL, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s', NULL, %i)", name, overwrite);
SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result);
result = SDL_SetEnvironmentVariable(env, NULL, value1, overwrite);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, NULL,'%s', %i)", value1, overwrite);
SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, "", value1, overwrite);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '','%s', %i)", value1, overwrite);
SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, "=", value1, overwrite);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '=','%s', %i)", value1, overwrite);
SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result);
result = SDL_SetEnvironmentVariable(env, name, NULL, overwrite);
SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s', NULL, %i)", name, overwrite);
SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result);
}
/* Clean up */
@ -1402,7 +1403,7 @@ static const SDLTest_TestCaseReference stdlibTest_swprintf = {
};
static const SDLTest_TestCaseReference stdlibTest_getsetenv = {
stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_getenv and SDL_setenv", TEST_ENABLED
stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_GetEnvironmentVariable and SDL_SetEnvironmentVariable", TEST_ENABLED
};
static const SDLTest_TestCaseReference stdlibTest_sscanf = {

View File

@ -43,7 +43,7 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title)
needs_renderer = SDL_TRUE;
} else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) {
/* Try to detect if the x11 driver is running under XWayland */
const char *session_type = SDL_getenv("XDG_SESSION_TYPE");
const char *session_type = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE");
if (session_type && SDL_strcasecmp(session_type, "wayland") == 0) {
needs_renderer = SDL_TRUE;
}
@ -1929,7 +1929,7 @@ static int SDLCALL video_getSetWindowState(void *arg)
* Other desktops can be enabled in the future as required.
*/
if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0 || SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) {
const char *desktop = SDL_getenv("XDG_CURRENT_DESKTOP");
const char *desktop = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_CURRENT_DESKTOP");
if (SDL_strcmp(desktop, "GNOME") != 0 && SDL_strcmp(desktop, "KDE") != 0) {
SDLTest_Log("Skipping test video_getSetWindowState: desktop environment %s not supported", desktop);
return TEST_SKIPPED;

View File

@ -93,7 +93,7 @@ int main(int argc, char *argv[])
/* Set the error value for the main thread */
SDL_SetError("No worries");
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) {
if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Log("Not running slower tests");
SDL_Quit();
return 0;

View File

@ -35,39 +35,35 @@ static void SDLCALL setUpProcess(void **arg) {
static const char *options[] = { "/path/to/childprocess" EXE, NULL };
static char *env_key_val_string(const char *key) {
const char *env = SDL_getenv(key);
size_t size_result;
char *result;
if (env == NULL) {
return NULL;
}
size_result = SDL_strlen(key) + SDL_strlen(env) + 2;
result = SDL_malloc(size_result);
SDL_snprintf(result, size_result, "%s=%s", key, env);
return result;
}
static char **DuplicateEnvironment(const char *key0, ...)
{
va_list ap;
size_t count = 1;
size_t i;
const char *keyN;
SDL_Environment *env = SDL_GetEnvironment();
SDL_Environment *new_env = SDL_CreateEnvironment(SDL_TRUE);
char **result;
if (key0) {
if (SDL_strchr(key0, '=') || SDL_getenv(key0)) {
count += 1;
char *sep = SDL_strchr(key0, '=');
if (sep) {
*sep = '\0';
SDL_SetEnvironmentVariable(new_env, key0, sep + 1, SDL_TRUE);
*sep = '=';
SDL_SetEnvironmentVariable(new_env, key0, sep, SDL_TRUE);
} else {
SDL_SetEnvironmentVariable(new_env, key0, SDL_GetEnvironmentVariable(env, key0), SDL_TRUE);
}
va_start(ap, key0);
for (;;) {
keyN = va_arg(ap, const char *);
if (keyN) {
if (SDL_strchr(keyN, '=') || SDL_getenv(keyN)) {
count += 1;
sep = SDL_strchr(keyN, '=');
if (sep) {
*sep = '\0';
SDL_SetEnvironmentVariable(new_env, keyN, sep + 1, SDL_TRUE);
*sep = '=';
} else {
SDL_SetEnvironmentVariable(new_env, keyN, SDL_GetEnvironmentVariable(env, keyN), SDL_TRUE);
}
} else {
break;
@ -76,45 +72,11 @@ static char **DuplicateEnvironment(const char *key0, ...)
va_end(ap);
}
result = SDL_calloc(count, sizeof(char *));
i = 0;
if (key0) {
if (SDL_strchr(key0, '=')) {
result[i++] = SDL_strdup(key0);
} else if (SDL_getenv(key0)) {
result[i++] = env_key_val_string(key0);
}
va_start(ap, key0);
for (;;) {
keyN = va_arg(ap, const char *);
if (keyN) {
if (SDL_strchr(keyN, '=')) {
result[i++] = SDL_strdup(keyN);
} else if (SDL_getenv(keyN)) {
result[i++] = env_key_val_string(keyN);
}
} else {
break;
}
}
va_end(ap);
}
result = SDL_GetEnvironmentVariables(new_env);
SDL_DestroyEnvironment(new_env);
return result;
}
static void DestroyEnvironment(char **environment) {
char **envp;
if (!environment) {
return;
}
for (envp = environment; *envp; envp++) {
SDL_free(*envp);
}
SDL_free(environment);
}
static int SDLCALL process_testArguments(void *arg)
{
TestProcessData *data = (TestProcessData *)arg;
@ -187,7 +149,7 @@ static int SDLCALL process_testInheritedEnv(void *arg)
test_env_val = SDLTest_RandomAsciiStringOfSize(32);
SDLTest_AssertPass("Setting parent environment variable %s=%s", TEST_ENV_KEY, test_env_val);
SDL_setenv(TEST_ENV_KEY, test_env_val, 1);
SDL_SetEnvironmentVariable(SDL_GetEnvironment(), TEST_ENV_KEY, test_env_val, SDL_TRUE);
SDL_snprintf(buffer, sizeof(buffer), "%s=%s", TEST_ENV_KEY, test_env_val);
process_args[3] = buffer;
@ -312,13 +274,14 @@ static int SDLCALL process_testNewEnv(void *arg)
SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
SDLTest_AssertPass("About to destroy process");
SDL_DestroyProcess(process);
DestroyEnvironment(process_env);
SDL_free(process_env);
SDL_free(test_env_val);
return TEST_COMPLETED;
failed:
SDL_free(test_env_val);
SDL_DestroyProcess(process);
DestroyEnvironment(process_env);
SDL_free(process_env);
return TEST_ABORTED;
}
@ -330,7 +293,6 @@ static int process_testStdinToStdout(void *arg)
"--stdin-to-stdout",
NULL,
};
const char **process_env = NULL;
SDL_PropertiesID props;
SDL_Process *process = NULL;
Sint64 pid;
@ -346,7 +308,6 @@ static int process_testStdinToStdout(void *arg)
props = SDL_CreateProperties();
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, (void *)process_env);
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_APP);
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
process = SDL_CreateProcessWithProperties(props);

View File

@ -223,7 +223,7 @@ int main(int argc, char *argv[])
SDL_Log("Playing %d Hz test tone on channel: %s\n", sine_freq, get_channel_name(j, total_channels));
/* fill_buffer() will increment the active channel */
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) {
if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Delay(QUICK_TEST_TIME_MSEC);
} else {
SDL_Delay(CHANNEL_TEST_TIME_SEC * 1000);

View File

@ -127,7 +127,7 @@ int main(int argc, char *argv[])
return 1;
}
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) {
if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Log("Not running slower tests");
SDL_Quit();
return 0;

View File

@ -124,7 +124,7 @@ int main(int argc, char *argv[])
return 1;
}
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) {
if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Log("Not running slower tests");
SDL_Quit();
return 0;