From 06160466e8c54fd31926f7102268a8a6afde537e Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Tue, 12 Feb 2019 21:34:27 +0100 Subject: [PATCH] Revert "Revert the env object because it's broken portability - please redo" This reverts commit d6294fa22b88187e44391c1c8ca64b1ebdf14533. --- 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, 439 insertions(+), 305 deletions(-) create mode 100644 src/lib/ecore/efl_core_env.eo create mode 100644 src/lib/ecore/efl_core_proc_env.c create mode 100644 src/lib/ecore/efl_core_proc_env.eo create mode 100644 src/tests/ecore/efl_app_test_env.c diff --git a/header_checks/meson.build b/header_checks/meson.build index b23e774ec1..066d228a83 100644 --- a/header_checks/meson.build +++ b/header_checks/meson.build @@ -53,7 +53,8 @@ header_checks = [ 'langinfo.h', 'locale.h', 'uv.h', - 'ws2tcpip.h' + 'ws2tcpip.h', + 'crt_externs.h' ] function_checks = [ diff --git a/meson.build b/meson.build index 0e2a50c2c9..d6b9b6074d 100644 --- a/meson.build +++ b/meson.build @@ -210,6 +210,7 @@ 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 7bc8e43b74..5f10ea7f2e 100644 --- a/src/Makefile_Ecore.am +++ b/src/Makefile_Ecore.am @@ -49,7 +49,9 @@ 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_view_model.eo \ + lib/ecore/efl_core_env.eo \ + lib/ecore/efl_core_proc_env.eo \ ecore_eolian_files = \ $(ecore_eolian_files_legacy) \ @@ -98,6 +100,8 @@ 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 \ @@ -335,6 +339,7 @@ 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 6a21ff5ea7..348b0f5b6d 100644 --- a/src/lib/ecore/Ecore_Eo.h +++ b/src/lib/ecore/Ecore_Eo.h @@ -26,6 +26,9 @@ * @{ */ +#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 c29f73d189..4e980d9123 100644 --- a/src/lib/ecore/ecore_private.h +++ b/src/lib/ecore/ecore_private.h @@ -188,7 +188,6 @@ 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 38fc9ba1a9..e0ee5a25e3 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 new file mode 100644 index 0000000000..86da8c14ff --- /dev/null +++ b/src/lib/ecore/efl_core_env.eo @@ -0,0 +1,57 @@ +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 new file mode 100644 index 0000000000..846b69a350 --- /dev/null +++ b/src/lib/ecore/efl_core_proc_env.c @@ -0,0 +1,145 @@ +#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 new file mode 100644 index 0000000000..23c2c67d75 --- /dev/null +++ b/src/lib/ecore/efl_core_proc_env.eo @@ -0,0 +1,21 @@ +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 a6f9f5f506..4b3bc658d6 100644 --- a/src/lib/ecore/efl_exe.c +++ b/src/lib/ecore/efl_exe.c @@ -40,6 +40,7 @@ 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 @@ -165,22 +166,6 @@ _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) { @@ -206,7 +191,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 @@ -300,6 +285,25 @@ _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) { @@ -564,17 +568,28 @@ _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 hash (clear what was there before so it is + // actually setenv the env object (clear what was there before so it is // the only env there) -#ifdef HAVE_CLEARENV - clearenv(); -#else - environ = NULL; -#endif - eina_hash_foreach(td->env, _foreach_env, NULL); + 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; + } // actually execute! _exec(cmd, pd->flags); diff --git a/src/lib/ecore/efl_exe.eo b/src/lib/ecore/efl_exe.eo index d0d0cb585e..111814af21 100644 --- a/src/lib/ecore/efl_exe.eo +++ b/src/lib/ecore/efl_exe.eo @@ -42,6 +42,23 @@ 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 44e9c872c9..68f9573b76 100644 --- a/src/lib/ecore/efl_loop.c +++ b/src/lib/ecore/efl_loop.c @@ -15,8 +15,6 @@ #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; @@ -53,11 +51,6 @@ _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) { @@ -354,16 +347,6 @@ _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)); } @@ -674,178 +657,6 @@ 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 fe9cbd9a5d..7480eee867 100644 --- a/src/lib/ecore/efl_loop.eo +++ b/src/lib/ecore/efl_loop.eo @@ -125,8 +125,6 @@ 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 6442669efd..311de0506a 100644 --- a/src/lib/ecore/efl_task.c +++ b/src/lib/ecore/efl_task.c @@ -227,19 +227,6 @@ _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 @@ -322,34 +309,6 @@ _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) { @@ -386,32 +345,13 @@ _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, Efl_Object *parent) +_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd EINA_UNUSED, 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 92f0094fef..526746ff60 100644 --- a/src/lib/ecore/efl_task.eo +++ b/src/lib/ecore/efl_task.eo @@ -96,26 +96,6 @@ 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 baa5263698..98909cb618 100644 --- a/src/lib/ecore/meson.build +++ b/src/lib/ecore/meson.build @@ -74,7 +74,9 @@ pub_eo_files = [ 'efl_boolean_model.eo', 'efl_select_model.eo', 'efl_composite_model.eo', - 'efl_view_model.eo' + 'efl_view_model.eo', + 'efl_core_env.eo', + 'efl_core_proc_env.eo' ] foreach eo_file : pub_eo_files @@ -180,6 +182,8 @@ 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 b3be09915a..cd26e2d95e 100644 --- a/src/tests/ecore/efl_app_suite.c +++ b/src/tests/ecore/efl_app_suite.c @@ -9,7 +9,6 @@ #include "efl_app_suite.h" #include "../efl_check.h" - EFL_START_TEST(efl_app_test_efl_build_version) { const Efl_Version *ver; @@ -53,6 +52,7 @@ 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 29ed8f031f..3a66dcdfcf 100644 --- a/src/tests/ecore/efl_app_suite.h +++ b/src/tests/ecore/efl_app_suite.h @@ -11,5 +11,6 @@ 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 new file mode 100644 index 0000000000..63bad166a2 --- /dev/null +++ b/src/tests/ecore/efl_app_test_env.c @@ -0,0 +1,135 @@ +#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 4b46814bbe..e3b4f6c851 100644 --- a/src/tests/ecore/meson.build +++ b/src/tests/ecore/meson.build @@ -75,7 +75,8 @@ 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_promise.c', + 'efl_app_test_env.c' ] efl_app_suite_deps = [m]