summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2019-02-12 20:11:44 +0000
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2019-02-12 20:22:28 +0000
commitd6294fa22b88187e44391c1c8ca64b1ebdf14533 (patch)
tree793733796eda67fdbea1fde4c83023bf3fe7f579
parenta57c7f751023fe1d1edeabbf8683574ac7497e5e (diff)
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.
-rw-r--r--header_checks/meson.build3
-rw-r--r--meson.build1
-rw-r--r--src/Makefile_Ecore.am7
-rw-r--r--src/lib/ecore/Ecore_Eo.h3
-rw-r--r--src/lib/ecore/ecore_private.h1
-rw-r--r--src/lib/ecore/efl_core_env.c2
-rw-r--r--src/lib/ecore/efl_core_env.eo57
-rw-r--r--src/lib/ecore/efl_core_proc_env.c145
-rw-r--r--src/lib/ecore/efl_core_proc_env.eo21
-rw-r--r--src/lib/ecore/efl_exe.c67
-rw-r--r--src/lib/ecore/efl_exe.eo17
-rw-r--r--src/lib/ecore/efl_loop.c189
-rw-r--r--src/lib/ecore/efl_loop.eo2
-rw-r--r--src/lib/ecore/efl_task.c62
-rw-r--r--src/lib/ecore/efl_task.eo20
-rw-r--r--src/lib/ecore/meson.build6
-rw-r--r--src/tests/ecore/efl_app_suite.c2
-rw-r--r--src/tests/ecore/efl_app_suite.h1
-rw-r--r--src/tests/ecore/efl_app_test_env.c135
-rw-r--r--src/tests/ecore/meson.build3
20 files changed, 305 insertions, 439 deletions
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 = [
53 'langinfo.h', 53 'langinfo.h',
54 'locale.h', 54 'locale.h',
55 'uv.h', 55 'uv.h',
56 'ws2tcpip.h', 56 'ws2tcpip.h'
57 'crt_externs.h'
58] 57]
59 58
60function_checks = [ 59function_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
210 sys_lib_extension = 'dylib' 210 sys_lib_extension = 'dylib'
211 sys_exe_extension = '' 211 sys_exe_extension = ''
212 sys_mod_extension = 'dylib' 212 sys_mod_extension = 'dylib'
213 config_h.set('environ', '(*_NSGetEnviron())')
214else 213else
215 error('System '+host_machine.system()+' not known') 214 error('System '+host_machine.system()+' not known')
216endif 215endif
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 = \
49 lib/ecore/efl_boolean_model.eo \ 49 lib/ecore/efl_boolean_model.eo \
50 lib/ecore/efl_select_model.eo \ 50 lib/ecore/efl_select_model.eo \
51 lib/ecore/efl_composite_model.eo \ 51 lib/ecore/efl_composite_model.eo \
52 lib/ecore/efl_view_model.eo \ 52 lib/ecore/efl_view_model.eo
53 lib/ecore/efl_core_env.eo \
54 lib/ecore/efl_core_proc_env.eo \
55 53
56ecore_eolian_files = \ 54ecore_eolian_files = \
57 $(ecore_eolian_files_legacy) \ 55 $(ecore_eolian_files_legacy) \
@@ -100,8 +98,6 @@ lib/ecore/ecore_job.c \
100lib/ecore/ecore_main.c \ 98lib/ecore/ecore_main.c \
101lib/ecore/ecore_event_message.c \ 99lib/ecore/ecore_event_message.c \
102lib/ecore/ecore_event_message_handler.c \ 100lib/ecore/ecore_event_message_handler.c \
103lib/ecore/efl_core_env.c \
104lib/ecore/efl_core_proc_env.c \
105lib/ecore/efl_app.c \ 101lib/ecore/efl_app.c \
106lib/ecore/efl_loop.c \ 102lib/ecore/efl_loop.c \
107lib/ecore/efl_loop_consumer.c \ 103lib/ecore/efl_loop_consumer.c \
@@ -339,7 +335,6 @@ tests/ecore/efl_app_test_loop.c \
339tests/ecore/efl_app_test_loop_fd.c \ 335tests/ecore/efl_app_test_loop_fd.c \
340tests/ecore/efl_app_test_loop_timer.c \ 336tests/ecore/efl_app_test_loop_timer.c \
341tests/ecore/efl_app_test_promise.c \ 337tests/ecore/efl_app_test_promise.c \
342tests/ecore/efl_app_test_env.c \
343tests/ecore/efl_app_suite.c \ 338tests/ecore/efl_app_suite.c \
344tests/ecore/efl_app_suite.h 339tests/ecore/efl_app_suite.h
345 340
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 @@
26 * @{ 26 * @{
27 */ 27 */
28 28
29#include "efl_core_env.eo.h"
30#include "efl_core_proc_env.eo.h"
31
32#include "efl_loop_message.eo.h" 29#include "efl_loop_message.eo.h"
33#include "efl_loop_message_handler.eo.h" 30#include "efl_loop_message_handler.eo.h"
34 31
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
188{ 188{
189 Eina_Stringshare *command; 189 Eina_Stringshare *command;
190 Eina_Array *args; 190 Eina_Array *args;
191 Eina_Hash *env;
191 Efl_Task_Priority priority; 192 Efl_Task_Priority priority;
192 int exit_code; 193 int exit_code;
193 Efl_Task_Flags flags; 194 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)
26{ 26{
27 if (!key || key[0] == '\0') return EINA_FALSE; 27 if (!key || key[0] == '\0') return EINA_FALSE;
28 28
29 if (isdigit(key[0])) return EINA_FALSE; 29 if isdigit(key[0]) return EINA_FALSE;
30 30
31 for (int i = 0; key[i] != '\0'; ++i) { 31 for (int i = 0; key[i] != '\0'; ++i) {
32 if (!isalnum(key[i]) && key[i] != '_') return EINA_FALSE; 32 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 @@
1class Efl.Core.Env extends Efl.Object implements Efl.Duplicate {
2 [[This object can maintain a set of key value pairs
3
4 A object of this type alone does not apply the object to the system.
5 For getting the value into the system, see @Efl.Core.Proc_Env.
6
7 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.
8 ]]
9 methods {
10 @property env {
11 [[ Stored var value pairs of this object.
12
13 Var must contain only: underscores ('_'), letters ('a-z', 'A-Z'),
14 numbers ('0-9'), but the first character may not be a number.
15 ]]
16 set {
17 [[ Add a new pair to this object ]]
18 }
19 get {
20 [[ Get the value of the $var, or $null if no such $var exists in the object]]
21 }
22 keys {
23 var: string; [[ The name of the variable ]]
24 }
25 values {
26 value: string; [[ Set var to this value if not $NULL,
27 otherwise clear this env value if value
28 is $NULL or if it is an empty string ]]
29 }
30 }
31 unset {
32 [[ Remove the pair with the matching $var from this object]]
33 params {
34 var : string; [[ The name of the variable ]]
35 }
36 }
37 clear {
38 [[ Remove all pairs from this object]]
39 }
40 @property content {
41 [[ Get the content of this object.
42
43 This will return a iterator that contains all keys that are part of this object.
44 ]]
45 get {
46
47 }
48 values {
49 iter : iterator<string>;
50 }
51 }
52 }
53 implements {
54 Efl.Object.constructor;
55 Efl.Duplicate.duplicate;
56 }
57}
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 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <Ecore.h>
6#ifdef HAVE_CRT_EXTERNS_H
7# include <crt_externs.h>
8#endif
9#include "ecore_private.h"
10
11#define MY_CLASS EFL_CORE_PROC_ENV_CLASS
12
13static Efl_Core_Env *env = NULL;
14
15typedef struct {
16 Eina_Bool in_sync;
17} Efl_Core_Proc_Env_Data;
18
19static void
20_sync(Efl_Core_Env *obj, Efl_Core_Proc_Env_Data *pd)
21{
22 Eina_List *existing_keys = NULL, *n;
23 Eina_Iterator *content;
24 const char *key;
25
26 pd->in_sync = EINA_TRUE;
27 content = efl_core_env_content_get(obj);
28
29 EINA_ITERATOR_FOREACH(content, key)
30 {
31 existing_keys = eina_list_append(existing_keys, key);
32 }
33
34 if (environ)
35 {
36 char **p;
37
38 for (p = environ; *p; p++)
39 {
40 char **values;
41
42 values = eina_str_split(*p, "=", 2);
43 efl_core_env_set(obj, values[0], values[1]);
44
45 EINA_LIST_FOREACH(existing_keys, n, key)
46 {
47 if (!strcmp(key, values[0]))
48 {
49 existing_keys = eina_list_remove_list(existing_keys, n);
50 break;
51 }
52 }
53 }
54 }
55 EINA_LIST_FOREACH(existing_keys, n, key)
56 {
57 efl_core_env_unset(obj, key);
58 }
59 pd->in_sync = EINA_FALSE;
60}
61
62EOLIAN static const char*
63_efl_core_proc_env_efl_core_env_env_get(const Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *var)
64{
65 if (!pd->in_sync)
66 _sync((Eo*)obj, pd);
67 return efl_core_env_get(efl_super(obj, MY_CLASS), var);
68}
69
70EOLIAN static void
71_efl_core_proc_env_efl_core_env_env_set(Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *var, const char *value)
72{
73 efl_core_env_set(efl_super(obj, MY_CLASS), var, value);
74 if (!pd->in_sync)
75 {
76 if (value)
77 setenv(var, value, 1);
78 else
79 unsetenv(var);
80 }
81}
82
83EOLIAN static void
84_efl_core_proc_env_efl_core_env_unset(Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *key)
85{
86 efl_core_env_unset(efl_super(obj, MY_CLASS), key);
87 if (!pd->in_sync)
88 {
89 unsetenv(key);
90 }
91}
92
93EOLIAN static void
94_efl_core_proc_env_efl_core_env_clear(Eo *obj, Efl_Core_Proc_Env_Data *pd)
95{
96 efl_core_env_clear(efl_super(obj, MY_CLASS));
97 if (!pd->in_sync)
98 {
99#ifdef HAVE_CLEARENV
100 clearenv();
101#else
102 environ = NULL;
103#endif
104 }
105}
106
107
108EOLIAN static Efl_Duplicate*
109_efl_core_proc_env_efl_duplicate_duplicate(const Eo *obj, Efl_Core_Proc_Env_Data *pd)
110{
111 if (!pd->in_sync)
112 _sync((Eo*) obj, pd);
113 return efl_duplicate(efl_super(obj, MY_CLASS));
114}
115
116EOLIAN static Eina_Iterator*
117_efl_core_proc_env_efl_core_env_content_get(const Eo *obj, Efl_Core_Proc_Env_Data *pd)
118{
119 if (!pd->in_sync)
120 _sync((Eo*) obj, pd);
121 return efl_core_env_content_get(efl_super(obj, MY_CLASS));
122}
123
124EOLIAN static Efl_Object*
125_efl_core_proc_env_efl_object_constructor(Eo *obj, Efl_Core_Proc_Env_Data *pd EINA_UNUSED)
126{
127 EINA_SAFETY_ON_TRUE_RETURN_VAL(!!env, NULL);
128
129 obj = efl_constructor(efl_super(obj, MY_CLASS));
130 return obj;
131}
132
133EOLIAN static Efl_Core_Env*
134_efl_core_proc_env_self(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
135{
136 if (!env)
137 {
138 env = efl_add_ref(EFL_CORE_PROC_ENV_CLASS, NULL);
139 efl_wref_add(env, &env);
140 }
141
142 return env;
143}
144
145#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 @@
1class Efl.Core.Proc_Env extends Efl.Core.Env
2{
3 eo_prefix : efl_env;
4 methods {
5 self @class {
6 [[Get a instance of this object
7
8 The object will apply the environment operations onto this process.
9 ]]
10 return : Efl.Core.Env;
11 }
12 }
13 implements {
14 Efl.Core.Env.env { set; get; }
15 Efl.Core.Env.content { get; }
16 Efl.Core.Env.unset;
17 Efl.Core.Env.clear;
18 Efl.Duplicate.duplicate;
19 Efl.Object.constructor;
20 }
21}
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;
40 40
41struct _Efl_Exe_Data 41struct _Efl_Exe_Data
42{ 42{
43 Efl_Core_Env *env;
44 int exit_signal; 43 int exit_signal;
45 Efl_Exe_Flags flags; 44 Efl_Exe_Flags flags;
46#ifdef _WIN32 45#ifdef _WIN32
@@ -166,6 +165,22 @@ _exec(const char *cmd, Efl_Exe_Flags flags)
166 } 165 }
167} 166}
168 167
168static Eina_Bool
169_foreach_env(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata EINA_UNUSED)
170{
171 int keylen;
172 char *buf, *s;
173
174 if (!data) return EINA_TRUE;
175 keylen = strlen(key);
176 buf = alloca(keylen + 1 + strlen(data) + 1);
177 strcpy(buf, key);
178 buf[keylen] = '=';
179 strcpy(buf + keylen + 1, data);
180 if ((s = strdup(buf))) putenv(s);
181 return EINA_TRUE;
182}
183
169static void 184static void
170_exe_exit_eval(Eo *obj, Efl_Exe_Data *pd) 185_exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
171{ 186{
@@ -191,7 +206,7 @@ _exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
191 // 128+n Fatal error signal "n" kill -9 $PPID $? returns 137 (128 + 9) 206 // 128+n Fatal error signal "n" kill -9 $PPID $? returns 137 (128 + 9)
192 // 130 Script terminated by Control-C Ctl-C Control-C is fatal error signal 2, (130 = 128 + 2, see above) 207 // 130 Script terminated by Control-C Ctl-C Control-C is fatal error signal 2, (130 = 128 + 2, see above)
193 // 255* Exit status out of range exit -1 exit takes only integer args in the range 0 - 255 208 // 255* Exit status out of range exit -1 exit takes only integer args in the range 0 - 255
194 // 209 //
195 // According to the above table, exit codes 1 - 2, 210 // According to the above table, exit codes 1 - 2,
196 // 126 - 165, and 255 [1] have special meanings, and 211 // 126 - 165, and 255 [1] have special meanings, and
197 // should therefore be avoided for user-specified exit 212 // should therefore be avoided for user-specified exit
@@ -285,25 +300,6 @@ _run_clean_cb(Efl_Loop_Consumer *consumer EINA_UNUSED,
285 300
286////////////////////////////////////////////////////////////////////////// 301//////////////////////////////////////////////////////////////////////////
287 302
288
289EOLIAN static void
290_efl_exe_env_set(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Core_Env *env)
291{
292 if (pd->env == env) return;
293
294 if (!pd->env)
295 efl_unref(pd->env);
296 pd->env = env;
297 if (pd->env)
298 efl_ref(pd->env);
299}
300
301EOLIAN static Efl_Core_Env*
302_efl_exe_env_get(const Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
303{
304 return pd->env;
305}
306
307EOLIAN static void 303EOLIAN static void
308_efl_exe_signal(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Exe_Signal sig) 304_efl_exe_signal(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Exe_Signal sig)
309{ 305{
@@ -568,28 +564,17 @@ _efl_exe_efl_task_run(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
568 // clear systemd notify socket... only relevant for systemd world, 564 // clear systemd notify socket... only relevant for systemd world,
569 // otherwise shouldn't be trouble 565 // otherwise shouldn't be trouble
570 putenv("NOTIFY_SOCKET="); 566 putenv("NOTIFY_SOCKET=");
567 // force the env hash to update from env vars
568 efl_task_env_get(loop, "HOME");
571 569
572 // actually setenv the env object (clear what was there before so it is 570 // actually setenv the env hash (clear what was there before so it is
573 // the only env there) 571 // the only env there)
574 if (pd->env) 572#ifdef HAVE_CLEARENV
575 { 573 clearenv();
576 Eina_Iterator *itr; 574#else
577 const char *key; 575 environ = NULL;
578 576#endif
579 #ifdef HAVE_CLEARENV 577 eina_hash_foreach(td->env, _foreach_env, NULL);
580 clearenv();
581 #else
582 environ = NULL;
583 #endif
584 itr = efl_core_env_content_get(pd->env);
585
586 EINA_ITERATOR_FOREACH(itr, key)
587 {
588 setenv(key, efl_core_env_get(pd->env, key) , 1);
589 }
590 efl_unref(pd->env);
591 pd->env = NULL;
592 }
593 578
594 // actually execute! 579 // actually execute!
595 _exec(cmd, pd->flags); 580 _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
42 sig: int; [[ The exit signal, or -1 if no exit signal happened ]] 42 sig: int; [[ The exit signal, or -1 if no exit signal happened ]]
43 } 43 }
44 } 44 }
45 @property env {
46 [[ If $env is $null then the process created by this object is
47 going to inherit the enviroment of this process.
48
49 In case $env is not $null then the environment variables declared
50 in this object will represent the environment passed to the new process.
51 ]]
52 get {
53 [[ Get the object assosiated with this object ]]
54 }
55 set {
56 [[ Set the object assosiated with this object ]]
57 }
58 values {
59 env : Efl.Core.Env; [[$env will be referenced until this object does not need it anymore.]]
60 }
61 }
62 } 45 }
63 implements { 46 implements {
64 Efl.Object.constructor; 47 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 @@
15 15
16#include "ecore_main_common.h" 16#include "ecore_main_common.h"
17 17
18extern char **environ;
19
18typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data; 20typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data;
19typedef struct _Efl_Internal_Promise Efl_Internal_Promise; 21typedef struct _Efl_Internal_Promise Efl_Internal_Promise;
20 22
@@ -51,6 +53,11 @@ _efl_loop_message_handler_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Loo
51Eo *_mainloop_singleton = NULL; 53Eo *_mainloop_singleton = NULL;
52Efl_Loop_Data *_mainloop_singleton_data = NULL; 54Efl_Loop_Data *_mainloop_singleton_data = NULL;
53 55
56extern Eina_Lock _environ_lock;
57static Eina_List *_environ_strings_set = NULL;
58
59static void _clean_old_environ(void);
60
54EAPI Eo * 61EAPI Eo *
55efl_main_loop_get(void) 62efl_main_loop_get(void)
56{ 63{
@@ -347,6 +354,16 @@ _efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd)
347{ 354{
348 pd->future_message_handler = NULL; 355 pd->future_message_handler = NULL;
349 356
357 eina_lock_take(&_environ_lock);
358 _clean_old_environ();
359 _environ_strings_set = eina_list_free(_environ_strings_set);
360 pd->env.environ_ptr = NULL;
361 free(pd->env.environ_copy);
362 pd->env.environ_copy = NULL;
363 eina_lock_release(&_environ_lock);
364
365 eina_value_flush(&pd->exit_code);
366
350 efl_destructor(efl_super(obj, EFL_LOOP_CLASS)); 367 efl_destructor(efl_super(obj, EFL_LOOP_CLASS));
351} 368}
352 369
@@ -657,6 +674,178 @@ efl_build_version_set(int vmaj, int vmin, int vmic, int revision,
657 _app_efl_version.build_id = build_id ? strdup(build_id) : NULL; 674 _app_efl_version.build_id = build_id ? strdup(build_id) : NULL;
658} 675}
659 676
677static void
678_env_sync(Efl_Loop_Data *pd, Efl_Task_Data *td)
679{
680 Eina_Bool update = EINA_FALSE;
681 unsigned int count = 0, i;
682 char **p;
683
684 // count environs
685 if (environ)
686 {
687 for (p = environ; *p; p++) count++;
688 }
689 // cached env ptr is the same... so look deeper if things changes
690 if (pd->env.environ_ptr == environ)
691 {
692 // if we have no cached copy then update
693 if (!pd->env.environ_copy) update = EINA_TRUE;
694 else
695 {
696 // if any ptr in the cached copy doesnt match environ ptr
697 // then update
698 for (i = 0; i <= count; i++)
699 {
700 if (pd->env.environ_copy[i] != environ[i])
701 {
702 update = EINA_TRUE;
703 break;
704 }
705 }
706 }
707 }
708 // cached env ptr changed so we need to update anyway
709 else update = EINA_TRUE;
710 if (!update) return;
711 // things changed - do the update
712 pd->env.environ_ptr = environ;
713 free(pd->env.environ_copy);
714 pd->env.environ_copy = NULL;
715 if (count > 0)
716 {
717 pd->env.environ_copy = malloc((count + 1) * sizeof(char *));
718 if (pd->env.environ_copy)
719 {
720 for (i = 0; i <= count; i++)
721 pd->env.environ_copy[i] = environ[i];
722 }
723 }
724 // clear previous env hash and rebuild it from environ so it matches
725 if (td->env) eina_hash_free(td->env);
726 td->env = eina_hash_string_superfast_new
727 ((Eina_Free_Cb)eina_stringshare_del);
728 for (i = 0; i < count; i++)
729 {
730 char *var;
731 const char *value;
732
733 if (!environ[i]) continue;
734 if ((value = strchr(environ[i], '=')))
735 {
736 if (*value)
737 {
738 if ((var = malloc(value - environ[i] + 1)))
739 {
740 strncpy(var, environ[i], value - environ[i]);
741 var[value - environ[i]] = 0;
742 value++;
743 eina_hash_add(td->env, var,
744 eina_stringshare_add(value));
745 free(var);
746 }
747 }
748 }
749 }
750}
751
752static void
753_clean_old_environ(void)
754{
755 char **p;
756 const char *str;
757 Eina_List *l, *ll;
758 Eina_Bool ok;
759
760 // clean up old strings no longer in environ
761 EINA_LIST_FOREACH_SAFE(_environ_strings_set, l, ll, str)
762 {
763 ok = EINA_FALSE;
764 for (p = environ; *p; p++)
765 {
766 if (*p == str)
767 {
768 ok = EINA_TRUE;
769 break;
770 }
771 }
772 if (!ok)
773 {
774 _environ_strings_set =
775 eina_list_remove_list(_environ_strings_set, l);
776 eina_stringshare_del(str);
777 }
778 }
779}
780
781EOLIAN static void
782_efl_loop_efl_task_env_set(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, const char *var, const char *value)
783{
784 char *str, *str2;
785 size_t varlen, vallen = 0;
786
787 if (!var) return;
788
789 Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
790 if (!td) return;
791
792 varlen = strlen(var);
793 if (value) vallen = strlen(value);
794
795 str = malloc(varlen + 1 + vallen + 1);
796 if (!str) return;
797 strcpy(str, var);
798 str[varlen] = '=';
799 if (value) strcpy(str + varlen + 1, value);
800 else str[varlen + 1] = 0;
801
802 str2 = (char *)eina_stringshare_add(str);
803 free(str);
804 if (!str2) return;
805
806 eina_lock_take(&_environ_lock);
807 if (putenv(str2) != 0)
808 {
809 eina_stringshare_del(str2);
810 eina_lock_release(&_environ_lock);
811 return;
812 }
813 _environ_strings_set = eina_list_append(_environ_strings_set, str2);
814 eina_lock_release(&_environ_lock);
815
816 efl_task_env_set(efl_super(obj, EFL_LOOP_CLASS), var, value);
817
818 eina_lock_take(&_environ_lock);
819 _clean_old_environ();
820 eina_lock_release(&_environ_lock);
821}
822
823EOLIAN static const char *
824_efl_loop_efl_task_env_get(const Eo *obj, Efl_Loop_Data *pd, const char *var)
825{
826 Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
827 if (!td) return NULL;
828 eina_lock_take(&_environ_lock);
829 _env_sync(pd, td);
830 eina_lock_release(&_environ_lock);
831 return efl_task_env_get(efl_super(obj, EFL_LOOP_CLASS), var);
832}
833
834EOLIAN static void
835_efl_loop_efl_task_env_reset(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
836{
837 Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
838 if (!td) return;
839 eina_lock_take(&_environ_lock);
840#ifdef HAVE_CLEARENV
841 clearenv();
842#else
843 environ = NULL;
844#endif
845 _env_sync(pd, td);
846 eina_lock_release(&_environ_lock);
847}
848
660EOLIAN static Eina_Future * 849EOLIAN static Eina_Future *
661_efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) 850_efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
662{ 851{
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
125 Efl.Object.invalidate; 125 Efl.Object.invalidate;
126 Efl.Object.destructor; 126 Efl.Object.destructor;
127 Efl.Object.provider_find; 127 Efl.Object.provider_find;
128 Efl.Task.env { set; get; }
129 Efl.Task.env_reset;
128 Efl.Task.run; 130 Efl.Task.run;
129 Efl.Task.end; 131 Efl.Task.end;
130 } 132 }
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)
227 eina_strbuf_free(sb); 227 eina_strbuf_free(sb);
228} 228}
229 229
230
231static Eina_Bool
232_foreach_env_copy(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata)
233{
234 if (data)
235 {
236 // only copy env vars not already set
237 if (!eina_hash_find(fdata, key))
238 eina_hash_add(fdata, key, eina_stringshare_add(data));
239 }
240 return EINA_TRUE;
241}
242
230////////////////////////////////////////////////////////////////////////// 243//////////////////////////////////////////////////////////////////////////
231 244
232EOLIAN static void 245EOLIAN static void
@@ -310,6 +323,34 @@ _efl_task_arg_reset(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
310} 323}
311 324
312EOLIAN static void 325EOLIAN static void
326_efl_task_env_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *var, const char *value)
327{
328 if (!var) return;
329 if (!pd->env)
330 pd->env = eina_hash_string_superfast_new
331 ((Eina_Free_Cb)eina_stringshare_del);
332 if (!pd->env) return;
333 if ((value) && (*value))
334 eina_hash_add(pd->env, var, eina_stringshare_add(value));
335 else eina_hash_del(pd->env, var, NULL);
336}
337
338
339EOLIAN static const char *
340_efl_task_env_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *var)
341{
342 if ((!var) || (!pd->env)) return NULL;
343 return eina_hash_find(pd->env, var);
344}
345
346EOLIAN static void
347_efl_task_env_reset(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
348{
349 if (pd->env) eina_hash_free(pd->env);
350 pd->env = NULL;
351}
352
353EOLIAN static void
313_efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Priority priority) 354_efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Priority priority)
314{ 355{
315 pd->priority = priority; 356 pd->priority = priority;
@@ -345,13 +386,32 @@ _efl_task_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
345 eina_stringshare_del(pd->command); 386 eina_stringshare_del(pd->command);
346 pd->command = NULL; 387 pd->command = NULL;
347 _clear_args(pd); 388 _clear_args(pd);
389 if (pd->env) eina_hash_free(pd->env);
390 pd->env = NULL;
348 efl_destructor(efl_super(obj, MY_CLASS)); 391 efl_destructor(efl_super(obj, MY_CLASS));
349} 392}
350 393
351EOLIAN static void 394EOLIAN static void
352_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd EINA_UNUSED, Efl_Object *parent) 395_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd, Efl_Object *parent)
353{ 396{
397 Eo *loop;
398
354 efl_parent_set(efl_super(obj, MY_CLASS), parent); 399 efl_parent_set(efl_super(obj, MY_CLASS), parent);
400 // copy loop env into exe task env, if not already set in env (overridden)
401 loop = efl_provider_find(parent, EFL_LOOP_CLASS);
402 if (loop)
403 {
404 Efl_Task_Data *tdl = efl_data_scope_get(loop, EFL_TASK_CLASS);
405
406 if (tdl)
407 {
408 if (!pd->env)
409 pd->env = eina_hash_string_superfast_new
410 ((Eina_Free_Cb)eina_stringshare_del);
411 if (tdl->env)
412 eina_hash_foreach(tdl->env, _foreach_env_copy, pd->env);
413 }
414 }
355} 415}
356 416
357////////////////////////////////////////////////////////////////////////// 417//////////////////////////////////////////////////////////////////////////
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
96 [[ Clear all arguments in arg_value/count set. Will result in the 96 [[ Clear all arguments in arg_value/count set. Will result in the
97 command property also being cleared. ]] 97 command property also being cleared. ]]
98 } 98 }
99 @property env {
100 [[ The environment to be passed in or that was passed to the
101 task. This is a string key, value list which map to environment
102 variables where appropriate. The var string must contain
103 only an underscore ('_'), letters ('a-z', 'A-Z'),
104 numbers ('0-9'), but the first character may not be a number.]]
105 set { }
106 get { }
107 keys {
108 var: string; [[ The variable name as a string ]]
109 }
110 values {
111 value: string; [[ Set var to this value if not $NULL,
112 otherwise clear this env value if value
113 is $NULL or if it is an empty string ]]
114 }
115 }
116 env_reset {
117 [[ Clear all environment variables. ]]
118 }
99 @property priority { 119 @property priority {
100 [[ The priority of this task. ]] 120 [[ The priority of this task. ]]
101 get { } 121 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 = [
74 'efl_boolean_model.eo', 74 'efl_boolean_model.eo',
75 'efl_select_model.eo', 75 'efl_select_model.eo',
76 'efl_composite_model.eo', 76 'efl_composite_model.eo',
77 'efl_view_model.eo', 77 'efl_view_model.eo'
78 'efl_core_env.eo',
79 'efl_core_proc_env.eo'
80] 78]
81 79
82foreach eo_file : pub_eo_files 80foreach eo_file : pub_eo_files
@@ -182,8 +180,6 @@ ecore_src = [
182 'efl_thread.c', 180 'efl_thread.c',
183 'efl_threadio.c', 181 'efl_threadio.c',
184 'efl_appthread.c', 182 'efl_appthread.c',
185 'efl_core_env.c',
186 'efl_core_proc_env.c',
187] 183]
188 184
189if sys_windows == true 185if 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 @@
9#include "efl_app_suite.h" 9#include "efl_app_suite.h"
10#include "../efl_check.h" 10#include "../efl_check.h"
11 11
12
12EFL_START_TEST(efl_app_test_efl_build_version) 13EFL_START_TEST(efl_app_test_efl_build_version)
13{ 14{
14 const Efl_Version *ver; 15 const Efl_Version *ver;
@@ -52,7 +53,6 @@ static const Efl_Test_Case etc[] = {
52 { "Promise", efl_app_test_promise_2 }, 53 { "Promise", efl_app_test_promise_2 },
53 { "Promise", efl_app_test_promise_3 }, 54 { "Promise", efl_app_test_promise_3 },
54 { "Promise", efl_app_test_promise_safety }, 55 { "Promise", efl_app_test_promise_safety },
55 { "Env", efl_test_efl_env },
56 { NULL, NULL } 56 { NULL, NULL }
57}; 57};
58 58
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);
11void efl_app_test_promise_2(TCase *tc); 11void efl_app_test_promise_2(TCase *tc);
12void efl_app_test_promise_3(TCase *tc); 12void efl_app_test_promise_3(TCase *tc);
13void efl_app_test_promise_safety(TCase *tc); 13void efl_app_test_promise_safety(TCase *tc);
14void efl_test_efl_env(TCase *tc);
15 14
16#endif /* _EFL_APP_SUITE_H */ 15#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 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <unistd.h>
7#define EFL_NOLEGACY_API_SUPPORT
8#include <Efl_Core.h>
9#include "efl_app_suite.h"
10#include "../efl_check.h"
11
12EFL_START_TEST(efl_core_env_test_set_get)
13{
14 Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
15
16 efl_core_env_set(env, "FOO", "bar");
17 efl_core_env_set(env, "going", "home");
18 efl_core_env_set(env, "Merry", "christmas");
19
20 ck_assert_str_eq(efl_core_env_get(env, "FOO"), "bar");
21 ck_assert_str_eq(efl_core_env_get(env, "going"), "home");
22 ck_assert_str_eq(efl_core_env_get(env, "Merry"), "christmas");
23
24 efl_core_env_unset(env, "Merry");
25
26 ck_assert_str_eq(efl_core_env_get(env, "FOO"), "bar");
27 ck_assert_str_eq(efl_core_env_get(env, "going"), "home");
28 ck_assert_ptr_eq(efl_core_env_get(env, "Merry"), NULL);
29
30 efl_unref(env);
31}
32EFL_END_TEST
33
34EFL_START_TEST(efl_core_env_test_invalid_keys)
35{
36 Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
37
38#define CHECK(val) \
39 efl_core_env_set(env, val, "TEST"); \
40 ck_assert_ptr_eq(efl_core_env_get(env, val), NULL);
41
42 CHECK("0foo");
43 CHECK("foo bar");
44 CHECK("foo!bar");
45
46#undef CHECK
47
48
49#define CHECK(val) \
50 efl_core_env_set(env, val, "TEST"); \
51 ck_assert_str_eq(efl_core_env_get(env, val), "TEST");
52
53 CHECK("foo0");
54 CHECK("foo_bar");
55
56#undef CHECK
57
58}
59EFL_END_TEST
60
61EFL_START_TEST(efl_core_env_test_clear)
62{
63 Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
64
65 efl_core_env_set(env, "FOO", "bar");
66 efl_core_env_set(env, "going", "home");
67 efl_core_env_set(env, "Merry", "christmas");
68
69 efl_core_env_clear(env);
70
71 ck_assert_ptr_eq(efl_core_env_get(env, "FOO"), NULL);
72 ck_assert_ptr_eq(efl_core_env_get(env, "going"), NULL);
73 ck_assert_ptr_eq(efl_core_env_get(env, "Merry"), NULL);
74
75 efl_unref(env);
76}
77EFL_END_TEST
78
79EFL_START_TEST(efl_core_env_test_fork)
80{
81 Efl_Core_Env *env_fork, *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
82
83 efl_core_env_set(env, "FOO", "bar");
84 efl_core_env_set(env, "going", "home");
85 efl_core_env_set(env, "Merry", "christmas");
86
87 env_fork = efl_duplicate(env);
88
89 ck_assert_str_eq(efl_core_env_get(env_fork, "FOO"), "bar");
90 ck_assert_str_eq(efl_core_env_get(env_fork, "going"), "home");
91 ck_assert_str_eq(efl_core_env_get(env_fork, "Merry"), "christmas");
92
93 efl_unref(env);
94}
95EFL_END_TEST
96
97EFL_START_TEST(efl_core_env_test_process)
98{
99 Efl_Core_Env *env_fork, *env = efl_env_self(EFL_CORE_PROC_ENV_CLASS);
100
101 ck_assert(env);
102
103 ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH"));
104 env_fork = efl_duplicate(env);
105 ck_assert_str_eq(efl_core_env_get(env_fork, "PATH"), getenv("PATH"));
106
107 efl_unref(env);
108}
109EFL_END_TEST
110
111EFL_START_TEST(efl_core_env_test_undepend_fork)
112{
113 Efl_Core_Env *env_fork, *env = efl_env_self(EFL_CORE_PROC_ENV_CLASS);
114
115 ck_assert(env);
116
117 ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH"));
118 env_fork = efl_duplicate(env);
119 efl_core_env_set(env_fork, "PATH", "abc");
120 ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH"));
121
122 efl_unref(env);
123 efl_unref(env_fork);
124}
125EFL_END_TEST
126
127void efl_test_efl_env(TCase *tc)
128{
129 tcase_add_test(tc, efl_core_env_test_set_get);
130 tcase_add_test(tc, efl_core_env_test_invalid_keys);
131 tcase_add_test(tc, efl_core_env_test_clear);
132 tcase_add_test(tc, efl_core_env_test_fork);
133 tcase_add_test(tc, efl_core_env_test_process);
134 tcase_add_test(tc, efl_core_env_test_undepend_fork);
135}
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 = [
75 'efl_app_test_loop.c', 75 'efl_app_test_loop.c',
76 'efl_app_test_loop_fd.c', 76 'efl_app_test_loop_fd.c',
77 'efl_app_test_loop_timer.c', 77 'efl_app_test_loop_timer.c',
78 'efl_app_test_promise.c', 78 'efl_app_test_promise.c'
79 'efl_app_test_env.c'
80] 79]
81 80
82efl_app_suite_deps = [m] 81efl_app_suite_deps = [m]