forked from external/yambar
config: dlopen() modules on-demand
TODO: optimizations and proper cleanup * We currently reload the shared library for each *instance* of the module, and we do it twice; once when verifying, and once when instantiating. * The shared libraries are never dlclosed()
This commit is contained in:
parent
731ab848e1
commit
64b77a0efc
4 changed files with 170 additions and 113 deletions
128
config-verify.c
128
config-verify.c
|
@ -3,24 +3,17 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define LOG_MODULE "config:verify"
|
||||
#define LOG_ENABLE_DBG 0
|
||||
#include "log.h"
|
||||
#include "tllist.h"
|
||||
|
||||
#include "modules/alsa/alsa.h"
|
||||
#include "modules/backlight/backlight.h"
|
||||
#include "modules/battery/battery.h"
|
||||
#include "modules/clock/clock.h"
|
||||
#include "modules/i3/i3.h"
|
||||
#include "modules/label/label.h"
|
||||
#include "modules/label/label.h"
|
||||
#include "modules/mpd/mpd.h"
|
||||
#include "modules/network/network.h"
|
||||
#include "modules/removables/removables.h"
|
||||
#include "modules/xkb/xkb.h"
|
||||
#include "modules/xwindow/xwindow.h"
|
||||
|
||||
const char *
|
||||
conf_err_prefix(const keychain_t *chain, const struct yml_node *node)
|
||||
{
|
||||
|
@ -441,42 +434,46 @@ verify_module(keychain_t *chain, const struct yml_node *node)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* TODO: this will dlopened later */
|
||||
static const struct {
|
||||
const char *name;
|
||||
const struct module_info *info;
|
||||
} modules[] = {
|
||||
{"alsa", &module_alsa},
|
||||
{"backlight", &module_backlight},
|
||||
{"battery", &module_battery},
|
||||
{"clock", &module_clock},
|
||||
{"i3", &module_i3},
|
||||
{"label", &module_label},
|
||||
{"mpd", &module_mpd},
|
||||
{"network", &module_network},
|
||||
{"removables", &module_removables},
|
||||
{"xkb", &module_xkb},
|
||||
{"xwindow", &module_xwindow},
|
||||
};
|
||||
char path[1024];
|
||||
snprintf(path, sizeof(path), "./modules/lib%s.so", mod_name);
|
||||
|
||||
for (size_t i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) {
|
||||
if (strcmp(modules[i].name, mod_name) != 0)
|
||||
continue;
|
||||
void *lib = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD);
|
||||
|
||||
if (!conf_verify_dict(chain_push(chain, mod_name),
|
||||
values,
|
||||
modules[i].info->attrs,
|
||||
modules[i].info->attr_count))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lib == NULL)
|
||||
lib = dlopen(path, RTLD_LOCAL | RTLD_NOW);
|
||||
|
||||
chain_pop(chain);
|
||||
return true;
|
||||
if (lib == NULL) {
|
||||
const char *dl_error = dlerror();
|
||||
if (dl_error != NULL)
|
||||
LOG_ERR("%s: dlopen: %s", mod_name, dlerror());
|
||||
else
|
||||
LOG_ERR("%s: invalid module name: %s",
|
||||
conf_err_prefix(chain, module), mod_name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_ERR("%s: invalid module name: %s", conf_err_prefix(chain, module), mod_name);
|
||||
return false;
|
||||
char sym[1024];
|
||||
snprintf(sym, sizeof(sym), "module_%s", mod_name);
|
||||
|
||||
dlerror(); /* Clear previous error */
|
||||
const struct module_info *info = dlsym(lib, sym);
|
||||
|
||||
const char *dlsym_error = dlerror();
|
||||
if (dlsym_error != NULL) {
|
||||
LOG_ERR("%s: dlsym: %s", mod_name, dlsym_error);
|
||||
dlclose(lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(info != NULL);
|
||||
|
||||
if (!conf_verify_dict(chain_push(chain, mod_name), values,
|
||||
info->attrs, info->attr_count))
|
||||
return false;
|
||||
|
||||
chain_pop(chain);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -515,6 +512,45 @@ verify_bar_location(keychain_t *chain, const struct yml_node *node)
|
|||
return conf_verify_enum(chain, node, (const char *[]){"top", "bottom"}, 2);
|
||||
}
|
||||
|
||||
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
|
||||
static void
|
||||
find_modules(void)
|
||||
{
|
||||
int cwd = open(".", O_RDONLY);
|
||||
assert(cwd != -1);
|
||||
|
||||
int modules = openat(cwd, "modules", O_RDONLY);
|
||||
assert(modules != -1);
|
||||
|
||||
DIR *dir = fdopendir(modules);
|
||||
assert(dir != NULL);
|
||||
|
||||
for (struct dirent *e = readdir(dir); e != NULL; e = readdir(dir)) {
|
||||
const size_t len = strlen(e->d_name);
|
||||
|
||||
if (len <= 6) {
|
||||
/* Need at least "libX.so" */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(e->d_name, "lib", 3) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp(&e->d_name[len - 3], ".so") != 0)
|
||||
continue;
|
||||
|
||||
char *name = malloc(len - 6 + 1);
|
||||
memcpy(name, &e->d_name[3], len - 6);
|
||||
name[len - 6] = '\0';
|
||||
|
||||
LOG_DBG("%s", name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
conf_verify_bar(const struct yml_node *bar)
|
||||
{
|
||||
|
@ -523,6 +559,10 @@ conf_verify_bar(const struct yml_node *bar)
|
|||
return false;
|
||||
}
|
||||
|
||||
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
|
||||
find_modules();
|
||||
#endif
|
||||
|
||||
keychain_t chain = tll_init();
|
||||
chain_push(&chain, "bar");
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue