1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 
9 #include <Efl.h>
10 
11 #include "Ecore.h"
12 #include "ecore_private.h"
13 
14 #define MY_CLASS ECORE_EXE_CLASS
15 
16 #include "ecore_exe_private.h"
17 
18 /* TODO: Something to let people build a command line and does auto escaping -
19  *
20  * ecore_exe_snprintf()
21  *
22  *   OR
23  *
24  * cmd = ecore_exe_comand_parameter_append(cmd, "firefox");
25  * cmd = ecore_exe_comand_parameter_append(cmd, "http://www.foo.com/bar.html?baz=yes");
26  * each parameter appended is one argument, and it gets escaped, quoted, and
27  * appended with a preceding space.  The first is the command off course.
28  */
29 
30 struct _ecore_exe_dead_exe
31 {
32    pid_t pid;
33    char *cmd;
34 };
35 
36 EAPI int ECORE_EXE_EVENT_ADD = 0;
37 EAPI int ECORE_EXE_EVENT_DEL = 0;
38 EAPI int ECORE_EXE_EVENT_DATA = 0;
39 EAPI int ECORE_EXE_EVENT_ERROR = 0;
40 
41 EAPI void
ecore_exe_run_priority_set(int pri)42 ecore_exe_run_priority_set(int pri)
43 {
44    EINA_MAIN_LOOP_CHECK_RETURN;
45    _impl_ecore_exe_run_priority_set(pri);
46 }
47 
48 EAPI int
ecore_exe_run_priority_get(void)49 ecore_exe_run_priority_get(void)
50 {
51    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
52    return _impl_ecore_exe_run_priority_get();
53 }
54 
55 EAPI Ecore_Exe *
ecore_exe_run(const char * exe_cmd,const void * data)56 ecore_exe_run(const char *exe_cmd,
57               const void *data)
58 {
59    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
60    return ecore_exe_pipe_run(exe_cmd, 0, data);
61 }
62 
63 EAPI Ecore_Exe *
ecore_exe_pipe_run(const char * exe_cmd,Ecore_Exe_Flags flags,const void * data)64 ecore_exe_pipe_run(const char      *exe_cmd,
65                    Ecore_Exe_Flags  flags,
66                    const void      *data)
67 {
68    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
69    Ecore_Exe *ret = efl_add(MY_CLASS, efl_main_loop_get(),
70                             ecore_obj_exe_command_set(efl_added, exe_cmd,
71                                                       flags));
72    if (ret)
73      {
74         Ecore_Exe_Data *pd = efl_data_scope_get(ret, MY_CLASS);
75         pd->data = (void *) data;
76      }
77    return ret;
78 }
79 
80 EOLIAN static void
_ecore_exe_command_set(Eo * obj EINA_UNUSED,Ecore_Exe_Data * pd,const char * cmd,Ecore_Exe_Flags flags)81 _ecore_exe_command_set(Eo *obj EINA_UNUSED, Ecore_Exe_Data *pd, const char *cmd, Ecore_Exe_Flags flags)
82 {
83    if (!cmd) return;
84    pd->cmd = strdup(cmd);
85    pd->flags = flags;
86 }
87 
88 EOLIAN static void
_ecore_exe_command_get(const Eo * obj EINA_UNUSED,Ecore_Exe_Data * pd,const char ** cmd,Ecore_Exe_Flags * flags)89 _ecore_exe_command_get(const Eo *obj EINA_UNUSED, Ecore_Exe_Data *pd, const char **cmd, Ecore_Exe_Flags *flags)
90 {
91    if (cmd) *cmd = pd->cmd;
92    if (flags) *flags = pd->flags;
93 }
94 
95 EOLIAN static Eo *
_ecore_exe_efl_object_finalize(Eo * obj,Ecore_Exe_Data * exe)96 _ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
97 {
98    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
99    obj = efl_finalize(efl_super(obj, MY_CLASS));
100    if (!obj) return obj;
101    return _impl_ecore_exe_efl_object_finalize(obj, exe);
102 }
103 
104 EAPI void
ecore_exe_callback_pre_free_set(Ecore_Exe * obj,Ecore_Exe_Cb func)105 ecore_exe_callback_pre_free_set(Ecore_Exe   *obj,
106                                 Ecore_Exe_Cb func)
107 {
108    EINA_MAIN_LOOP_CHECK_RETURN;
109    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
110    if (!efl_isa(obj, MY_CLASS)) return;
111    exe->pre_free_cb = func;
112 }
113 
114 EAPI Eina_Bool
ecore_exe_send(Ecore_Exe * obj,const void * data,int size)115 ecore_exe_send(Ecore_Exe  *obj,
116                const void *data,
117                int         size)
118 {
119    EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
120    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
121    if (!efl_isa(obj, MY_CLASS)) return EINA_FALSE;
122 
123    EINA_SAFETY_ON_TRUE_RETURN_VAL(size == 0, EINA_TRUE);
124    if (exe->close_stdin)
125      {
126         ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p",
127             exe, size, data);
128         return EINA_FALSE;
129      }
130    return _impl_ecore_exe_send(obj, exe, data, size);
131 }
132 
133 EAPI void
ecore_exe_close_stdin(Ecore_Exe * obj)134 ecore_exe_close_stdin(Ecore_Exe *obj)
135 {
136    EINA_MAIN_LOOP_CHECK_RETURN;
137    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
138    if (!efl_isa(obj, MY_CLASS)) return;
139    exe->close_stdin = 1;
140 }
141 
142 EAPI void
ecore_exe_auto_limits_set(Ecore_Exe * obj,int start_bytes,int end_bytes,int start_lines,int end_lines)143 ecore_exe_auto_limits_set(Ecore_Exe *obj,
144                           int        start_bytes,
145                           int        end_bytes,
146                           int        start_lines,
147                           int        end_lines)
148 {
149    EINA_MAIN_LOOP_CHECK_RETURN;
150    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
151    if (!efl_isa(obj, MY_CLASS)) return;
152    _impl_ecore_exe_auto_limits_set(obj, exe, start_bytes, end_bytes,
153                                    start_lines, end_lines);
154 }
155 
156 EAPI Ecore_Exe_Event_Data *
ecore_exe_event_data_get(Ecore_Exe * obj,Ecore_Exe_Flags flags)157 ecore_exe_event_data_get(Ecore_Exe      *obj,
158                          Ecore_Exe_Flags flags)
159 {
160    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
161    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
162    if (!efl_isa(obj, MY_CLASS)) return NULL;
163    return _impl_ecore_exe_event_data_get(obj, exe, flags);
164 }
165 
166 EAPI void
ecore_exe_tag_set(Ecore_Exe * obj,const char * tag)167 ecore_exe_tag_set(Ecore_Exe  *obj,
168                   const char *tag)
169 {
170    EINA_MAIN_LOOP_CHECK_RETURN;
171    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
172    if (!efl_isa(obj, MY_CLASS)) return;
173    IF_FREE(exe->tag);
174    if (tag) exe->tag = strdup(tag);
175    else exe->tag = NULL;
176 }
177 
178 EAPI const char *
ecore_exe_tag_get(const Ecore_Exe * obj)179 ecore_exe_tag_get(const Ecore_Exe *obj)
180 {
181    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
182    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
183    if (!efl_isa(obj, MY_CLASS)) return NULL;
184    return exe->tag;
185 }
186 
187 EAPI void *
ecore_exe_free(Ecore_Exe * obj)188 ecore_exe_free(Ecore_Exe *obj)
189 {
190    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
191    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
192    if (!efl_isa(obj, MY_CLASS)) return NULL;
193    void *data = exe->data;
194    efl_del(obj);
195    return data;
196 }
197 
198 EOLIAN static void
_ecore_exe_efl_object_destructor(Eo * obj,Ecore_Exe_Data * exe)199 _ecore_exe_efl_object_destructor(Eo *obj, Ecore_Exe_Data *exe)
200 {
201    efl_destructor(efl_super(obj, ECORE_EXE_CLASS));
202    _impl_ecore_exe_efl_object_destructor(obj, exe);
203 }
204 
205 EAPI void
ecore_exe_event_data_free(Ecore_Exe_Event_Data * e)206 ecore_exe_event_data_free(Ecore_Exe_Event_Data *e)
207 {
208    if (!e) return;
209    IF_FREE(e->lines);
210    IF_FREE(e->data);
211    free(e);
212 }
213 
214 EAPI pid_t
ecore_exe_pid_get(const Ecore_Exe * obj)215 ecore_exe_pid_get(const Ecore_Exe *obj)
216 {
217    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
218    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
219    if (!efl_isa(obj, MY_CLASS)) return -1;
220    return exe->pid;
221 }
222 
223 EAPI const char *
ecore_exe_cmd_get(const Ecore_Exe * obj)224 ecore_exe_cmd_get(const Ecore_Exe *obj)
225 {
226    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
227    const char *ret = NULL;
228    ecore_obj_exe_command_get(obj, &ret, NULL);
229    return ret;
230 }
231 
232 EAPI void *
ecore_exe_data_get(const Ecore_Exe * obj)233 ecore_exe_data_get(const Ecore_Exe *obj)
234 {
235    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
236    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
237    if (!efl_isa(obj, MY_CLASS)) return NULL;
238    return exe->data;
239 }
240 
241 EAPI void *
ecore_exe_data_set(Ecore_Exe * obj,void * data)242 ecore_exe_data_set(Ecore_Exe *obj,
243                    void      *data)
244 {
245    void *ret;
246    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
247    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
248    if (!efl_isa(obj, MY_CLASS)) return NULL;
249    ret = exe->data;
250    exe->data = data;
251    return ret;
252 }
253 
254 EAPI Ecore_Exe_Flags
ecore_exe_flags_get(const Ecore_Exe * obj)255 ecore_exe_flags_get(const Ecore_Exe *obj)
256 {
257    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
258    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
259    if (!efl_isa(obj, MY_CLASS)) return 0;
260    return exe->flags;
261 }
262 
263 EAPI void
ecore_exe_pause(Ecore_Exe * obj)264 ecore_exe_pause(Ecore_Exe *obj)
265 {
266    efl_control_suspend_set(obj, EINA_TRUE);
267 }
268 
269 EAPI void
ecore_exe_continue(Ecore_Exe * obj)270 ecore_exe_continue(Ecore_Exe *obj)
271 {
272    efl_control_suspend_set(obj, EINA_FALSE);
273 }
274 
275 EOLIAN static void
_ecore_exe_efl_control_suspend_set(Eo * obj EINA_UNUSED,Ecore_Exe_Data * exe,Eina_Bool suspend)276 _ecore_exe_efl_control_suspend_set(Eo *obj EINA_UNUSED, Ecore_Exe_Data *exe, Eina_Bool suspend)
277 {
278    EINA_MAIN_LOOP_CHECK_RETURN;
279    if (suspend) _impl_ecore_exe_pause(obj, exe);
280    else _impl_ecore_exe_continue(obj, exe);
281 }
282 
283 EAPI void
ecore_exe_interrupt(Ecore_Exe * obj)284 ecore_exe_interrupt(Ecore_Exe *obj)
285 {
286    EINA_MAIN_LOOP_CHECK_RETURN;
287    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
288    if (!efl_isa(obj, MY_CLASS)) return;
289    _impl_ecore_exe_interrupt(obj, exe);
290 }
291 
292 EAPI void
ecore_exe_quit(Ecore_Exe * obj)293 ecore_exe_quit(Ecore_Exe *obj)
294 {
295    EINA_MAIN_LOOP_CHECK_RETURN;
296    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
297    if (!efl_isa(obj, MY_CLASS)) return;
298    _impl_ecore_exe_quit(obj, exe);
299 }
300 
301 EAPI void
ecore_exe_terminate(Ecore_Exe * obj)302 ecore_exe_terminate(Ecore_Exe *obj)
303 {
304    EINA_MAIN_LOOP_CHECK_RETURN;
305    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
306    if (!efl_isa(obj, MY_CLASS)) return;
307    _impl_ecore_exe_terminate(obj, exe);
308 }
309 
310 EAPI void
ecore_exe_kill(Ecore_Exe * obj)311 ecore_exe_kill(Ecore_Exe *obj)
312 {
313    EINA_MAIN_LOOP_CHECK_RETURN;
314    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
315    if (!efl_isa(obj, MY_CLASS)) return;
316    _impl_ecore_exe_kill(obj, exe);
317 }
318 
319 EAPI void
ecore_exe_signal(Ecore_Exe * obj,int num)320 ecore_exe_signal(Ecore_Exe *obj,
321                  int        num)
322 {
323    EINA_MAIN_LOOP_CHECK_RETURN;
324    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
325    if (!efl_isa(obj, MY_CLASS)) return;
326    _impl_ecore_exe_signal(obj, exe, num);
327 }
328 
329 EAPI void
ecore_exe_hup(Ecore_Exe * obj)330 ecore_exe_hup(Ecore_Exe *obj)
331 {
332    EINA_MAIN_LOOP_CHECK_RETURN;
333    Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
334    if (!efl_isa(obj, MY_CLASS)) return;
335    _impl_ecore_exe_hup(obj, exe);
336 }
337 
338 void
_ecore_exe_init(void)339 _ecore_exe_init(void)
340 {
341    ECORE_EXE_EVENT_ADD = ecore_event_type_new();
342    ECORE_EXE_EVENT_DEL = ecore_event_type_new();
343    ECORE_EXE_EVENT_DATA = ecore_event_type_new();
344    ECORE_EXE_EVENT_ERROR = ecore_event_type_new();
345 }
346 
347 void
_ecore_exe_shutdown(void)348 _ecore_exe_shutdown(void)
349 {
350    Ecore_Exe *exe = NULL;
351    Eina_List *l1, *l2;
352    Efl_Loop_Data *loop = EFL_LOOP_DATA;
353 
354    EINA_LIST_FOREACH_SAFE(loop->exes, l1, l2, exe)
355       ecore_exe_free(exe);
356 
357    ecore_event_type_flush(ECORE_EXE_EVENT_ADD,
358                           ECORE_EXE_EVENT_DEL,
359                           ECORE_EXE_EVENT_DATA,
360                           ECORE_EXE_EVENT_ERROR);
361 }
362 
363 Ecore_Exe *
_ecore_exe_find(pid_t pid)364 _ecore_exe_find(pid_t pid)
365 {
366    Eina_List *itr;
367    Ecore_Exe *obj;
368    Efl_Loop_Data *loop = EFL_LOOP_DATA;
369 
370    EINA_LIST_FOREACH(loop->exes, itr, obj)
371      {
372         Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS);
373         if (exe->pid == pid) return obj;
374      }
375    return NULL;
376 }
377 
378 void *
_ecore_exe_event_del_new(void)379 _ecore_exe_event_del_new(void)
380 {
381    Ecore_Exe_Event_Del *e = calloc(1, sizeof(Ecore_Exe_Event_Del));
382    return e;
383 }
384 
385 void
_ecore_exe_event_del_free(void * data EINA_UNUSED,void * ev)386 _ecore_exe_event_del_free(void *data EINA_UNUSED,
387                           void *ev)
388 {
389    Ecore_Exe_Event_Del *e = ev;
390    if (e->exe) ecore_exe_free(e->exe);
391    free(e);
392 }
393 
394 void
_ecore_exe_event_exe_data_free(void * data EINA_UNUSED,void * ev)395 _ecore_exe_event_exe_data_free(void *data EINA_UNUSED,
396                                void *ev)
397 {
398    Ecore_Exe_Event_Data *e = ev;
399    ecore_exe_event_data_free(e);
400 }
401 
402 Ecore_Exe_Event_Add *
_ecore_exe_event_add_new(void)403 _ecore_exe_event_add_new(void)
404 {
405    Ecore_Exe_Event_Add *e = calloc(1, sizeof(Ecore_Exe_Event_Add));
406    return e;
407 }
408 
409 void
_ecore_exe_event_add_free(void * data EINA_UNUSED,void * ev)410 _ecore_exe_event_add_free(void *data EINA_UNUSED,
411                           void *ev)
412 {
413    Ecore_Exe_Event_Add *e = ev;
414    free(e);
415 }
416 
417 #include "ecore_exe_eo.c"
418