From a43a88779981c87a90d863e03f3a9d9172c28189 Mon Sep 17 00:00:00 2001 From: octo Date: Wed, 14 Dec 2005 13:48:28 +0000 Subject: [PATCH] Implemented `plugin_get_dir' and `plugin_set_dir' Renamed `plugin_load' to `plugin_load_file' Implemented `plugin_load' which works with plugin-names rather than filenames --- src/plugin.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ src/plugin.h | 66 +++++++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 11 deletions(-) diff --git a/src/plugin.c b/src/plugin.c index 9bc02abe..d2e5f47c 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -42,6 +42,27 @@ static plugin_t *first_plugin = NULL; extern int operating_mode; #endif +static char *plugindir = NULL; + +char *plugin_get_dir (void) +{ + if (plugindir == NULL) + return (PLUGINDIR); + else + return (plugindir); +} + +void plugin_set_dir (char *dir) +{ + if (plugindir != NULL) + free (plugindir); + + if (dir == NULL) + plugindir = NULL; + else if ((plugindir = strdup (dir)) == NULL) + syslog (LOG_ERR, "strdup: %s", strerror (errno)); +} + /* * Returns the number of plugins registered */ @@ -86,11 +107,11 @@ int plugin_exists (char *type) } /* - * (Try to) load the shared object `name'. Won't complain if it isn't a shared + * (Try to) load the shared object `file'. Won't complain if it isn't a shared * object, but it will bitch about a shared object not having a * ``module_register'' symbol.. */ -void plugin_load (char *name) +int plugin_load_file (char *file) { lt_dlhandle dlh; void (*reg_handle) (void); @@ -98,24 +119,94 @@ void plugin_load (char *name) lt_dlinit (); lt_dlerror (); /* clear errors */ - if ((dlh = lt_dlopen (name)) == NULL) - return; + if ((dlh = lt_dlopen (file)) == NULL) + return (1); if ((reg_handle = lt_dlsym (dlh, "module_register")) == NULL) { syslog (LOG_WARNING, "Couldn't find symbol ``module_register'' in ``%s'': %s\n", - name, lt_dlerror ()); + file, lt_dlerror ()); lt_dlclose (dlh); - return; + return (-1); } (*reg_handle) (); + + return (0); +} + +#define BUFSIZE 512 +int plugin_load (char *type) +{ + DIR *dh; + char *dir; + char filename[BUFSIZE]; + char typename[BUFSIZE]; + int typename_len; + int ret; + struct stat statbuf; + struct dirent *de; + + dir = plugin_get_dir (); + ret = 1; + + /* don't load twice */ + if (plugin_search (type) != NULL) + return (0); + + /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the + * type when matching the filename */ + if (snprintf (typename, BUFSIZE, "%s.so", type) >= BUFSIZE) + { + syslog (LOG_WARNING, "snprintf: truncated: `%s.so'", type); + return (-1); + } + typename_len = strlen (typename); + + if ((dh = opendir (dir)) == NULL) + { + syslog (LOG_ERR, "opendir (%s): %s", dir, strerror (errno)); + return (-1); + } + + while ((de = readdir (dh)) != NULL) + { + if (strncmp (de->d_name, typename, typename_len)) + continue; + + if (snprintf (filename, BUFSIZE, "%s/%s", dir, de->d_name) >= BUFSIZE) + { + syslog (LOG_WARNING, "snprintf: truncated: `%s/%s'", dir, de->d_name); + continue; + } + + if (lstat (filename, &statbuf) == -1) + { + syslog (LOG_WARNING, "stat %s: %s", filename, strerror (errno)); + continue; + } + else if (!S_ISREG (statbuf.st_mode)) + { + /* don't follow symlinks */ + continue; + } + + if (plugin_load_file (filename) == 0) + { + /* success */ + ret = 0; + break; + } + } + + closedir (dh); + + return (ret); } /* * (Try to) load all plugins in `dir'. Returns the number of loaded plugins.. */ -#define BUFSIZE 512 int plugin_load_all (char *dir) { DIR *dh; @@ -124,18 +215,23 @@ int plugin_load_all (char *dir) struct stat statbuf; if (dir == NULL) - dir = PLUGINDIR; + dir = plugin_get_dir (); + else + plugin_set_dir (dir); if ((dh = opendir (dir)) == NULL) { - fprintf (stderr, "Error: Cannot read plugin directory `%s'\n", dir); + syslog (LOG_ERR, "opendir (%s): %s", dir, strerror (errno)); return (0); } while ((de = readdir (dh)) != NULL) { if (snprintf (filename, BUFSIZE, "%s/%s", dir, de->d_name) >= BUFSIZE) + { + syslog (LOG_WARNING, "snprintf: truncated: %s/%s", dir, de->d_name); continue; + } if (lstat (filename, &statbuf) == -1) { @@ -147,7 +243,7 @@ int plugin_load_all (char *dir) continue; } - plugin_load (filename); + plugin_load_file (filename); } closedir (dh); diff --git a/src/plugin.h b/src/plugin.h index 5bf5de67..6e363673 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -23,11 +23,75 @@ #ifndef PLUGIN_H #define PLUGIN_H +/* + * NAME + * plugin_set_dir + * + * DESCRIPTION + * Sets the current `plugindir' + * + * ARGUMENTS + * `dir' Path to the plugin directory + * + * NOTES + * If `dir' is NULL the compiled in default `PLUGINDIR' is used. + */ +void plugin_set_dir (char *dir); + +/* + * NAME + * plugin_count + * + * DESCRIPTION + * trivial + * + * RETURN VALUE + * The number of currently loaded plugins + */ +int plugin_count (void); + +/* + * NAME + * plugin_exists + * + * DESCRIPTION + * trivial + * + * ARGUMENTS + * `type' Name of the plugin. + * + * RETURN VALUE + * Returns non-zero if a plugin with the name $type is found and zero + * otherwise. + */ +int plugin_exists (char *type); + +/* + * NAME + * plugin_load + * + * DESCRIPTION + * Searches the current `plugindir' (see `plugin_set_dir') for the plugin + * named $type and loads it. Afterwards the plugin's `module_register' + * function is called, which then calls `plugin_register' to register callback + * functions. + * + * ARGUMENTS + * `type' Name of the plugin to load. + * + * RETURN VALUE + * Returns zero upon success, a value greater than zero if no plugin was found + * and a value below zero if an error occurs. + * + * NOTES + * No attempt is made to re-load an already loaded module. + */ +int plugin_load (char *type); + int plugin_load_all (char *dir); void plugin_init_all (void); void plugin_read_all (void); -int plugin_exists (char *type); void plugin_register (char *type, void (*init) (void), void (*read) (void), -- 2.11.0