forked from enlightenment/efl
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 commit2373d5db5b
. Revert "efl_task: remove env from this object" This reverts commitc3d69f66a6
.
This commit is contained in:
parent
a57c7f7510
commit
d6294fa22b
|
@ -53,8 +53,7 @@ header_checks = [
|
|||
'langinfo.h',
|
||||
'locale.h',
|
||||
'uv.h',
|
||||
'ws2tcpip.h',
|
||||
'crt_externs.h'
|
||||
'ws2tcpip.h'
|
||||
]
|
||||
|
||||
function_checks = [
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<string>;
|
||||
}
|
||||
}
|
||||
}
|
||||
implements {
|
||||
Efl.Object.constructor;
|
||||
Efl.Duplicate.duplicate;
|
||||
}
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <Ecore.h>
|
||||
#ifdef HAVE_CRT_EXTERNS_H
|
||||
# include <crt_externs.h>
|
||||
#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"
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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 { }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#define EFL_NOLEGACY_API_SUPPORT
|
||||
#include <Efl_Core.h>
|
||||
#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);
|
||||
}
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue