mirror of
https://git.pwmt.org/pwmt/zathura.git
synced 2025-01-30 14:24:56 +01:00
Make plugin path configurable
* We don't fail if we can't load a plugin. There can be anything. * Reintroduce the command line parser from glib. * Use fstatat as it is more reliable than d_type from dirent.
This commit is contained in:
parent
fdf0bd5649
commit
b2fc17207e
4 changed files with 150 additions and 73 deletions
156
document.c
156
document.c
|
@ -1,7 +1,7 @@
|
||||||
/* See LICENSE file for license and copyright information */
|
/* See LICENSE file for license and copyright information */
|
||||||
|
|
||||||
#define _BSD_SOURCE
|
#define _BSD_SOURCE
|
||||||
#define _XOPEN_SOURCE 500
|
#define _XOPEN_SOURCE 700
|
||||||
// TODO: Implement realpath
|
// TODO: Implement realpath
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -11,6 +11,9 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -22,87 +25,98 @@
|
||||||
void
|
void
|
||||||
zathura_document_plugins_load(zathura_t* zathura)
|
zathura_document_plugins_load(zathura_t* zathura)
|
||||||
{
|
{
|
||||||
/* read all files in the plugin directory */
|
girara_list_iterator_t* iter = girara_list_iterator(zathura->plugins.path);
|
||||||
DIR* dir = opendir(PLUGIN_DIR);
|
if (iter == NULL) {
|
||||||
if (dir == NULL) {
|
|
||||||
fprintf(stderr, "error: could not open plugin directory: %s\n", PLUGIN_DIR);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dirent* entry;
|
do
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
{
|
||||||
/* check if entry is a file */
|
char* plugindir = girara_list_iterator_data(iter);
|
||||||
if (entry->d_type != 0x8) {
|
|
||||||
|
/* read all files in the plugin directory */
|
||||||
|
DIR* dir = opendir(plugindir);
|
||||||
|
if (dir == NULL) {
|
||||||
|
girara_error("could not open plugin directory: %s", plugindir);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* handle = NULL;
|
int fddir = dirfd(dir);
|
||||||
zathura_document_plugin_t* plugin = NULL;
|
struct dirent* entry;
|
||||||
char* path = NULL;
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
struct stat statbuf;
|
||||||
|
if (fstatat(fddir, entry->d_name, &statbuf, 0) != 0) {
|
||||||
|
girara_error("failed to fstatat %s/%s; errno is %d.", plugindir, entry->d_name, errno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* get full path */
|
/* check if entry is a file */
|
||||||
path = string_concat(PLUGIN_DIR, "/", entry->d_name, NULL);
|
if (S_ISREG(statbuf.st_mode) == 0) {
|
||||||
|
girara_info("%s/%s is not a regular file. Skipping.", plugindir, entry->d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (path == NULL) {
|
void* handle = NULL;
|
||||||
goto error_continue;
|
zathura_document_plugin_t* plugin = NULL;
|
||||||
|
char* path = NULL;
|
||||||
|
|
||||||
|
/* get full path */
|
||||||
|
path = g_build_filename(plugindir, entry->d_name, NULL);
|
||||||
|
if (path == NULL) {
|
||||||
|
g_error("failed to allocate memory!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load plugin */
|
||||||
|
handle = dlopen(path, RTLD_NOW);
|
||||||
|
if (handle == NULL) {
|
||||||
|
girara_error("could not load plugin %s (%s)", path, dlerror());
|
||||||
|
g_free(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* resolve symbol */
|
||||||
|
zathura_plugin_register_service_t register_plugin;
|
||||||
|
*(void**)(®ister_plugin) = dlsym(handle, PLUGIN_REGISTER_FUNCTION);
|
||||||
|
|
||||||
|
if (register_plugin == NULL) {
|
||||||
|
girara_error("could not find '%s' function in plugin %s", PLUGIN_REGISTER_FUNCTION, path);
|
||||||
|
g_free(path);
|
||||||
|
dlclose(handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin = malloc(sizeof(zathura_document_plugin_t));
|
||||||
|
|
||||||
|
if (plugin == NULL) {
|
||||||
|
g_error("failed to allocate memory!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin->file_extension = NULL;
|
||||||
|
plugin->open_function = NULL;
|
||||||
|
|
||||||
|
register_plugin(plugin);
|
||||||
|
|
||||||
|
bool r = zathura_document_plugin_register(zathura, plugin, handle);
|
||||||
|
|
||||||
|
if (r == false) {
|
||||||
|
girara_error("could not register plugin %s", path);
|
||||||
|
free(plugin);
|
||||||
|
dlclose(handle);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
girara_info("successfully loaded plugin %s", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load plugin */
|
if (closedir(dir) == -1) {
|
||||||
handle = dlopen(path, RTLD_NOW);
|
girara_error("could not close plugin directory %s", plugindir);
|
||||||
|
|
||||||
if (handle == NULL) {
|
|
||||||
fprintf(stderr, "error: could not load plugin (%s)\n", dlerror());
|
|
||||||
goto error_free;
|
|
||||||
}
|
}
|
||||||
|
} while (girara_list_iterator_next(iter));
|
||||||
/* resolve symbol */
|
girara_list_iterator_free(iter);
|
||||||
zathura_plugin_register_service_t register_plugin;
|
|
||||||
*(void**)(®ister_plugin) = dlsym(handle, PLUGIN_REGISTER_FUNCTION);
|
|
||||||
|
|
||||||
if (register_plugin == NULL) {
|
|
||||||
fprintf(stderr, "error: could not find '%s' function in the plugin\n", PLUGIN_REGISTER_FUNCTION);
|
|
||||||
goto error_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin = malloc(sizeof(zathura_document_plugin_t));
|
|
||||||
|
|
||||||
if (plugin == NULL) {
|
|
||||||
goto error_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin->file_extension = NULL;
|
|
||||||
plugin->open_function = NULL;
|
|
||||||
|
|
||||||
register_plugin(plugin);
|
|
||||||
|
|
||||||
bool r = zathura_document_plugin_register(zathura, plugin, handle);
|
|
||||||
|
|
||||||
if (r == false) {
|
|
||||||
fprintf(stderr, "error: could not register plugin (%s)\n", path);
|
|
||||||
goto error_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
|
|
||||||
error_free:
|
|
||||||
|
|
||||||
free(path);
|
|
||||||
free(plugin);
|
|
||||||
|
|
||||||
if (handle) {
|
|
||||||
dlclose(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
error_continue:
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closedir(dir) == -1) {
|
|
||||||
fprintf(stderr, "error: could not close plugin directory: %s\n", PLUGIN_DIR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <girara-datastructures.h>
|
#include <girara-datastructures.h>
|
||||||
#include "zathura.h"
|
#include "zathura.h"
|
||||||
|
|
||||||
#define PLUGIN_DIR "/usr/lib/zathura"
|
|
||||||
#define PLUGIN_REGISTER_FUNCTION "plugin_register"
|
#define PLUGIN_REGISTER_FUNCTION "plugin_register"
|
||||||
|
|
||||||
typedef struct zathura_list_s zathura_list_t;
|
typedef struct zathura_list_s zathura_list_t;
|
||||||
|
|
60
zathura.c
60
zathura.c
|
@ -33,7 +33,8 @@ zathura_init(int argc, char* argv[])
|
||||||
|
|
||||||
/* plugins */
|
/* plugins */
|
||||||
zathura->plugins.plugins = girara_list_new();
|
zathura->plugins.plugins = girara_list_new();
|
||||||
zathura->plugins.path = NULL;
|
zathura->plugins.path = girara_list_new();
|
||||||
|
girara_list_set_free_function(zathura->plugins.path, g_free);
|
||||||
|
|
||||||
/* UI */
|
/* UI */
|
||||||
if ((zathura->ui.session = girara_session_create()) == NULL) {
|
if ((zathura->ui.session = girara_session_create()) == NULL) {
|
||||||
|
@ -87,6 +88,58 @@ zathura_init(int argc, char* argv[])
|
||||||
/* girara events */
|
/* girara events */
|
||||||
zathura->ui.session->events.buffer_changed = buffer_changed;
|
zathura->ui.session->events.buffer_changed = buffer_changed;
|
||||||
|
|
||||||
|
/* parse command line options */
|
||||||
|
gchar* config_dir = NULL, *data_dir = NULL, *plugin_path = NULL;
|
||||||
|
GOptionEntry entries[] =
|
||||||
|
{
|
||||||
|
/* { "reparent", 'e', 0, G_OPTION_ARG_INT, &Zathura.UI.embed, "Reparents to window specified by xid", "xid" }, */
|
||||||
|
{ "config-dir", 'c', 0, G_OPTION_ARG_FILENAME, &config_dir, "Path to the config directory", "path" },
|
||||||
|
{ "data-dir", 'd', 0, G_OPTION_ARG_FILENAME, &data_dir, "Path to the data directory", "path" },
|
||||||
|
{ "plugins-dir", 'p', 0, G_OPTION_ARG_STRING, &plugin_path, "Path to the directories containing plugins", "path" },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
GOptionContext* context = g_option_context_new(" [file] [password]");
|
||||||
|
g_option_context_add_main_entries(context, entries, NULL);
|
||||||
|
|
||||||
|
GError* error = NULL;
|
||||||
|
if (!g_option_context_parse(context, &argc, &argv, &error))
|
||||||
|
{
|
||||||
|
printf("Error parsing command line arguments: %s\n", error->message);
|
||||||
|
g_option_context_free(context);
|
||||||
|
g_error_free(error);
|
||||||
|
goto error_free;
|
||||||
|
}
|
||||||
|
g_option_context_free(context);
|
||||||
|
|
||||||
|
if (config_dir) {
|
||||||
|
zathura->config.config_dir = g_strdup(config_dir);
|
||||||
|
} else {
|
||||||
|
gchar* path = girara_get_xdg_path(XDG_CONFIG);
|
||||||
|
zathura->config.config_dir = g_build_filename(path, "zathura", NULL);
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_dir) {
|
||||||
|
zathura->config.data_dir = g_strdup(config_dir);
|
||||||
|
} else {
|
||||||
|
gchar* path = girara_get_xdg_path(XDG_DATA);
|
||||||
|
zathura->config.config_dir = g_build_filename(path, "zathura", NULL);
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plugin_path) {
|
||||||
|
gchar** paths = g_strsplit(plugin_path, ":", 0);
|
||||||
|
for (unsigned int i = 0; paths[i] != '\0'; ++i) {
|
||||||
|
girara_list_append(zathura->plugins.path, g_strdup(paths[i]));
|
||||||
|
}
|
||||||
|
g_strfreev(paths);
|
||||||
|
} else {
|
||||||
|
/* XXX: this shouldn't be hard coded! */
|
||||||
|
girara_list_append(zathura->plugins.path, g_strdup("/usr/local/lib/zathura"));
|
||||||
|
girara_list_append(zathura->plugins.path, g_strdup("/usr/lib/zathura"));
|
||||||
|
}
|
||||||
|
|
||||||
/* load plugins */
|
/* load plugins */
|
||||||
zathura_document_plugins_load(zathura);
|
zathura_document_plugins_load(zathura);
|
||||||
|
|
||||||
|
@ -135,6 +188,11 @@ zathura_free(zathura_t* zathura)
|
||||||
/* free registered plugins */
|
/* free registered plugins */
|
||||||
zathura_document_plugins_free(zathura);
|
zathura_document_plugins_free(zathura);
|
||||||
girara_list_free(zathura->plugins.plugins);
|
girara_list_free(zathura->plugins.plugins);
|
||||||
|
girara_list_free(zathura->plugins.path);
|
||||||
|
|
||||||
|
/* free config variables */
|
||||||
|
g_free(zathura->config.config_dir);
|
||||||
|
g_free(zathura->config.data_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|
|
@ -59,6 +59,12 @@ typedef struct zathura_s
|
||||||
girara_list_t* path;
|
girara_list_t* path;
|
||||||
} plugins;
|
} plugins;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
gchar* config_dir;
|
||||||
|
gchar* data_dir;
|
||||||
|
} config;
|
||||||
|
|
||||||
zathura_document_t* document; /**> The current document */
|
zathura_document_t* document; /**> The current document */
|
||||||
} zathura_t;
|
} zathura_t;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue