summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-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, 439 insertions, 305 deletions
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 = [
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'
57] 58]
58 59
59function_checks = [ 60function_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
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())')
213else 214else
214 error('System '+host_machine.system()+' not known') 215 error('System '+host_machine.system()+' not known')
215endif 216endif
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 = \
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 \
53 55
54ecore_eolian_files = \ 56ecore_eolian_files = \
55 $(ecore_eolian_files_legacy) \ 57 $(ecore_eolian_files_legacy) \
@@ -98,6 +100,8 @@ lib/ecore/ecore_job.c \
98lib/ecore/ecore_main.c \ 100lib/ecore/ecore_main.c \
99lib/ecore/ecore_event_message.c \ 101lib/ecore/ecore_event_message.c \
100lib/ecore/ecore_event_message_handler.c \ 102lib/ecore/ecore_event_message_handler.c \
103lib/ecore/efl_core_env.c \
104lib/ecore/efl_core_proc_env.c \
101lib/ecore/efl_app.c \ 105lib/ecore/efl_app.c \
102lib/ecore/efl_loop.c \ 106lib/ecore/efl_loop.c \
103lib/ecore/efl_loop_consumer.c \ 107lib/ecore/efl_loop_consumer.c \
@@ -335,6 +339,7 @@ tests/ecore/efl_app_test_loop.c \
335tests/ecore/efl_app_test_loop_fd.c \ 339tests/ecore/efl_app_test_loop_fd.c \
336tests/ecore/efl_app_test_loop_timer.c \ 340tests/ecore/efl_app_test_loop_timer.c \
337tests/ecore/efl_app_test_promise.c \ 341tests/ecore/efl_app_test_promise.c \
342tests/ecore/efl_app_test_env.c \
338tests/ecore/efl_app_suite.c \ 343tests/ecore/efl_app_suite.c \
339tests/ecore/efl_app_suite.h 344tests/ecore/efl_app_suite.h
340 345
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 @@
26 * @{ 26 * @{
27 */ 27 */
28 28
29#include "efl_core_env.eo.h"
30#include "efl_core_proc_env.eo.h"
31
29#include "efl_loop_message.eo.h" 32#include "efl_loop_message.eo.h"
30#include "efl_loop_message_handler.eo.h" 33#include "efl_loop_message_handler.eo.h"
31 34
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
188{ 188{
189 Eina_Stringshare *command; 189 Eina_Stringshare *command;
190 Eina_Array *args; 190 Eina_Array *args;
191 Eina_Hash *env;
192 Efl_Task_Priority priority; 191 Efl_Task_Priority priority;
193 int exit_code; 192 int exit_code;
194 Efl_Task_Flags flags; 193 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)
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
new file mode 100644
index 0000000000..86da8c14ff
--- /dev/null
+++ b/src/lib/ecore/efl_core_env.eo
@@ -0,0 +1,57 @@
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
new file mode 100644
index 0000000000..846b69a350
--- /dev/null
+++ b/src/lib/ecore/efl_core_proc_env.c
@@ -0,0 +1,145 @@
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
new file mode 100644
index 0000000000..23c2c67d75
--- /dev/null
+++ b/src/lib/ecore/efl_core_proc_env.eo
@@ -0,0 +1,21 @@
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 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;
40 40
41struct _Efl_Exe_Data 41struct _Efl_Exe_Data
42{ 42{
43 Efl_Core_Env *env;
43 int exit_signal; 44 int exit_signal;
44 Efl_Exe_Flags flags; 45 Efl_Exe_Flags flags;
45#ifdef _WIN32 46#ifdef _WIN32
@@ -165,22 +166,6 @@ _exec(const char *cmd, Efl_Exe_Flags flags)
165 } 166 }
166} 167}
167 168
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
184static void 169static void
185_exe_exit_eval(Eo *obj, Efl_Exe_Data *pd) 170_exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
186{ 171{
@@ -206,7 +191,7 @@ _exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
206 // 128+n Fatal error signal "n" kill -9 $PPID $? returns 137 (128 + 9) 191 // 128+n Fatal error signal "n" kill -9 $PPID $? returns 137 (128 + 9)
207 // 130 Script terminated by Control-C Ctl-C Control-C is fatal error signal 2, (130 = 128 + 2, see above) 192 // 130 Script terminated by Control-C Ctl-C Control-C is fatal error signal 2, (130 = 128 + 2, see above)
208 // 255* Exit status out of range exit -1 exit takes only integer args in the range 0 - 255 193 // 255* Exit status out of range exit -1 exit takes only integer args in the range 0 - 255
209 // 194 //
210 // According to the above table, exit codes 1 - 2, 195 // According to the above table, exit codes 1 - 2,
211 // 126 - 165, and 255 [1] have special meanings, and 196 // 126 - 165, and 255 [1] have special meanings, and
212 // should therefore be avoided for user-specified exit 197 // should therefore be avoided for user-specified exit
@@ -300,6 +285,25 @@ _run_clean_cb(Efl_Loop_Consumer *consumer EINA_UNUSED,
300 285
301////////////////////////////////////////////////////////////////////////// 286//////////////////////////////////////////////////////////////////////////
302 287
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
303EOLIAN static void 307EOLIAN static void
304_efl_exe_signal(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Exe_Signal sig) 308_efl_exe_signal(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Exe_Signal sig)
305{ 309{
@@ -564,17 +568,28 @@ _efl_exe_efl_task_run(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
564 // clear systemd notify socket... only relevant for systemd world, 568 // clear systemd notify socket... only relevant for systemd world,
565 // otherwise shouldn't be trouble 569 // otherwise shouldn't be trouble
566 putenv("NOTIFY_SOCKET="); 570 putenv("NOTIFY_SOCKET=");
567 // force the env hash to update from env vars
568 efl_task_env_get(loop, "HOME");
569 571
570 // actually setenv the env hash (clear what was there before so it is 572 // actually setenv the env object (clear what was there before so it is
571 // the only env there) 573 // the only env there)
572#ifdef HAVE_CLEARENV 574 if (pd->env)
573 clearenv(); 575 {
574#else 576 Eina_Iterator *itr;
575 environ = NULL; 577 const char *key;
576#endif 578
577 eina_hash_foreach(td->env, _foreach_env, NULL); 579 #ifdef HAVE_CLEARENV
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 }
578 593
579 // actually execute! 594 // actually execute!
580 _exec(cmd, pd->flags); 595 _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
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 }
45 } 62 }
46 implements { 63 implements {
47 Efl.Object.constructor; 64 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 @@
15 15
16#include "ecore_main_common.h" 16#include "ecore_main_common.h"
17 17
18extern char **environ;
19
20typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data; 18typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data;
21typedef struct _Efl_Internal_Promise Efl_Internal_Promise; 19typedef struct _Efl_Internal_Promise Efl_Internal_Promise;
22 20
@@ -53,11 +51,6 @@ _efl_loop_message_handler_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Loo
53Eo *_mainloop_singleton = NULL; 51Eo *_mainloop_singleton = NULL;
54Efl_Loop_Data *_mainloop_singleton_data = NULL; 52Efl_Loop_Data *_mainloop_singleton_data = NULL;
55 53
56extern Eina_Lock _environ_lock;
57static Eina_List *_environ_strings_set = NULL;
58
59static void _clean_old_environ(void);
60
61EAPI Eo * 54EAPI Eo *
62efl_main_loop_get(void) 55efl_main_loop_get(void)
63{ 56{
@@ -354,16 +347,6 @@ _efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd)
354{ 347{
355 pd->future_message_handler = NULL; 348 pd->future_message_handler = NULL;
356 349
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
367 efl_destructor(efl_super(obj, EFL_LOOP_CLASS)); 350 efl_destructor(efl_super(obj, EFL_LOOP_CLASS));
368} 351}
369 352
@@ -674,178 +657,6 @@ efl_build_version_set(int vmaj, int vmin, int vmic, int revision,
674 _app_efl_version.build_id = build_id ? strdup(build_id) : NULL; 657 _app_efl_version.build_id = build_id ? strdup(build_id) : NULL;
675} 658}
676 659
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
849EOLIAN static Eina_Future * 660EOLIAN static Eina_Future *
850_efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) 661_efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
851{ 662{
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
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;
130 Efl.Task.run; 128 Efl.Task.run;
131 Efl.Task.end; 129 Efl.Task.end;
132 } 130 }
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)
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
243////////////////////////////////////////////////////////////////////////// 230//////////////////////////////////////////////////////////////////////////
244 231
245EOLIAN static void 232EOLIAN static void
@@ -323,34 +310,6 @@ _efl_task_arg_reset(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
323} 310}
324 311
325EOLIAN static void 312EOLIAN 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
354_efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Priority priority) 313_efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Priority priority)
355{ 314{
356 pd->priority = priority; 315 pd->priority = priority;
@@ -386,32 +345,13 @@ _efl_task_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
386 eina_stringshare_del(pd->command); 345 eina_stringshare_del(pd->command);
387 pd->command = NULL; 346 pd->command = NULL;
388 _clear_args(pd); 347 _clear_args(pd);
389 if (pd->env) eina_hash_free(pd->env);
390 pd->env = NULL;
391 efl_destructor(efl_super(obj, MY_CLASS)); 348 efl_destructor(efl_super(obj, MY_CLASS));
392} 349}
393 350
394EOLIAN static void 351EOLIAN static void
395_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd, Efl_Object *parent) 352_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd EINA_UNUSED, Efl_Object *parent)
396{ 353{
397 Eo *loop;
398
399 efl_parent_set(efl_super(obj, MY_CLASS), parent); 354 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 }
415} 355}
416 356
417////////////////////////////////////////////////////////////////////////// 357//////////////////////////////////////////////////////////////////////////
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
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 }
119 @property priority { 99 @property priority {
120 [[ The priority of this task. ]] 100 [[ The priority of this task. ]]
121 get { } 101 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 = [
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'
78] 80]
79 81
80foreach eo_file : pub_eo_files 82foreach eo_file : pub_eo_files
@@ -180,6 +182,8 @@ ecore_src = [
180 'efl_thread.c', 182 'efl_thread.c',
181 'efl_threadio.c', 183 'efl_threadio.c',
182 'efl_appthread.c', 184 'efl_appthread.c',
185 'efl_core_env.c',
186 'efl_core_proc_env.c',
183] 187]
184 188
185if sys_windows == true 189if 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 @@
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
13EFL_START_TEST(efl_app_test_efl_build_version) 12EFL_START_TEST(efl_app_test_efl_build_version)
14{ 13{
15 const Efl_Version *ver; 14 const Efl_Version *ver;
@@ -53,6 +52,7 @@ static const Efl_Test_Case etc[] = {
53 { "Promise", efl_app_test_promise_2 }, 52 { "Promise", efl_app_test_promise_2 },
54 { "Promise", efl_app_test_promise_3 }, 53 { "Promise", efl_app_test_promise_3 },
55 { "Promise", efl_app_test_promise_safety }, 54 { "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 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);
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);
14 15
15#endif /* _EFL_APP_SUITE_H */ 16#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 @@
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 4b46814bbe..e3b4f6c851 100644
--- a/src/tests/ecore/meson.build
+++ b/src/tests/ecore/meson.build
@@ -75,7 +75,8 @@ 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'
79] 80]
80 81
81efl_app_suite_deps = [m] 82efl_app_suite_deps = [m]