348 lines
8.6 KiB
C
348 lines
8.6 KiB
C
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <Eldbus.h>
|
|
#include <Ecore.h>
|
|
#include <locale.h>
|
|
|
|
static int _log_dom = -1;
|
|
static Eldbus_Connection *_conn = NULL;
|
|
|
|
static Eina_List *_objs = NULL;
|
|
static Eina_List *_proxies = NULL;
|
|
static Eina_List *_eldbus_pending = NULL;
|
|
|
|
#ifdef CRI
|
|
#undef CRI
|
|
#endif
|
|
#define CRI(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
|
|
|
|
#ifdef ERR
|
|
#undef ERR
|
|
#endif
|
|
#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
|
|
|
|
#ifdef WRN
|
|
#undef WRN
|
|
#endif
|
|
#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
|
|
|
|
#ifdef DBG
|
|
#undef DBG
|
|
#endif
|
|
#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
|
|
|
|
|
|
static void
|
|
_props_changed_hostname(void *data EINA_UNUSED, const Eldbus_Message *msg)
|
|
{
|
|
Eldbus_Message_Iter *changed, *entry, *invalidated;
|
|
const char *iface, *prop;
|
|
|
|
if (!eldbus_message_arguments_get(msg, "sa{sv}as",
|
|
&iface, &changed, &invalidated))
|
|
{
|
|
ERR("Error getting data from properties changed signal.");
|
|
return;
|
|
}
|
|
|
|
while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
|
|
{
|
|
const void *key;
|
|
Eldbus_Message_Iter *var;
|
|
if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
|
|
continue;
|
|
if (strcmp(key, "Hostname") == 0)
|
|
goto changed_hostname;
|
|
}
|
|
|
|
while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
|
|
{
|
|
if (strcmp(prop, "Hostname") == 0)
|
|
goto changed_hostname;
|
|
}
|
|
|
|
return;
|
|
|
|
changed_hostname:
|
|
ecore_event_add(ECORE_EVENT_HOSTNAME_CHANGED, NULL, NULL, NULL);
|
|
}
|
|
|
|
static void
|
|
_props_changed_timedate(void *data EINA_UNUSED, const Eldbus_Message *msg)
|
|
{
|
|
Eldbus_Message_Iter *changed, *entry, *invalidated;
|
|
const char *iface, *prop;
|
|
|
|
if (!eldbus_message_arguments_get(msg, "sa{sv}as",
|
|
&iface, &changed, &invalidated))
|
|
{
|
|
ERR("Error getting data from properties changed signal.");
|
|
return;
|
|
}
|
|
|
|
while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
|
|
{
|
|
const void *key;
|
|
Eldbus_Message_Iter *var;
|
|
if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
|
|
continue;
|
|
if (strcmp(key, "Timezone") == 0)
|
|
goto changed_timedate;
|
|
}
|
|
|
|
while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
|
|
{
|
|
if (strcmp(prop, "Timezone") == 0)
|
|
goto changed_timedate;
|
|
}
|
|
|
|
return;
|
|
|
|
changed_timedate:
|
|
ecore_event_add(ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, NULL, NULL, NULL);
|
|
}
|
|
|
|
static void _locale_envs_unset(void)
|
|
{
|
|
unsetenv("LC_CTYPE");
|
|
unsetenv("LC_NUMERIC");
|
|
unsetenv("LC_TIME");
|
|
unsetenv("LC_COLLATE");
|
|
unsetenv("LC_MONETARY");
|
|
unsetenv("LC_MESSAGES");
|
|
unsetenv("LC_ALL");
|
|
unsetenv("LC_PAPER");
|
|
unsetenv("LC_NAME");
|
|
unsetenv("LC_ADDRESS");
|
|
unsetenv("LC_TELEPHONE");
|
|
unsetenv("LC_MEASUREMENT");
|
|
unsetenv("LC_IDENTIFICATION");
|
|
}
|
|
|
|
static void _locale_get(void *data EINA_UNUSED, const Eldbus_Message *msg,
|
|
Eldbus_Pending *pending)
|
|
{
|
|
Eldbus_Message_Iter *variant, *array;
|
|
const char *errname, *errmsg, *val;
|
|
|
|
_eldbus_pending = eina_list_remove(_eldbus_pending, pending);
|
|
if (eldbus_message_error_get(msg, &errname, &errmsg))
|
|
{
|
|
ERR("Message error %s - %s", errname, errmsg);
|
|
goto end;
|
|
}
|
|
if (!eldbus_message_arguments_get(msg, "v", &variant))
|
|
{
|
|
ERR("Error getting arguments.");
|
|
goto end;
|
|
}
|
|
|
|
if (!eldbus_message_iter_get_and_next(variant, 'a', &array))
|
|
{
|
|
ERR("Error getting array.");
|
|
goto end;
|
|
}
|
|
|
|
_locale_envs_unset();
|
|
|
|
while (eldbus_message_iter_get_and_next(array, 's', &val))
|
|
{
|
|
char buf[1024], *value, *type;
|
|
|
|
snprintf(buf, sizeof(buf), "%s", val);
|
|
|
|
type = buf;
|
|
|
|
value = strchr(buf, '=');
|
|
if (!value)
|
|
continue;
|
|
*value = 0;
|
|
value++;
|
|
|
|
setenv(type, value, 1);
|
|
}
|
|
setlocale(LC_ALL, "");
|
|
|
|
end:
|
|
ecore_event_add(ECORE_EVENT_LOCALE_CHANGED, NULL, NULL, NULL);
|
|
}
|
|
|
|
static void
|
|
_props_changed_locale(void *data, const Eldbus_Message *msg)
|
|
{
|
|
Eldbus_Proxy *proxy = data;
|
|
Eldbus_Message_Iter *changed, *entry, *invalidated;
|
|
const char *iface, *prop;
|
|
Eldbus_Pending *pend;
|
|
|
|
if (!eldbus_message_arguments_get(msg, "sa{sv}as",
|
|
&iface, &changed, &invalidated))
|
|
{
|
|
ERR("Error getting data from properties changed signal.");
|
|
return;
|
|
}
|
|
|
|
while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
|
|
{
|
|
const void *key;
|
|
Eldbus_Message_Iter *var;
|
|
if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
|
|
continue;
|
|
if (strcmp(key, "Locale") == 0)
|
|
goto changed_locale;
|
|
}
|
|
|
|
while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
|
|
{
|
|
if (strcmp(prop, "Locale") == 0)
|
|
goto changed_locale;
|
|
}
|
|
|
|
return;
|
|
|
|
changed_locale:
|
|
pend = eldbus_proxy_property_get(proxy, "Locale", _locale_get, NULL);
|
|
_eldbus_pending = eina_list_append(_eldbus_pending, pend);
|
|
}
|
|
|
|
static Eina_Bool
|
|
_property_change_monitor(const char *name,
|
|
const char *path,
|
|
const char *iface,
|
|
Eldbus_Signal_Cb cb)
|
|
{
|
|
Eldbus_Object *o;
|
|
Eldbus_Proxy *p;
|
|
Eldbus_Signal_Handler *s;
|
|
|
|
o = eldbus_object_get(_conn, name, path);
|
|
if (!o)
|
|
{
|
|
ERR("could not get object name=%s, path=%s", name, path);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
p = eldbus_proxy_get(o, iface);
|
|
if (!p)
|
|
{
|
|
ERR("could not get proxy interface=%s, name=%s, path=%s",
|
|
iface, name, path);
|
|
eldbus_object_unref(o);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
s = eldbus_proxy_properties_changed_callback_add(p, cb, p);
|
|
if (!s)
|
|
{
|
|
ERR("could not add signal handler for properties changed for proxy "
|
|
"interface=%s, name=%s, path=%s", iface, name, path);
|
|
eldbus_proxy_unref(p);
|
|
eldbus_object_unref(o);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
_objs = eina_list_append(_objs, o);
|
|
_proxies = eina_list_append(_proxies, p);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static void _ecore_system_systemd_shutdown(void);
|
|
static Eina_Bool _ecore_system_systemd_init(void);
|
|
static unsigned int reseting = 0;
|
|
|
|
static void
|
|
_ecore_system_systemd_reset()
|
|
{
|
|
reseting = 1;
|
|
_ecore_system_systemd_shutdown();
|
|
_ecore_system_systemd_init();
|
|
reseting = 0;
|
|
}
|
|
static Eina_Bool
|
|
_ecore_system_systemd_init(void)
|
|
{
|
|
eldbus_init();
|
|
if (!reseting)
|
|
ecore_fork_reset_callback_add(_ecore_system_systemd_reset, NULL);
|
|
|
|
_log_dom = eina_log_domain_register("ecore_system_systemd", NULL);
|
|
if (_log_dom < 0)
|
|
{
|
|
EINA_LOG_ERR("Could not register log domain: ecore_system_systemd");
|
|
goto error;
|
|
}
|
|
|
|
_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
|
|
|
|
if (!_property_change_monitor("org.freedesktop.hostname1",
|
|
"/org/freedesktop/hostname1",
|
|
"org.freedesktop.hostname1",
|
|
_props_changed_hostname))
|
|
goto error;
|
|
|
|
if (!_property_change_monitor("org.freedesktop.timedate1",
|
|
"/org/freedesktop/timedate1",
|
|
"org.freedesktop.timedate1",
|
|
_props_changed_timedate))
|
|
goto error;
|
|
|
|
if (!_property_change_monitor("org.freedesktop.locale1",
|
|
"/org/freedesktop/locale1",
|
|
"org.freedesktop.locale1",
|
|
_props_changed_locale))
|
|
goto error;
|
|
|
|
DBG("ecore system 'systemd' loaded");
|
|
return EINA_TRUE;
|
|
|
|
error:
|
|
_ecore_system_systemd_shutdown();
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
static void
|
|
_ecore_system_systemd_shutdown(void)
|
|
{
|
|
Eldbus_Pending *pend;
|
|
|
|
DBG("ecore system 'systemd' unloaded");
|
|
if (!reseting)
|
|
ecore_fork_reset_callback_del(_ecore_system_systemd_reset, NULL);
|
|
|
|
while (_proxies)
|
|
{
|
|
eldbus_proxy_unref(_proxies->data);
|
|
_proxies = eina_list_remove_list(_proxies, _proxies);
|
|
}
|
|
|
|
while (_objs)
|
|
{
|
|
eldbus_object_unref(_objs->data);
|
|
_objs = eina_list_remove_list(_objs, _objs);
|
|
}
|
|
|
|
if (_conn)
|
|
{
|
|
eldbus_connection_unref(_conn);
|
|
_conn = NULL;
|
|
}
|
|
|
|
if (_log_dom > 0)
|
|
{
|
|
eina_log_domain_unregister(_log_dom);
|
|
_log_dom = -1;
|
|
}
|
|
|
|
EINA_LIST_FREE(_eldbus_pending, pend)
|
|
{
|
|
eldbus_pending_cancel(pend);
|
|
}
|
|
|
|
eldbus_shutdown();
|
|
}
|
|
|
|
EINA_MODULE_INIT(_ecore_system_systemd_init);
|
|
EINA_MODULE_SHUTDOWN(_ecore_system_systemd_shutdown);
|