/**
* collectd - src/plugin.c
- * Copyright (C) 2005 Florian octo Forster
+ * Copyright (C) 2005,2006 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
#include <ltdl.h>
#include "plugin.h"
-#include "multicast.h"
+#include "network.h"
+#include "utils_debug.h"
typedef struct plugin
{
static plugin_t *first_plugin = NULL;
-#ifdef HAVE_LIBRRD
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 (const 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
/*
* Returns the plugins with the type `type' or NULL if it's not found.
*/
-plugin_t *plugin_search (char *type)
+plugin_t *plugin_search (const char *type)
{
plugin_t *ret;
}
/*
- * (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);
+ DBG ("file = %s", file);
+
lt_dlinit ();
lt_dlerror (); /* clear errors */
- if ((dlh = lt_dlopen (name)) == NULL)
- return;
+ if ((dlh = lt_dlopen (file)) == NULL)
+ {
+ const char *error = lt_dlerror ();
+
+ syslog (LOG_ERR, "lt_dlopen failed: %s", error);
+ DBG ("lt_dlopen failed: %s", error);
+ 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 (const char *type)
+{
+ DIR *dh;
+ char *dir;
+ char filename[BUFSIZE];
+ char typename[BUFSIZE];
+ int typename_len;
+ int ret;
+ struct stat statbuf;
+ struct dirent *de;
+
+ DBG ("type = %s", type);
+
+ 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 (strncasecmp (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;
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)
{
continue;
}
- plugin_load (filename);
+ plugin_load_file (filename);
}
closedir (dh);
if (plugin_search (type) != NULL)
return;
+#ifdef HAVE_LIBRRD
+ if (operating_mode != MODE_SERVER)
+#endif
+ if ((init != NULL) && (read == NULL))
+ syslog (LOG_NOTICE, "Plugin `%s' doesn't provide a read function.", type);
+
if ((p = (plugin_t *) malloc (sizeof (plugin_t))) == NULL)
return;
* Send received data back to the plugin/module which will append DS
* definitions and pass it on to ``rrd_update_file''.
*/
-#ifdef HAVE_LIBRRD
void plugin_write (char *host, char *type, char *inst, char *val)
{
plugin_t *p;
(*p->write) (host, inst, val);
}
-#endif /* HAVE_LIBRRD */
/*
* Receive data from the plugin/module and get it somehow to ``plugin_write'':
- * Either using ``multicast_send'' (when in network/client mode) or call it
+ * Either using ``network_send'' (when in network/client mode) or call it
* directly (in local mode).
*/
void plugin_submit (char *type, char *inst, char *val)
{
-#ifdef HAVE_LIBRRD
- if (operating_mode == MODE_LOCAL)
+ if (operating_mode == MODE_CLIENT)
+ network_send (type, inst, val);
+ else
plugin_write (NULL, type, inst, val);
- else if (operating_mode == MODE_CLIENT)
- multicast_send (type, inst, val);
- else /* operating_mode == MODE_SERVER */
- syslog (LOG_ERR, "WTF is the server doing in ``plugin_submit''?!?\n");
-#else
- multicast_send (type, inst, val);
-#endif
}