1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #ifdef _WIN32
6 # include <evil_private.h> /* setenv */
7 #endif
8
9 #include <Ecore.h>
10 #include <Ecore_Ipc.h>
11
12 #include "efreetd.h"
13 #include "efreetd_cache.h"
14
15 extern FILE *efreetd_log_file;
16
17 static int init = 0;
18 static Ecore_Ipc_Server *ipc = NULL;
19 static Ecore_Event_Handler *hnd_add = NULL;
20 static Ecore_Event_Handler *hnd_del = NULL;
21 static Ecore_Event_Handler *hnd_data = NULL;
22 static int clients = 0;
23 static Ecore_Timer *quit_timer_start = NULL;
24 static Ecore_Timer *quit_timer = NULL;
25
26 static Eina_Bool
_cb_quit_timer(void * data EINA_UNUSED)27 _cb_quit_timer(void *data EINA_UNUSED)
28 {
29 quit_timer = NULL;
30 quit();
31 return EINA_FALSE;
32 }
33
34 static Eina_Bool
_cb_quit_timer_start(void * data EINA_UNUSED)35 _cb_quit_timer_start(void *data EINA_UNUSED)
36 {
37 quit_timer_start = NULL;
38 if (quit_timer) ecore_timer_del(quit_timer);
39 quit_timer = ecore_timer_add(10.0, _cb_quit_timer, NULL);
40 return EINA_FALSE;
41 }
42
43 static void
_broadcast(Ecore_Ipc_Server * svr,int major,int minor,void * data,int size)44 _broadcast(Ecore_Ipc_Server *svr, int major, int minor, void *data, int size)
45 {
46 Eina_List *ipc_clients = ecore_ipc_server_clients_get(svr);
47 Eina_List *l;
48 Ecore_Ipc_Client *cl;
49
50 EINA_LIST_FOREACH(ipc_clients, l, cl)
51 {
52 fprintf(efreetd_log_file, "[%09.3f] Client broadcast %i.%i\n", ecore_time_get(), major, minor);
53 fflush(efreetd_log_file);
54 ecore_ipc_client_send(cl, major, minor, 0, 0, 0, data, size);
55 }
56 }
57
58 static char *
_parse_str(void * data,int size)59 _parse_str(void *data, int size)
60 {
61 char *str = malloc(size + 1);
62 if (!str) return NULL;
63 memcpy(str, data, size);
64 str[size] = 0;
65 return str;
66 }
67
68 static Eina_List *
_parse_strs(void * data,int size)69 _parse_strs(void *data, int size)
70 {
71 Eina_List *list = NULL;
72 char *p, *p0 = NULL, *p1 = NULL, *e = (char *)data + size;
73
74 for (p = data; p < e; p++)
75 {
76 if (!p0)
77 {
78 if (*p)
79 {
80 p0 = p;
81 p1 = e;
82 }
83 }
84 if ((!*p) && (p0))
85 {
86 p1 = strdup(p0);
87 if (p1) list = eina_list_append(list, p1);
88 p0 = NULL;
89 }
90 }
91 if (p0)
92 {
93 p = malloc(p1 - p0 + 1);
94 if (p)
95 {
96 memcpy(p, p0, p1 - p0);
97 p[p1 - p0] = 0;
98 list = eina_list_append(list, p);
99 }
100 }
101 return list;
102 }
103
104 #define IPC_HEAD(_type) \
105 Ecore_Ipc_Event_Client_##_type *e = event; \
106 if (ecore_ipc_client_server_get(e->client) != ipc) \
107 return ECORE_CALLBACK_PASS_ON
108
109 static Eina_Bool
_cb_client_add(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)110 _cb_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
111 {
112 IPC_HEAD(Add);
113 if (quit_timer)
114 {
115 ecore_timer_del(quit_timer);
116 quit_timer = NULL;
117 }
118 if (quit_timer_start)
119 {
120 ecore_timer_del(quit_timer_start);
121 quit_timer_start = NULL;
122 }
123 clients++;
124 fprintf(efreetd_log_file, "[%09.3f] Add client (count=%i)\n", ecore_time_get(),
125 clients);
126 fflush(efreetd_log_file);
127 return ECORE_CALLBACK_DONE;
128 }
129
130 static Eina_Bool
_cb_client_del(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)131 _cb_client_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
132 {
133 IPC_HEAD(Del);
134 clients--;
135 fprintf(efreetd_log_file, "[%09.3f] Del client (count=%i)\n", ecore_time_get(),
136 clients);
137 fflush(efreetd_log_file);
138 if (clients == 0)
139 {
140 if (quit_timer) ecore_timer_del(quit_timer);
141 quit_timer = ecore_timer_add(2.0, _cb_quit_timer, NULL);
142 }
143 return ECORE_CALLBACK_DONE;
144 }
145
146 static Eina_Bool
_cb_client_data(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)147 _cb_client_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
148 {
149 Eina_List *strs;
150 char *s;
151 IPC_HEAD(Data);
152 if (e->major == 1) // register lang
153 { // input: str -> lang
154 fprintf(efreetd_log_file, "[%09.3f] Client register lang\n", ecore_time_get());
155 fflush(efreetd_log_file);
156 if ((s = _parse_str(e->data, e->size)))
157 {
158 setenv("LANG", s, 1);
159 free(s);
160 }
161 // return if desktop cache exists (bool as minor)
162 ecore_ipc_client_send(e->client, 1 /* register reply */,
163 cache_desktop_exists(), 0, 0, 0, NULL, 0);
164 }
165 else if (e->major == 2) // add desktop dirs
166 { // input: array of str -> dirs
167 fprintf(efreetd_log_file, "[%09.3f] Client add desktop dirs\n", ecore_time_get());
168 fflush(efreetd_log_file);
169 strs = _parse_strs(e->data, e->size);
170 EINA_LIST_FREE(strs, s)
171 {
172 cache_desktop_dir_add(s);
173 free(s);
174 }
175 }
176 else if (e->major == 3) // build desktop cache
177 { // input: str -> lang
178 fprintf(efreetd_log_file, "[%09.3f] Client update desktop cache\n", ecore_time_get());
179 fflush(efreetd_log_file);
180 if ((s = _parse_str(e->data, e->size)))
181 {
182 setenv("LANG", s, 1);
183 free(s);
184 }
185 cache_desktop_update();
186 }
187 else if (e->major == 4) // add icon dirs
188 { // input: array of str -> dirs
189 fprintf(efreetd_log_file, "[%09.3f] Client add icon dirs\n", ecore_time_get());
190 fflush(efreetd_log_file);
191 strs = _parse_strs(e->data, e->size);
192 EINA_LIST_FREE(strs, s)
193 {
194 cache_icon_dir_add(s);
195 free(s);
196 }
197 }
198 else if (e->major == 5) // add icon exts
199 { // input: array of str -> exts
200 fprintf(efreetd_log_file, "[%09.3f] Client add icon exts\n", ecore_time_get());
201 fflush(efreetd_log_file);
202 strs = _parse_strs(e->data, e->size);
203 EINA_LIST_FREE(strs, s)
204 {
205 cache_icon_ext_add(s);
206 free(s);
207 }
208 }
209 return ECORE_CALLBACK_DONE;
210 }
211
212 ///////////////////////////////////////////////////////////////////////////
213
214 void
send_signal_icon_cache_update(Eina_Bool update)215 send_signal_icon_cache_update(Eina_Bool update)
216 {
217 _broadcast(ipc, 2 /* icon cache update */, update, NULL, 0);
218 }
219
220 void
send_signal_desktop_cache_update(Eina_Bool update)221 send_signal_desktop_cache_update(Eina_Bool update)
222 {
223 _broadcast(ipc, 3 /* desktop cache update */, update, NULL, 0);
224 }
225
226 void
send_signal_desktop_cache_build(void)227 send_signal_desktop_cache_build(void)
228 {
229 _broadcast(ipc, 1 /* desktop cache build */, 1, NULL, 0);
230 }
231
232 void
send_signal_mime_cache_build(void)233 send_signal_mime_cache_build(void)
234 {
235 _broadcast(ipc, 4 /* mime cache build */, 1, NULL, 0);
236 }
237
238 Eina_Bool
ipc_init(void)239 ipc_init(void)
240 {
241 if (init > 0) return EINA_TRUE;
242 if (!ecore_ipc_init()) return EINA_FALSE;
243 ipc = ecore_ipc_server_add(ECORE_IPC_LOCAL_USER, "efreetd", 0, NULL);
244 if (!ipc)
245 {
246 ecore_ipc_shutdown();
247 return EINA_FALSE;
248 }
249 quit_timer_start = ecore_timer_add(10.0, _cb_quit_timer_start, NULL);
250 hnd_add = ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_ADD,
251 _cb_client_add, NULL);
252 hnd_del = ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DEL,
253 _cb_client_del, NULL);
254 hnd_data = ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DATA,
255 _cb_client_data, NULL);
256 init++;
257 return EINA_TRUE;
258 }
259
260 Eina_Bool
ipc_shutdown(void)261 ipc_shutdown(void)
262 {
263 if (init <= 0) return EINA_TRUE;
264 init--;
265 if (init > 0) return EINA_TRUE;
266 if (quit_timer) ecore_timer_del(quit_timer);
267 if (quit_timer_start) ecore_timer_del(quit_timer_start);
268 quit_timer = NULL;
269 quit_timer_start = NULL;
270 ecore_ipc_server_del(ipc);
271 ecore_event_handler_del(hnd_add);
272 ecore_event_handler_del(hnd_del);
273 ecore_event_handler_del(hnd_data);
274 ipc = NULL;
275 hnd_add = NULL;
276 hnd_del = NULL;
277 hnd_data = NULL;
278 ecore_ipc_shutdown();
279 return EINA_TRUE;
280 }
281
282