diff --git a/document.c b/document.c index 6525711..34ab250 100644 --- a/document.c +++ b/document.c @@ -1,7 +1,7 @@ /* See LICENSE file for license and copyright information */ #define _BSD_SOURCE -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 // TODO: Implement realpath #include @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include #include "document.h" #include "utils.h" @@ -22,87 +25,98 @@ void zathura_document_plugins_load(zathura_t* zathura) { - /* read all files in the plugin directory */ - DIR* dir = opendir(PLUGIN_DIR); - if (dir == NULL) { - fprintf(stderr, "error: could not open plugin directory: %s\n", PLUGIN_DIR); + girara_list_iterator_t* iter = girara_list_iterator(zathura->plugins.path); + if (iter == NULL) { return; } - struct dirent* entry; - while ((entry = readdir(dir)) != NULL) { - /* check if entry is a file */ - if (entry->d_type != 0x8) { + do + { + char* plugindir = girara_list_iterator_data(iter); + + /* read all files in the plugin directory */ + DIR* dir = opendir(plugindir); + if (dir == NULL) { + girara_error("could not open plugin directory: %s", plugindir); continue; } - void* handle = NULL; - zathura_document_plugin_t* plugin = NULL; - char* path = NULL; + int fddir = dirfd(dir); + struct dirent* entry; + 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 */ - path = string_concat(PLUGIN_DIR, "/", entry->d_name, NULL); + /* check if entry is a file */ + 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) { - goto error_continue; + void* handle = NULL; + 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 */ - handle = dlopen(path, RTLD_NOW); - - if (handle == NULL) { - fprintf(stderr, "error: could not load plugin (%s)\n", dlerror()); - goto error_free; + if (closedir(dir) == -1) { + girara_error("could not close plugin directory %s", plugindir); } - - /* resolve symbol */ - 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); - } + } while (girara_list_iterator_next(iter)); + girara_list_iterator_free(iter); } void diff --git a/document.h b/document.h index 56a3e90..358b945 100644 --- a/document.h +++ b/document.h @@ -9,7 +9,6 @@ #include #include "zathura.h" -#define PLUGIN_DIR "/usr/lib/zathura" #define PLUGIN_REGISTER_FUNCTION "plugin_register" typedef struct zathura_list_s zathura_list_t; diff --git a/zathura.c b/zathura.c index 25d479c..f444c3b 100644 --- a/zathura.c +++ b/zathura.c @@ -33,7 +33,8 @@ zathura_init(int argc, char* argv[]) /* plugins */ 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 */ if ((zathura->ui.session = girara_session_create()) == NULL) { @@ -87,6 +88,58 @@ zathura_init(int argc, char* argv[]) /* girara events */ 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 */ zathura_document_plugins_load(zathura); @@ -135,6 +188,11 @@ zathura_free(zathura_t* zathura) /* free registered plugins */ zathura_document_plugins_free(zathura); 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 diff --git a/zathura.h b/zathura.h index 739cd76..86c17a9 100644 --- a/zathura.h +++ b/zathura.h @@ -59,6 +59,12 @@ typedef struct zathura_s girara_list_t* path; } plugins; + struct + { + gchar* config_dir; + gchar* data_dir; + } config; + zathura_document_t* document; /**> The current document */ } zathura_t;