Implemented `plugin_get_dir' and `plugin_set_dir'
authorocto <octo>
Wed, 14 Dec 2005 13:48:28 +0000 (13:48 +0000)
committerocto <octo>
Wed, 14 Dec 2005 13:48:28 +0000 (13:48 +0000)
Renamed `plugin_load' to `plugin_load_file'
Implemented `plugin_load' which works with plugin-names rather than filenames

src/plugin.c
src/plugin.h

index 9bc02ab..d2e5f47 100644 (file)
@@ -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);
index 5bf5de6..6e36367 100644 (file)
 #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),