summaryrefslogtreecommitdiff
path: root/src/modules/ecore/system/systemd/ecore_system_systemd.c
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2013-08-08 20:32:53 -0300
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2013-08-09 14:28:02 -0300
commitc0c5736a4e0d41adc9c97577006c289718c926de (patch)
tree50bc5feedd13d4c4fca49aeb55842008fd3100b7 /src/modules/ecore/system/systemd/ecore_system_systemd.c
parentca39ff976e576dd917becf989f28fdf149c9f1d0 (diff)
ecore: add system modules, implement 'systemd'.
Ecore will now load "system modules" on ecore_init(). The "systemd" module will use DBus to monitor localed, hostnamed and timedated and add system events related to those changes.
Diffstat (limited to '')
-rw-r--r--src/modules/ecore/system/systemd/ecore_system_systemd.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/modules/ecore/system/systemd/ecore_system_systemd.c b/src/modules/ecore/system/systemd/ecore_system_systemd.c
new file mode 100644
index 0000000000..0943775ead
--- /dev/null
+++ b/src/modules/ecore/system/systemd/ecore_system_systemd.c
@@ -0,0 +1,354 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <Eldbus.h>
6#include <Ecore.h>
7#include <locale.h>
8
9static int _log_dom = -1;
10static Eldbus_Connection *_conn = NULL;
11
12static Eina_List *_objs = NULL;
13static Eina_List *_proxies = NULL;
14
15#ifdef CRITICAL
16#undef CRITICAL
17#endif
18#define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
19
20#ifdef ERR
21#undef ERR
22#endif
23#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
24
25#ifdef WRN
26#undef WRN
27#endif
28#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
29
30#ifdef DBG
31#undef DBG
32#endif
33#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
34
35
36static void
37_props_changed_hostname(void *data EINA_UNUSED, const Eldbus_Message *msg)
38{
39 Eldbus_Message_Iter *changed, *entry, *invalidated;
40 const char *iface, *prop;
41
42 if (!eldbus_message_arguments_get(msg, "sa{sv}as",
43 &iface, &changed, &invalidated))
44 {
45 ERR("Error getting data from properties changed signal.");
46 return;
47 }
48
49 while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
50 {
51 const void *key;
52 Eldbus_Message_Iter *var;
53 if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
54 continue;
55 if (strcmp(key, "Hostname") == 0)
56 goto changed_hostname;
57 }
58
59 while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
60 {
61 if (strcmp(prop, "Hostname") == 0)
62 goto changed_hostname;
63 }
64
65 return;
66
67 changed_hostname:
68 ecore_event_add(ECORE_EVENT_HOSTNAME_CHANGED, NULL, NULL, NULL);
69}
70
71static void
72_props_changed_timedate(void *data EINA_UNUSED, const Eldbus_Message *msg)
73{
74 Eldbus_Message_Iter *changed, *entry, *invalidated;
75 const char *iface, *prop;
76
77 if (!eldbus_message_arguments_get(msg, "sa{sv}as",
78 &iface, &changed, &invalidated))
79 {
80 ERR("Error getting data from properties changed signal.");
81 return;
82 }
83
84 while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
85 {
86 const void *key;
87 Eldbus_Message_Iter *var;
88 if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
89 continue;
90 if (strcmp(key, "Timezone") == 0)
91 goto changed_timedate;
92 }
93
94 while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
95 {
96 if (strcmp(prop, "Timezone") == 0)
97 goto changed_timedate;
98 }
99
100 return;
101
102 changed_timedate:
103 ecore_event_add(ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, NULL, NULL, NULL);
104}
105
106struct locale_cat_desc {
107 int cat;
108 int namelen;
109 const char *name;
110};
111
112static const struct locale_cat_desc locale_cat_desc[] = {
113#define CAT(name) {name, sizeof(#name) - 1, #name}
114 CAT(LC_CTYPE),
115 CAT(LC_NUMERIC),
116 CAT(LC_TIME),
117 CAT(LC_COLLATE),
118 CAT(LC_MONETARY),
119 CAT(LC_MESSAGES),
120 CAT(LC_ALL),
121 CAT(LC_PAPER),
122 CAT(LC_NAME),
123 CAT(LC_ADDRESS),
124 CAT(LC_TELEPHONE),
125 CAT(LC_MEASUREMENT),
126 CAT(LC_IDENTIFICATION),
127#undef CAT
128 {-1, -1, NULL}
129};
130
131static int _locale_parse(const char *str, int *cat, const char **value)
132{
133 const struct locale_cat_desc *itr;
134 const char *p = strchr(str, '=');
135 int klen;
136
137 if (!p) goto end;
138
139 klen = p - str;
140 for (itr = locale_cat_desc; itr->name != NULL; itr++)
141 {
142 if ((klen == itr->namelen) && (memcmp(str, itr->name, klen) == 0))
143 {
144 *cat = itr->cat;
145 *value = str + itr->namelen + 1;
146 return itr - locale_cat_desc;
147 }
148 }
149
150 end:
151 *cat = -1;
152 *value = NULL;
153 return -1;
154}
155
156static void _locale_get(void *data EINA_UNUSED, const Eldbus_Message *msg,
157 Eldbus_Pending *pending EINA_UNUSED)
158{
159 Eldbus_Message_Iter *variant, *array;
160 const char *errname, *errmsg, *val;
161 Eina_Bool setlocs[EINA_C_ARRAY_LENGTH(locale_cat_desc)];
162 unsigned int i;
163
164 if (eldbus_message_error_get(msg, &errname, &errmsg))
165 {
166 ERR("Message error %s - %s", errname, errmsg);
167 goto end;
168 }
169 if (!eldbus_message_arguments_get(msg, "v", &variant))
170 {
171 ERR("Error getting arguments.");
172 goto end;
173 }
174
175 if (!eldbus_message_iter_get_and_next(variant, 'a', &array))
176 {
177 ERR("Error getting array.");
178 goto end;
179 }
180
181 memset(setlocs, 0, sizeof(setlocs));
182 while (eldbus_message_iter_get_and_next(array, 's', &val))
183 {
184 int cat, idx;
185 const char *value;
186 idx = _locale_parse(val, &cat, &value);
187 if (idx >= 0)
188 setlocs[idx] = EINA_TRUE;
189 setlocale(cat, value);
190 }
191
192 for (i = 0; i < EINA_C_ARRAY_LENGTH(locale_cat_desc); i++)
193 {
194 if ((!setlocs[i]) && (locale_cat_desc[i].cat != LC_ALL))
195 setlocale(locale_cat_desc[i].cat, "C");
196 }
197
198 end:
199 ecore_event_add(ECORE_EVENT_LOCALE_CHANGED, NULL, NULL, NULL);
200}
201
202static void
203_props_changed_locale(void *data, const Eldbus_Message *msg)
204{
205 Eldbus_Proxy *proxy = data;
206 Eldbus_Message_Iter *changed, *entry, *invalidated;
207 const char *iface, *prop;
208
209 if (!eldbus_message_arguments_get(msg, "sa{sv}as",
210 &iface, &changed, &invalidated))
211 {
212 ERR("Error getting data from properties changed signal.");
213 return;
214 }
215
216 while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
217 {
218 const void *key;
219 Eldbus_Message_Iter *var;
220 if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
221 continue;
222 if (strcmp(key, "Locale") == 0)
223 goto changed_locale;
224 }
225
226 while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
227 {
228 if (strcmp(prop, "Locale") == 0)
229 goto changed_locale;
230 }
231
232 return;
233
234 changed_locale:
235 eldbus_proxy_property_get(proxy, "Locale", _locale_get, NULL);
236}
237
238static Eina_Bool
239_property_change_monitor(const char *name,
240 const char *path,
241 const char *iface,
242 Eldbus_Signal_Cb cb)
243{
244 Eldbus_Object *o;
245 Eldbus_Proxy *p;
246 Eldbus_Signal_Handler *s;
247
248 o = eldbus_object_get(_conn, name, path);
249 if (!o)
250 {
251 ERR("could not get object name=%s, path=%s", name, path);
252 return EINA_FALSE;
253 }
254
255 p = eldbus_proxy_get(o, iface);
256 if (!p)
257 {
258 ERR("could not get proxy interface=%s, name=%s, path=%s",
259 iface, name, path);
260 eldbus_object_unref(o);
261 return EINA_FALSE;
262 }
263
264 s = eldbus_proxy_properties_changed_callback_add(p, cb, p);
265 if (!s)
266 {
267 ERR("could not add signal handler for properties changed for proxy "
268 "interface=%s, name=%s, path=%s", iface, name, path);
269 eldbus_proxy_unref(p);
270 eldbus_object_unref(o);
271 return EINA_FALSE;
272 }
273
274 _objs = eina_list_append(_objs, o);
275 _proxies = eina_list_append(_proxies, p);
276 return EINA_TRUE;
277}
278
279static void _ecore_system_systemd_shutdown(void);
280
281static Eina_Bool
282_ecore_system_systemd_init(void)
283{
284 eldbus_init();
285
286 _log_dom = eina_log_domain_register("ecore_system_systemd", NULL);
287 if (_log_dom < 0)
288 {
289 EINA_LOG_ERR("Could not register log domain: ecore_system_systemd");
290 goto error;
291 }
292
293 _conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
294
295 if (!_property_change_monitor("org.freedesktop.hostname1",
296 "/org/freedesktop/hostname1",
297 "org.freedesktop.hostname1",
298 _props_changed_hostname))
299 goto error;
300
301 if (!_property_change_monitor("org.freedesktop.timedate1",
302 "/org/freedesktop/timedate1",
303 "org.freedesktop.timedate1",
304 _props_changed_timedate))
305 goto error;
306
307 if (!_property_change_monitor("org.freedesktop.locale1",
308 "/org/freedesktop/locale1",
309 "org.freedesktop.locale1",
310 _props_changed_locale))
311 goto error;
312
313 DBG("ecore system 'systemd' loaded");
314 return EINA_TRUE;
315
316 error:
317 _ecore_system_systemd_shutdown();
318 return EINA_FALSE;
319}
320
321static void
322_ecore_system_systemd_shutdown(void)
323{
324 DBG("ecore system 'systemd' unloaded");
325
326 while (_proxies)
327 {
328 eldbus_proxy_unref(_proxies->data);
329 _proxies = eina_list_remove_list(_proxies, _proxies);
330 }
331
332 while (_objs)
333 {
334 eldbus_object_unref(_objs->data);
335 _objs = eina_list_remove_list(_objs, _objs);
336 }
337
338 if (_conn)
339 {
340 eldbus_connection_unref(_conn);
341 _conn = NULL;
342 }
343
344 if (_log_dom > 0)
345 {
346 eina_log_domain_unregister(_log_dom);
347 _log_dom = -1;
348 }
349
350 eldbus_shutdown();
351}
352
353EINA_MODULE_INIT(_ecore_system_systemd_init);
354EINA_MODULE_SHUTDOWN(_ecore_system_systemd_shutdown);