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.
This commit is contained in:
Gustavo Sverzut Barbieri 2013-08-08 20:32:53 -03:00
parent ca39ff976e
commit c0c5736a4e
7 changed files with 486 additions and 1 deletions

View File

@ -549,6 +549,8 @@ AC_ARG_ENABLE([systemd],
fi
],
[want_systemd="no"])
AM_CONDITIONAL([WANT_SYSTEMD], [test "${want_systemd}" = "yes"])
#### Platform-dependent
DL_LIBS=""

View File

@ -21,6 +21,12 @@ eezefilesdir = $(datadir)/eeze
eezefiles_DATA = eeze/checkme
EXTRA_DIST += $(eezefiles_DATA)
########################################################################
# Ecore
ecorefilesdir = $(datadir)/ecore
ecorefiles_DATA = ecore/checkme
EXTRA_DIST += $(ecorefiles_DATA)
########################################################################
# Ecore_Imf
ecoreimffilesdir = $(datadir)/ecore_imf

1
data/ecore/checkme Normal file
View File

@ -0,0 +1 @@
This is just a test file used to help ecore determine its prefix location.

View File

@ -2,6 +2,8 @@ prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
modules=@libdir@/ecore
module_arch=@MODULE_ARCH@
Name: ecore
Description: Ecore event abstraction library

View File

@ -52,11 +52,41 @@ lib_ecore_libecore_la_SOURCES += lib/ecore/ecore_signal.c lib/ecore/ecore_exe.c
endif
endif
lib_ecore_libecore_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_CFLAGS@
lib_ecore_libecore_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/ecore\" \
-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\" \
@ECORE_CFLAGS@
lib_ecore_libecore_la_LIBADD = @ECORE_LIBS@
lib_ecore_libecore_la_DEPENDENCIES = @ECORE_INTERNAL_LIBS@
lib_ecore_libecore_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
### Modules
# systemd
if WANT_SYSTEMD
ecoresystemdpkgdir = $(libdir)/ecore/system/systemd/$(MODULE_ARCH)
ecoresystemdpkg_LTLIBRARIES = modules/ecore/system/systemd/module.la
modules_ecore_system_systemd_module_la_SOURCES = \
modules/ecore/system/systemd/ecore_system_systemd.c
modules_ecore_system_systemd_module_la_CPPFLAGS = \
-I$(top_builddir)/src/lib/efl \
@ECORE_CFLAGS@ \
@ELDBUS_CFLAGS@
modules_ecore_system_systemd_module_la_LIBADD = \
@USE_ECORE_LIBS@ \
@USE_ELDBUS_LIBS@
modules_ecore_system_systemd_module_la_DEPENDENCIES = \
@USE_ECORE_INTERNAL_LIBS@ \
@USE_ELDBUS_INTERNAL_LIBS@
modules_ecore_system_systemd_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
modules_ecore_system_systemd_module_la_LIBTOOLFLAGS = --tag=disable-static
endif
### Unit tests
if EFL_ENABLE_TESTS

View File

@ -116,6 +116,77 @@ int _ecore_main_lock_count;
# define CODESET "INVALID"
#endif
static Eina_Prefix *_ecore_pfx = NULL;
static Eina_Array *module_list = NULL;
static void
ecore_system_modules_load(void)
{
char buf[PATH_MAX] = "";
char *path;
if (getenv("EFL_RUN_IN_TREE"))
{
struct stat st;
snprintf(buf, sizeof(buf), "%s/src/modules/ecore/system",
PACKAGE_BUILD_DIR);
if (stat(buf, &st) == 0)
{
const char *built_modules[] = {
#ifdef HAVE_SYSTEMD
"systemd",
#endif
NULL
};
const char **itr;
for (itr = built_modules; *itr != NULL; itr++)
{
snprintf(buf, sizeof(buf),
"%s/src/modules/ecore/system/%s/.libs",
PACKAGE_BUILD_DIR, *itr);
module_list = eina_module_list_get(module_list, buf,
EINA_FALSE, NULL, NULL);
}
if (module_list)
eina_module_list_load(module_list);
return;
}
}
path = eina_module_environment_path_get("ECORE_MODULES_DIR",
"/ecore/system");
if (path)
{
module_list = eina_module_arch_list_get(module_list, path, MODULE_ARCH);
free(path);
}
path = eina_module_environment_path_get("HOME", "/.ecore/system");
if (path)
{
module_list = eina_module_arch_list_get(module_list, path, MODULE_ARCH);
free(path);
}
snprintf(buf, sizeof(buf), "%s/ecore/system",
eina_prefix_lib_get(_ecore_pfx));
module_list = eina_module_arch_list_get(module_list, buf, MODULE_ARCH);
eina_module_list_load(module_list);
}
static void
ecore_system_modules_unload(void)
{
if (module_list)
{
eina_module_list_free(module_list);
eina_array_free(module_list);
module_list = NULL;
}
}
/**
* @addtogroup Ecore_Init_Group
*
@ -170,6 +241,16 @@ ecore_init(void)
goto shutdown_log_dom;
}
_ecore_pfx = eina_prefix_new(NULL, ecore_init,
"ECORE", "ecore", "checkme",
PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
if (!_ecore_pfx)
{
ERR("Could not get ecore installation prefix");
goto shutdown_log_dom;
}
eo_init();
if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1;
@ -230,6 +311,9 @@ ecore_init(void)
EINA_LOG_STATE_STOP,
EINA_LOG_STATE_INIT);
ecore_system_modules_load();
return _ecore_init_count;
shutdown_mempool:
@ -273,6 +357,8 @@ ecore_shutdown(void)
if (--_ecore_init_count != 0)
goto unlock;
ecore_system_modules_unload();
eina_log_timing(_ecore_log_dom,
EINA_LOG_STATE_START,
EINA_LOG_STATE_SHUTDOWN);
@ -345,6 +431,10 @@ ecore_shutdown(void)
ecore_mempool_shutdown();
eina_log_domain_unregister(_ecore_log_dom);
_ecore_log_dom = -1;
eina_prefix_free(_ecore_pfx);
_ecore_pfx = NULL;
eina_shutdown();
#ifdef HAVE_EVIL
evil_shutdown();

View File

@ -0,0 +1,354 @@
#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;
#ifdef CRITICAL
#undef CRITICAL
#endif
#define CRITICAL(...) 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);
}
struct locale_cat_desc {
int cat;
int namelen;
const char *name;
};
static const struct locale_cat_desc locale_cat_desc[] = {
#define CAT(name) {name, sizeof(#name) - 1, #name}
CAT(LC_CTYPE),
CAT(LC_NUMERIC),
CAT(LC_TIME),
CAT(LC_COLLATE),
CAT(LC_MONETARY),
CAT(LC_MESSAGES),
CAT(LC_ALL),
CAT(LC_PAPER),
CAT(LC_NAME),
CAT(LC_ADDRESS),
CAT(LC_TELEPHONE),
CAT(LC_MEASUREMENT),
CAT(LC_IDENTIFICATION),
#undef CAT
{-1, -1, NULL}
};
static int _locale_parse(const char *str, int *cat, const char **value)
{
const struct locale_cat_desc *itr;
const char *p = strchr(str, '=');
int klen;
if (!p) goto end;
klen = p - str;
for (itr = locale_cat_desc; itr->name != NULL; itr++)
{
if ((klen == itr->namelen) && (memcmp(str, itr->name, klen) == 0))
{
*cat = itr->cat;
*value = str + itr->namelen + 1;
return itr - locale_cat_desc;
}
}
end:
*cat = -1;
*value = NULL;
return -1;
}
static void _locale_get(void *data EINA_UNUSED, const Eldbus_Message *msg,
Eldbus_Pending *pending EINA_UNUSED)
{
Eldbus_Message_Iter *variant, *array;
const char *errname, *errmsg, *val;
Eina_Bool setlocs[EINA_C_ARRAY_LENGTH(locale_cat_desc)];
unsigned int i;
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;
}
memset(setlocs, 0, sizeof(setlocs));
while (eldbus_message_iter_get_and_next(array, 's', &val))
{
int cat, idx;
const char *value;
idx = _locale_parse(val, &cat, &value);
if (idx >= 0)
setlocs[idx] = EINA_TRUE;
setlocale(cat, value);
}
for (i = 0; i < EINA_C_ARRAY_LENGTH(locale_cat_desc); i++)
{
if ((!setlocs[i]) && (locale_cat_desc[i].cat != LC_ALL))
setlocale(locale_cat_desc[i].cat, "C");
}
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;
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:
eldbus_proxy_property_get(proxy, "Locale", _locale_get, NULL);
}
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)
{
eldbus_init();
_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)
{
DBG("ecore system 'systemd' unloaded");
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;
}
eldbus_shutdown();
}
EINA_MODULE_INIT(_ecore_system_systemd_init);
EINA_MODULE_SHUTDOWN(_ecore_system_systemd_shutdown);