From d6294fa22b88187e44391c1c8ca64b1ebdf14533 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Tue, 12 Feb 2019 20:11:44 +0000 Subject: [PATCH] Revert the env object because it's broken portability - please redo setenv and unsetenv are not portable. i explained to you at fosdem there are issues and it's why i used putenv in the original implementation and even though it's a pain (the string tou pass to putenv is a pointer used literallt from there on in and you get it from getenv, thus making ownership a pain -this is a libc issue we can't readily solve). use putenv like the original code. then put it back in. vtorri now has windows porting issues with the setenv use. i knew there was a reason that still existed... in addition your in_sync stuff is broken. psuedocode: // assuming BLAGH env is not set to anything here c = efl_core_env_get(global_env, "BLAH"); ... putenv("BLAH=10"); ... c = efl_core_env_Get(global_env, "BLAH"); i will get NULL in both cases for c ... but i should get "10" for the 2nd in reality. reality is lots of code across application code and libraries will at times mess with the environment. it has to work with this. the prior implementation did work with this. Revert "ecore: here comes a env object" This reverts commit 2373d5db5b4cd5dfe139aa2a10017ef61b28b5ce. Revert "efl_task: remove env from this object" This reverts commit c3d69f66a69c0def357a5c373a13343e1c01ff5d. --- header_checks/meson.build | 3 +- meson.build | 1 - src/Makefile_Ecore.am | 7 +- src/lib/ecore/Ecore_Eo.h | 3 - src/lib/ecore/ecore_private.h | 1 + src/lib/ecore/efl_core_env.c | 2 +- src/lib/ecore/efl_core_env.eo | 57 --------- src/lib/ecore/efl_core_proc_env.c | 145 ---------------------- src/lib/ecore/efl_core_proc_env.eo | 21 ---- src/lib/ecore/efl_exe.c | 67 ++++------ src/lib/ecore/efl_exe.eo | 17 --- src/lib/ecore/efl_loop.c | 189 +++++++++++++++++++++++++++++ src/lib/ecore/efl_loop.eo | 2 + src/lib/ecore/efl_task.c | 62 +++++++++- src/lib/ecore/efl_task.eo | 20 +++ src/lib/ecore/meson.build | 6 +- src/tests/ecore/efl_app_suite.c | 2 +- src/tests/ecore/efl_app_suite.h | 1 - src/tests/ecore/efl_app_test_env.c | 135 --------------------- src/tests/ecore/meson.build | 3 +- 20 files changed, 305 insertions(+), 439 deletions(-) delete mode 100644 src/lib/ecore/efl_core_env.eo delete mode 100644 src/lib/ecore/efl_core_proc_env.c delete mode 100644 src/lib/ecore/efl_core_proc_env.eo delete mode 100644 src/tests/ecore/efl_app_test_env.c diff --git a/header_checks/meson.build b/header_checks/meson.build index 066d228a83..b23e774ec1 100644 --- a/header_checks/meson.build +++ b/header_checks/meson.build @@ -53,8 +53,7 @@ header_checks = [ 'langinfo.h', 'locale.h', 'uv.h', - 'ws2tcpip.h', - 'crt_externs.h' + 'ws2tcpip.h' ] function_checks = [ diff --git a/meson.build b/meson.build index d6b9b6074d..0e2a50c2c9 100644 --- a/meson.build +++ b/meson.build @@ -210,7 +210,6 @@ elif sys_osx == true sys_lib_extension = 'dylib' sys_exe_extension = '' sys_mod_extension = 'dylib' - config_h.set('environ', '(*_NSGetEnviron())') else error('System '+host_machine.system()+' not known') endif diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am index 5f10ea7f2e..7bc8e43b74 100644 --- a/src/Makefile_Ecore.am +++ b/src/Makefile_Ecore.am @@ -49,9 +49,7 @@ ecore_eolian_files_public = \ lib/ecore/efl_boolean_model.eo \ lib/ecore/efl_select_model.eo \ lib/ecore/efl_composite_model.eo \ - lib/ecore/efl_view_model.eo \ - lib/ecore/efl_core_env.eo \ - lib/ecore/efl_core_proc_env.eo \ + lib/ecore/efl_view_model.eo ecore_eolian_files = \ $(ecore_eolian_files_legacy) \ @@ -100,8 +98,6 @@ lib/ecore/ecore_job.c \ lib/ecore/ecore_main.c \ lib/ecore/ecore_event_message.c \ lib/ecore/ecore_event_message_handler.c \ -lib/ecore/efl_core_env.c \ -lib/ecore/efl_core_proc_env.c \ lib/ecore/efl_app.c \ lib/ecore/efl_loop.c \ lib/ecore/efl_loop_consumer.c \ @@ -339,7 +335,6 @@ tests/ecore/efl_app_test_loop.c \ tests/ecore/efl_app_test_loop_fd.c \ tests/ecore/efl_app_test_loop_timer.c \ tests/ecore/efl_app_test_promise.c \ -tests/ecore/efl_app_test_env.c \ tests/ecore/efl_app_suite.c \ tests/ecore/efl_app_suite.h diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h index 348b0f5b6d..6a21ff5ea7 100644 --- a/src/lib/ecore/Ecore_Eo.h +++ b/src/lib/ecore/Ecore_Eo.h @@ -26,9 +26,6 @@ * @{ */ -#include "efl_core_env.eo.h" -#include "efl_core_proc_env.eo.h" - #include "efl_loop_message.eo.h" #include "efl_loop_message_handler.eo.h" diff --git a/src/lib/ecore/ecore_private.h b/src/lib/ecore/ecore_private.h index 4e980d9123..c29f73d189 100644 --- a/src/lib/ecore/ecore_private.h +++ b/src/lib/ecore/ecore_private.h @@ -188,6 +188,7 @@ struct _Efl_Task_Data { Eina_Stringshare *command; Eina_Array *args; + Eina_Hash *env; Efl_Task_Priority priority; int exit_code; Efl_Task_Flags flags; diff --git a/src/lib/ecore/efl_core_env.c b/src/lib/ecore/efl_core_env.c index e0ee5a25e3..38fc9ba1a9 100644 --- a/src/lib/ecore/efl_core_env.c +++ b/src/lib/ecore/efl_core_env.c @@ -26,7 +26,7 @@ key_valid(const char *key) { if (!key || key[0] == '\0') return EINA_FALSE; - if (isdigit(key[0])) return EINA_FALSE; + if isdigit(key[0]) return EINA_FALSE; for (int i = 0; key[i] != '\0'; ++i) { if (!isalnum(key[i]) && key[i] != '_') return EINA_FALSE; diff --git a/src/lib/ecore/efl_core_env.eo b/src/lib/ecore/efl_core_env.eo deleted file mode 100644 index 86da8c14ff..0000000000 --- a/src/lib/ecore/efl_core_env.eo +++ /dev/null @@ -1,57 +0,0 @@ -class Efl.Core.Env extends Efl.Object implements Efl.Duplicate { - [[This object can maintain a set of key value pairs - - A object of this type alone does not apply the object to the system. - For getting the value into the system, see @Efl.Core.Proc_Env. - - A object can be forked, which will only copy its values, changes to the returned object will not change the object where it is forked off. - ]] - methods { - @property env { - [[ Stored var value pairs of this object. - - Var must contain only: underscores ('_'), letters ('a-z', 'A-Z'), - numbers ('0-9'), but the first character may not be a number. - ]] - set { - [[ Add a new pair to this object ]] - } - get { - [[ Get the value of the $var, or $null if no such $var exists in the object]] - } - keys { - var: string; [[ The name of the variable ]] - } - values { - value: string; [[ Set var to this value if not $NULL, - otherwise clear this env value if value - is $NULL or if it is an empty string ]] - } - } - unset { - [[ Remove the pair with the matching $var from this object]] - params { - var : string; [[ The name of the variable ]] - } - } - clear { - [[ Remove all pairs from this object]] - } - @property content { - [[ Get the content of this object. - - This will return a iterator that contains all keys that are part of this object. - ]] - get { - - } - values { - iter : iterator; - } - } - } - implements { - Efl.Object.constructor; - Efl.Duplicate.duplicate; - } -} diff --git a/src/lib/ecore/efl_core_proc_env.c b/src/lib/ecore/efl_core_proc_env.c deleted file mode 100644 index 846b69a350..0000000000 --- a/src/lib/ecore/efl_core_proc_env.c +++ /dev/null @@ -1,145 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#ifdef HAVE_CRT_EXTERNS_H -# include -#endif -#include "ecore_private.h" - -#define MY_CLASS EFL_CORE_PROC_ENV_CLASS - -static Efl_Core_Env *env = NULL; - -typedef struct { - Eina_Bool in_sync; -} Efl_Core_Proc_Env_Data; - -static void -_sync(Efl_Core_Env *obj, Efl_Core_Proc_Env_Data *pd) -{ - Eina_List *existing_keys = NULL, *n; - Eina_Iterator *content; - const char *key; - - pd->in_sync = EINA_TRUE; - content = efl_core_env_content_get(obj); - - EINA_ITERATOR_FOREACH(content, key) - { - existing_keys = eina_list_append(existing_keys, key); - } - - if (environ) - { - char **p; - - for (p = environ; *p; p++) - { - char **values; - - values = eina_str_split(*p, "=", 2); - efl_core_env_set(obj, values[0], values[1]); - - EINA_LIST_FOREACH(existing_keys, n, key) - { - if (!strcmp(key, values[0])) - { - existing_keys = eina_list_remove_list(existing_keys, n); - break; - } - } - } - } - EINA_LIST_FOREACH(existing_keys, n, key) - { - efl_core_env_unset(obj, key); - } - pd->in_sync = EINA_FALSE; -} - -EOLIAN static const char* -_efl_core_proc_env_efl_core_env_env_get(const Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *var) -{ - if (!pd->in_sync) - _sync((Eo*)obj, pd); - return efl_core_env_get(efl_super(obj, MY_CLASS), var); -} - -EOLIAN static void -_efl_core_proc_env_efl_core_env_env_set(Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *var, const char *value) -{ - efl_core_env_set(efl_super(obj, MY_CLASS), var, value); - if (!pd->in_sync) - { - if (value) - setenv(var, value, 1); - else - unsetenv(var); - } -} - -EOLIAN static void -_efl_core_proc_env_efl_core_env_unset(Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *key) -{ - efl_core_env_unset(efl_super(obj, MY_CLASS), key); - if (!pd->in_sync) - { - unsetenv(key); - } -} - -EOLIAN static void -_efl_core_proc_env_efl_core_env_clear(Eo *obj, Efl_Core_Proc_Env_Data *pd) -{ - efl_core_env_clear(efl_super(obj, MY_CLASS)); - if (!pd->in_sync) - { -#ifdef HAVE_CLEARENV - clearenv(); -#else - environ = NULL; -#endif - } -} - - -EOLIAN static Efl_Duplicate* -_efl_core_proc_env_efl_duplicate_duplicate(const Eo *obj, Efl_Core_Proc_Env_Data *pd) -{ - if (!pd->in_sync) - _sync((Eo*) obj, pd); - return efl_duplicate(efl_super(obj, MY_CLASS)); -} - -EOLIAN static Eina_Iterator* -_efl_core_proc_env_efl_core_env_content_get(const Eo *obj, Efl_Core_Proc_Env_Data *pd) -{ - if (!pd->in_sync) - _sync((Eo*) obj, pd); - return efl_core_env_content_get(efl_super(obj, MY_CLASS)); -} - -EOLIAN static Efl_Object* -_efl_core_proc_env_efl_object_constructor(Eo *obj, Efl_Core_Proc_Env_Data *pd EINA_UNUSED) -{ - EINA_SAFETY_ON_TRUE_RETURN_VAL(!!env, NULL); - - obj = efl_constructor(efl_super(obj, MY_CLASS)); - return obj; -} - -EOLIAN static Efl_Core_Env* -_efl_core_proc_env_self(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED) -{ - if (!env) - { - env = efl_add_ref(EFL_CORE_PROC_ENV_CLASS, NULL); - efl_wref_add(env, &env); - } - - return env; -} - -#include "efl_core_proc_env.eo.c" diff --git a/src/lib/ecore/efl_core_proc_env.eo b/src/lib/ecore/efl_core_proc_env.eo deleted file mode 100644 index 23c2c67d75..0000000000 --- a/src/lib/ecore/efl_core_proc_env.eo +++ /dev/null @@ -1,21 +0,0 @@ -class Efl.Core.Proc_Env extends Efl.Core.Env -{ - eo_prefix : efl_env; - methods { - self @class { - [[Get a instance of this object - - The object will apply the environment operations onto this process. - ]] - return : Efl.Core.Env; - } - } - implements { - Efl.Core.Env.env { set; get; } - Efl.Core.Env.content { get; } - Efl.Core.Env.unset; - Efl.Core.Env.clear; - Efl.Duplicate.duplicate; - Efl.Object.constructor; - } -} diff --git a/src/lib/ecore/efl_exe.c b/src/lib/ecore/efl_exe.c index 4b3bc658d6..a6f9f5f506 100644 --- a/src/lib/ecore/efl_exe.c +++ b/src/lib/ecore/efl_exe.c @@ -40,7 +40,6 @@ typedef struct _Efl_Exe_Data Efl_Exe_Data; struct _Efl_Exe_Data { - Efl_Core_Env *env; int exit_signal; Efl_Exe_Flags flags; #ifdef _WIN32 @@ -166,6 +165,22 @@ _exec(const char *cmd, Efl_Exe_Flags flags) } } +static Eina_Bool +_foreach_env(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata EINA_UNUSED) +{ + int keylen; + char *buf, *s; + + if (!data) return EINA_TRUE; + keylen = strlen(key); + buf = alloca(keylen + 1 + strlen(data) + 1); + strcpy(buf, key); + buf[keylen] = '='; + strcpy(buf + keylen + 1, data); + if ((s = strdup(buf))) putenv(s); + return EINA_TRUE; +} + static void _exe_exit_eval(Eo *obj, Efl_Exe_Data *pd) { @@ -191,7 +206,7 @@ _exe_exit_eval(Eo *obj, Efl_Exe_Data *pd) // 128+n Fatal error signal "n" kill -9 $PPID $? returns 137 (128 + 9) // 130 Script terminated by Control-C Ctl-C Control-C is fatal error signal 2, (130 = 128 + 2, see above) // 255* Exit status out of range exit -1 exit takes only integer args in the range 0 - 255 - // + // // According to the above table, exit codes 1 - 2, // 126 - 165, and 255 [1] have special meanings, and // should therefore be avoided for user-specified exit @@ -285,25 +300,6 @@ _run_clean_cb(Efl_Loop_Consumer *consumer EINA_UNUSED, ////////////////////////////////////////////////////////////////////////// - -EOLIAN static void -_efl_exe_env_set(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Core_Env *env) -{ - if (pd->env == env) return; - - if (!pd->env) - efl_unref(pd->env); - pd->env = env; - if (pd->env) - efl_ref(pd->env); -} - -EOLIAN static Efl_Core_Env* -_efl_exe_env_get(const Eo *obj EINA_UNUSED, Efl_Exe_Data *pd) -{ - return pd->env; -} - EOLIAN static void _efl_exe_signal(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Exe_Signal sig) { @@ -568,28 +564,17 @@ _efl_exe_efl_task_run(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd) // clear systemd notify socket... only relevant for systemd world, // otherwise shouldn't be trouble putenv("NOTIFY_SOCKET="); + // force the env hash to update from env vars + efl_task_env_get(loop, "HOME"); - // actually setenv the env object (clear what was there before so it is + // actually setenv the env hash (clear what was there before so it is // the only env there) - if (pd->env) - { - Eina_Iterator *itr; - const char *key; - - #ifdef HAVE_CLEARENV - clearenv(); - #else - environ = NULL; - #endif - itr = efl_core_env_content_get(pd->env); - - EINA_ITERATOR_FOREACH(itr, key) - { - setenv(key, efl_core_env_get(pd->env, key) , 1); - } - efl_unref(pd->env); - pd->env = NULL; - } +#ifdef HAVE_CLEARENV + clearenv(); +#else + environ = NULL; +#endif + eina_hash_foreach(td->env, _foreach_env, NULL); // actually execute! _exec(cmd, pd->flags); diff --git a/src/lib/ecore/efl_exe.eo b/src/lib/ecore/efl_exe.eo index 111814af21..d0d0cb585e 100644 --- a/src/lib/ecore/efl_exe.eo +++ b/src/lib/ecore/efl_exe.eo @@ -42,23 +42,6 @@ class Efl.Exe extends Efl.Task implements Efl.Io.Reader, Efl.Io.Writer, Efl.Io.C sig: int; [[ The exit signal, or -1 if no exit signal happened ]] } } - @property env { - [[ If $env is $null then the process created by this object is - going to inherit the enviroment of this process. - - In case $env is not $null then the environment variables declared - in this object will represent the environment passed to the new process. - ]] - get { - [[ Get the object assosiated with this object ]] - } - set { - [[ Set the object assosiated with this object ]] - } - values { - env : Efl.Core.Env; [[$env will be referenced until this object does not need it anymore.]] - } - } } implements { Efl.Object.constructor; diff --git a/src/lib/ecore/efl_loop.c b/src/lib/ecore/efl_loop.c index 68f9573b76..44e9c872c9 100644 --- a/src/lib/ecore/efl_loop.c +++ b/src/lib/ecore/efl_loop.c @@ -15,6 +15,8 @@ #include "ecore_main_common.h" +extern char **environ; + typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data; typedef struct _Efl_Internal_Promise Efl_Internal_Promise; @@ -51,6 +53,11 @@ _efl_loop_message_handler_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Loo Eo *_mainloop_singleton = NULL; Efl_Loop_Data *_mainloop_singleton_data = NULL; +extern Eina_Lock _environ_lock; +static Eina_List *_environ_strings_set = NULL; + +static void _clean_old_environ(void); + EAPI Eo * efl_main_loop_get(void) { @@ -347,6 +354,16 @@ _efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd) { pd->future_message_handler = NULL; + eina_lock_take(&_environ_lock); + _clean_old_environ(); + _environ_strings_set = eina_list_free(_environ_strings_set); + pd->env.environ_ptr = NULL; + free(pd->env.environ_copy); + pd->env.environ_copy = NULL; + eina_lock_release(&_environ_lock); + + eina_value_flush(&pd->exit_code); + efl_destructor(efl_super(obj, EFL_LOOP_CLASS)); } @@ -657,6 +674,178 @@ efl_build_version_set(int vmaj, int vmin, int vmic, int revision, _app_efl_version.build_id = build_id ? strdup(build_id) : NULL; } +static void +_env_sync(Efl_Loop_Data *pd, Efl_Task_Data *td) +{ + Eina_Bool update = EINA_FALSE; + unsigned int count = 0, i; + char **p; + + // count environs + if (environ) + { + for (p = environ; *p; p++) count++; + } + // cached env ptr is the same... so look deeper if things changes + if (pd->env.environ_ptr == environ) + { + // if we have no cached copy then update + if (!pd->env.environ_copy) update = EINA_TRUE; + else + { + // if any ptr in the cached copy doesnt match environ ptr + // then update + for (i = 0; i <= count; i++) + { + if (pd->env.environ_copy[i] != environ[i]) + { + update = EINA_TRUE; + break; + } + } + } + } + // cached env ptr changed so we need to update anyway + else update = EINA_TRUE; + if (!update) return; + // things changed - do the update + pd->env.environ_ptr = environ; + free(pd->env.environ_copy); + pd->env.environ_copy = NULL; + if (count > 0) + { + pd->env.environ_copy = malloc((count + 1) * sizeof(char *)); + if (pd->env.environ_copy) + { + for (i = 0; i <= count; i++) + pd->env.environ_copy[i] = environ[i]; + } + } + // clear previous env hash and rebuild it from environ so it matches + if (td->env) eina_hash_free(td->env); + td->env = eina_hash_string_superfast_new + ((Eina_Free_Cb)eina_stringshare_del); + for (i = 0; i < count; i++) + { + char *var; + const char *value; + + if (!environ[i]) continue; + if ((value = strchr(environ[i], '='))) + { + if (*value) + { + if ((var = malloc(value - environ[i] + 1))) + { + strncpy(var, environ[i], value - environ[i]); + var[value - environ[i]] = 0; + value++; + eina_hash_add(td->env, var, + eina_stringshare_add(value)); + free(var); + } + } + } + } +} + +static void +_clean_old_environ(void) +{ + char **p; + const char *str; + Eina_List *l, *ll; + Eina_Bool ok; + + // clean up old strings no longer in environ + EINA_LIST_FOREACH_SAFE(_environ_strings_set, l, ll, str) + { + ok = EINA_FALSE; + for (p = environ; *p; p++) + { + if (*p == str) + { + ok = EINA_TRUE; + break; + } + } + if (!ok) + { + _environ_strings_set = + eina_list_remove_list(_environ_strings_set, l); + eina_stringshare_del(str); + } + } +} + +EOLIAN static void +_efl_loop_efl_task_env_set(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, const char *var, const char *value) +{ + char *str, *str2; + size_t varlen, vallen = 0; + + if (!var) return; + + Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS); + if (!td) return; + + varlen = strlen(var); + if (value) vallen = strlen(value); + + str = malloc(varlen + 1 + vallen + 1); + if (!str) return; + strcpy(str, var); + str[varlen] = '='; + if (value) strcpy(str + varlen + 1, value); + else str[varlen + 1] = 0; + + str2 = (char *)eina_stringshare_add(str); + free(str); + if (!str2) return; + + eina_lock_take(&_environ_lock); + if (putenv(str2) != 0) + { + eina_stringshare_del(str2); + eina_lock_release(&_environ_lock); + return; + } + _environ_strings_set = eina_list_append(_environ_strings_set, str2); + eina_lock_release(&_environ_lock); + + efl_task_env_set(efl_super(obj, EFL_LOOP_CLASS), var, value); + + eina_lock_take(&_environ_lock); + _clean_old_environ(); + eina_lock_release(&_environ_lock); +} + +EOLIAN static const char * +_efl_loop_efl_task_env_get(const Eo *obj, Efl_Loop_Data *pd, const char *var) +{ + Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS); + if (!td) return NULL; + eina_lock_take(&_environ_lock); + _env_sync(pd, td); + eina_lock_release(&_environ_lock); + return efl_task_env_get(efl_super(obj, EFL_LOOP_CLASS), var); +} + +EOLIAN static void +_efl_loop_efl_task_env_reset(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd) +{ + Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS); + if (!td) return; + eina_lock_take(&_environ_lock); +#ifdef HAVE_CLEARENV + clearenv(); +#else + environ = NULL; +#endif + _env_sync(pd, td); + eina_lock_release(&_environ_lock); +} + EOLIAN static Eina_Future * _efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) { diff --git a/src/lib/ecore/efl_loop.eo b/src/lib/ecore/efl_loop.eo index 7480eee867..fe9cbd9a5d 100644 --- a/src/lib/ecore/efl_loop.eo +++ b/src/lib/ecore/efl_loop.eo @@ -125,6 +125,8 @@ class Efl.Loop extends Efl.Task Efl.Object.invalidate; Efl.Object.destructor; Efl.Object.provider_find; + Efl.Task.env { set; get; } + Efl.Task.env_reset; Efl.Task.run; Efl.Task.end; } diff --git a/src/lib/ecore/efl_task.c b/src/lib/ecore/efl_task.c index 311de0506a..6442669efd 100644 --- a/src/lib/ecore/efl_task.c +++ b/src/lib/ecore/efl_task.c @@ -227,6 +227,19 @@ _rebuild_command(Efl_Task_Data *pd) eina_strbuf_free(sb); } + +static Eina_Bool +_foreach_env_copy(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata) +{ + if (data) + { + // only copy env vars not already set + if (!eina_hash_find(fdata, key)) + eina_hash_add(fdata, key, eina_stringshare_add(data)); + } + return EINA_TRUE; +} + ////////////////////////////////////////////////////////////////////////// EOLIAN static void @@ -309,6 +322,34 @@ _efl_task_arg_reset(Eo *obj EINA_UNUSED, Efl_Task_Data *pd) pd->command_dirty = EINA_TRUE; } +EOLIAN static void +_efl_task_env_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *var, const char *value) +{ + if (!var) return; + if (!pd->env) + pd->env = eina_hash_string_superfast_new + ((Eina_Free_Cb)eina_stringshare_del); + if (!pd->env) return; + if ((value) && (*value)) + eina_hash_add(pd->env, var, eina_stringshare_add(value)); + else eina_hash_del(pd->env, var, NULL); +} + + +EOLIAN static const char * +_efl_task_env_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *var) +{ + if ((!var) || (!pd->env)) return NULL; + return eina_hash_find(pd->env, var); +} + +EOLIAN static void +_efl_task_env_reset(Eo *obj EINA_UNUSED, Efl_Task_Data *pd) +{ + if (pd->env) eina_hash_free(pd->env); + pd->env = NULL; +} + EOLIAN static void _efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Priority priority) { @@ -345,13 +386,32 @@ _efl_task_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Task_Data *pd) eina_stringshare_del(pd->command); pd->command = NULL; _clear_args(pd); + if (pd->env) eina_hash_free(pd->env); + pd->env = NULL; efl_destructor(efl_super(obj, MY_CLASS)); } EOLIAN static void -_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd EINA_UNUSED, Efl_Object *parent) +_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd, Efl_Object *parent) { + Eo *loop; + efl_parent_set(efl_super(obj, MY_CLASS), parent); + // copy loop env into exe task env, if not already set in env (overridden) + loop = efl_provider_find(parent, EFL_LOOP_CLASS); + if (loop) + { + Efl_Task_Data *tdl = efl_data_scope_get(loop, EFL_TASK_CLASS); + + if (tdl) + { + if (!pd->env) + pd->env = eina_hash_string_superfast_new + ((Eina_Free_Cb)eina_stringshare_del); + if (tdl->env) + eina_hash_foreach(tdl->env, _foreach_env_copy, pd->env); + } + } } ////////////////////////////////////////////////////////////////////////// diff --git a/src/lib/ecore/efl_task.eo b/src/lib/ecore/efl_task.eo index 526746ff60..92f0094fef 100644 --- a/src/lib/ecore/efl_task.eo +++ b/src/lib/ecore/efl_task.eo @@ -96,6 +96,26 @@ abstract Efl.Task extends Efl.Object [[ Clear all arguments in arg_value/count set. Will result in the command property also being cleared. ]] } + @property env { + [[ The environment to be passed in or that was passed to the + task. This is a string key, value list which map to environment + variables where appropriate. The var string must contain + only an underscore ('_'), letters ('a-z', 'A-Z'), + numbers ('0-9'), but the first character may not be a number.]] + set { } + get { } + keys { + var: string; [[ The variable name as a string ]] + } + values { + value: string; [[ Set var to this value if not $NULL, + otherwise clear this env value if value + is $NULL or if it is an empty string ]] + } + } + env_reset { + [[ Clear all environment variables. ]] + } @property priority { [[ The priority of this task. ]] get { } diff --git a/src/lib/ecore/meson.build b/src/lib/ecore/meson.build index 98909cb618..baa5263698 100644 --- a/src/lib/ecore/meson.build +++ b/src/lib/ecore/meson.build @@ -74,9 +74,7 @@ pub_eo_files = [ 'efl_boolean_model.eo', 'efl_select_model.eo', 'efl_composite_model.eo', - 'efl_view_model.eo', - 'efl_core_env.eo', - 'efl_core_proc_env.eo' + 'efl_view_model.eo' ] foreach eo_file : pub_eo_files @@ -182,8 +180,6 @@ ecore_src = [ 'efl_thread.c', 'efl_threadio.c', 'efl_appthread.c', - 'efl_core_env.c', - 'efl_core_proc_env.c', ] if sys_windows == true diff --git a/src/tests/ecore/efl_app_suite.c b/src/tests/ecore/efl_app_suite.c index cd26e2d95e..b3be09915a 100644 --- a/src/tests/ecore/efl_app_suite.c +++ b/src/tests/ecore/efl_app_suite.c @@ -9,6 +9,7 @@ #include "efl_app_suite.h" #include "../efl_check.h" + EFL_START_TEST(efl_app_test_efl_build_version) { const Efl_Version *ver; @@ -52,7 +53,6 @@ static const Efl_Test_Case etc[] = { { "Promise", efl_app_test_promise_2 }, { "Promise", efl_app_test_promise_3 }, { "Promise", efl_app_test_promise_safety }, - { "Env", efl_test_efl_env }, { NULL, NULL } }; diff --git a/src/tests/ecore/efl_app_suite.h b/src/tests/ecore/efl_app_suite.h index 3a66dcdfcf..29ed8f031f 100644 --- a/src/tests/ecore/efl_app_suite.h +++ b/src/tests/ecore/efl_app_suite.h @@ -11,6 +11,5 @@ void efl_app_test_promise(TCase *tc); void efl_app_test_promise_2(TCase *tc); void efl_app_test_promise_3(TCase *tc); void efl_app_test_promise_safety(TCase *tc); -void efl_test_efl_env(TCase *tc); #endif /* _EFL_APP_SUITE_H */ diff --git a/src/tests/ecore/efl_app_test_env.c b/src/tests/ecore/efl_app_test_env.c deleted file mode 100644 index 63bad166a2..0000000000 --- a/src/tests/ecore/efl_app_test_env.c +++ /dev/null @@ -1,135 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#define EFL_NOLEGACY_API_SUPPORT -#include -#include "efl_app_suite.h" -#include "../efl_check.h" - -EFL_START_TEST(efl_core_env_test_set_get) -{ - Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL); - - efl_core_env_set(env, "FOO", "bar"); - efl_core_env_set(env, "going", "home"); - efl_core_env_set(env, "Merry", "christmas"); - - ck_assert_str_eq(efl_core_env_get(env, "FOO"), "bar"); - ck_assert_str_eq(efl_core_env_get(env, "going"), "home"); - ck_assert_str_eq(efl_core_env_get(env, "Merry"), "christmas"); - - efl_core_env_unset(env, "Merry"); - - ck_assert_str_eq(efl_core_env_get(env, "FOO"), "bar"); - ck_assert_str_eq(efl_core_env_get(env, "going"), "home"); - ck_assert_ptr_eq(efl_core_env_get(env, "Merry"), NULL); - - efl_unref(env); -} -EFL_END_TEST - -EFL_START_TEST(efl_core_env_test_invalid_keys) -{ - Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL); - -#define CHECK(val) \ - efl_core_env_set(env, val, "TEST"); \ - ck_assert_ptr_eq(efl_core_env_get(env, val), NULL); - - CHECK("0foo"); - CHECK("foo bar"); - CHECK("foo!bar"); - -#undef CHECK - - -#define CHECK(val) \ - efl_core_env_set(env, val, "TEST"); \ - ck_assert_str_eq(efl_core_env_get(env, val), "TEST"); - - CHECK("foo0"); - CHECK("foo_bar"); - -#undef CHECK - -} -EFL_END_TEST - -EFL_START_TEST(efl_core_env_test_clear) -{ - Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL); - - efl_core_env_set(env, "FOO", "bar"); - efl_core_env_set(env, "going", "home"); - efl_core_env_set(env, "Merry", "christmas"); - - efl_core_env_clear(env); - - ck_assert_ptr_eq(efl_core_env_get(env, "FOO"), NULL); - ck_assert_ptr_eq(efl_core_env_get(env, "going"), NULL); - ck_assert_ptr_eq(efl_core_env_get(env, "Merry"), NULL); - - efl_unref(env); -} -EFL_END_TEST - -EFL_START_TEST(efl_core_env_test_fork) -{ - Efl_Core_Env *env_fork, *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL); - - efl_core_env_set(env, "FOO", "bar"); - efl_core_env_set(env, "going", "home"); - efl_core_env_set(env, "Merry", "christmas"); - - env_fork = efl_duplicate(env); - - ck_assert_str_eq(efl_core_env_get(env_fork, "FOO"), "bar"); - ck_assert_str_eq(efl_core_env_get(env_fork, "going"), "home"); - ck_assert_str_eq(efl_core_env_get(env_fork, "Merry"), "christmas"); - - efl_unref(env); -} -EFL_END_TEST - -EFL_START_TEST(efl_core_env_test_process) -{ - Efl_Core_Env *env_fork, *env = efl_env_self(EFL_CORE_PROC_ENV_CLASS); - - ck_assert(env); - - ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH")); - env_fork = efl_duplicate(env); - ck_assert_str_eq(efl_core_env_get(env_fork, "PATH"), getenv("PATH")); - - efl_unref(env); -} -EFL_END_TEST - -EFL_START_TEST(efl_core_env_test_undepend_fork) -{ - Efl_Core_Env *env_fork, *env = efl_env_self(EFL_CORE_PROC_ENV_CLASS); - - ck_assert(env); - - ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH")); - env_fork = efl_duplicate(env); - efl_core_env_set(env_fork, "PATH", "abc"); - ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH")); - - efl_unref(env); - efl_unref(env_fork); -} -EFL_END_TEST - -void efl_test_efl_env(TCase *tc) -{ - tcase_add_test(tc, efl_core_env_test_set_get); - tcase_add_test(tc, efl_core_env_test_invalid_keys); - tcase_add_test(tc, efl_core_env_test_clear); - tcase_add_test(tc, efl_core_env_test_fork); - tcase_add_test(tc, efl_core_env_test_process); - tcase_add_test(tc, efl_core_env_test_undepend_fork); -} diff --git a/src/tests/ecore/meson.build b/src/tests/ecore/meson.build index e3b4f6c851..4b46814bbe 100644 --- a/src/tests/ecore/meson.build +++ b/src/tests/ecore/meson.build @@ -75,8 +75,7 @@ efl_app_suite_src = [ 'efl_app_test_loop.c', 'efl_app_test_loop_fd.c', 'efl_app_test_loop_timer.c', - 'efl_app_test_promise.c', - 'efl_app_test_env.c' + 'efl_app_test_promise.c' ] efl_app_suite_deps = [m]