Merge branch 'collectd-4.1'
[collectd.git] / src / perl.c
index 626b287..8c21e45 100644 (file)
@@ -81,15 +81,6 @@ typedef struct {
  * private variables
  */
 
-/* valid configuration file keys */
-static const char *config_keys[] =
-{
-       "LoadPlugin",
-       "BaseName",
-       "IncludeDir"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-
 static PerlInterpreter *perl = NULL;
 
 static int  perl_argc   = 0;
@@ -111,6 +102,27 @@ static struct {
        { "", NULL }
 };
 
+struct {
+       char name[64];
+       int  value;
+} constants[] =
+{
+       { "Collectd::TYPE_INIT",       PLUGIN_INIT },
+       { "Collectd::TYPE_READ",       PLUGIN_READ },
+       { "Collectd::TYPE_WRITE",      PLUGIN_WRITE },
+       { "Collectd::TYPE_SHUTDOWN",   PLUGIN_SHUTDOWN },
+       { "Collectd::TYPE_LOG",        PLUGIN_LOG },
+       { "Collectd::TYPE_DATASET",    PLUGIN_DATASET },
+       { "Collectd::DS_TYPE_COUNTER", DS_TYPE_COUNTER },
+       { "Collectd::DS_TYPE_GAUGE",   DS_TYPE_GAUGE },
+       { "Collectd::LOG_ERR",         LOG_ERR },
+       { "Collectd::LOG_WARNING",     LOG_WARNING },
+       { "Collectd::LOG_NOTICE",      LOG_NOTICE },
+       { "Collectd::LOG_INFO",        LOG_INFO },
+       { "Collectd::LOG_DEBUG",       LOG_DEBUG },
+       { "", 0 }
+};
+
 
 /*
  * Helper functions for data type conversion.
@@ -731,58 +743,6 @@ static XS (Collectd_plugin_log)
        XSRETURN_YES;
 } /* static XS (Collectd_plugin_log) */
 
-/*
- * Collectd::bootstrap ().
- */
-static XS (boot_Collectd)
-{
-       HV   *stash = NULL;
-       char *file  = __FILE__;
-
-       struct {
-               char name[64];
-               SV   *value;
-       } consts[] =
-       {
-               { "Collectd::TYPE_INIT",       Perl_newSViv (perl, PLUGIN_INIT) },
-               { "Collectd::TYPE_READ",       Perl_newSViv (perl, PLUGIN_READ) },
-               { "Collectd::TYPE_WRITE",      Perl_newSViv (perl, PLUGIN_WRITE) },
-               { "Collectd::TYPE_SHUTDOWN",   Perl_newSViv (perl, PLUGIN_SHUTDOWN) },
-               { "Collectd::TYPE_LOG",        Perl_newSViv (perl, PLUGIN_LOG) },
-               { "Collectd::TYPE_DATASET",    Perl_newSViv (perl, PLUGIN_DATASET) },
-               { "Collectd::DS_TYPE_COUNTER", Perl_newSViv (perl, DS_TYPE_COUNTER) },
-               { "Collectd::DS_TYPE_GAUGE",   Perl_newSViv (perl, DS_TYPE_GAUGE) },
-               { "Collectd::LOG_ERR",         Perl_newSViv (perl, LOG_ERR) },
-               { "Collectd::LOG_WARNING",     Perl_newSViv (perl, LOG_WARNING) },
-               { "Collectd::LOG_NOTICE",      Perl_newSViv (perl, LOG_NOTICE) },
-               { "Collectd::LOG_INFO",        Perl_newSViv (perl, LOG_INFO) },
-               { "Collectd::LOG_DEBUG",       Perl_newSViv (perl, LOG_DEBUG) },
-               { "", NULL }
-       };
-
-       int i = 0;
-
-       dXSARGS;
-
-       if ((1 > items) || (2 < items)) {
-               log_err ("Usage: Collectd::bootstrap(name[, version])");
-               XSRETURN_EMPTY;
-       }
-
-       XS_VERSION_BOOTCHECK;
-
-       /* register API */
-       for (i = 0; NULL != api[i].f; ++i)
-               Perl_newXS (perl, api[i].name, api[i].f, file);
-
-       stash = Perl_gv_stashpv (perl, "Collectd", 1);
-
-       /* export "constants" */
-       for (i = 0; NULL != consts[i].value; ++i)
-               Perl_newCONSTSUB (perl, stash, consts[i].name, consts[i].value);
-       XSRETURN_YES;
-} /* static XS (boot_Collectd) */
-
 
 /*
  * Interface to collectd.
@@ -829,7 +789,7 @@ static int perl_shutdown (void)
 {
        int ret = 0;
 
-       plugin_unregister_config ("perl");
+       plugin_unregister_complex_config ("perl");
 
        if (NULL == perl)
                return 0;
@@ -867,32 +827,46 @@ static int perl_shutdown (void)
        return ret;
 } /* static void perl_shutdown (void) */
 
+/* bootstrap the Collectd module */
 static void xs_init (pTHX)
 {
-       char *file = __FILE__;
+       HV   *stash = NULL;
+       char *file  = __FILE__;
 
-       dXSUB_SYS;
+       int i = 0;
 
-       /* build the Collectd module into the perl interpreter */
-       Perl_newXS (perl, "Collectd::bootstrap", boot_Collectd, file);
+       dXSUB_SYS;
 
        /* enable usage of Perl modules using shared libraries */
        Perl_newXS (perl, "DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
+
+       /* register API */
+       for (i = 0; NULL != api[i].f; ++i)
+               Perl_newXS (perl, api[i].name, api[i].f, file);
+
+       stash = Perl_gv_stashpv (perl, "Collectd", 1);
+
+       /* export "constants" */
+       for (i = 0; '\0' != constants[i].name[0]; ++i)
+               Perl_newCONSTSUB (perl, stash, constants[i].name,
+                               Perl_newSViv (perl, constants[i].value));
        return;
 } /* static void xs_init (pTHX) */
 
 /* Initialize the global Perl interpreter. */
 static int init_pi (int argc, char **argv)
 {
-       int i = 0;
-
        if (NULL != perl)
                return 0;
 
        log_info ("Initializing Perl interpreter...");
 #if COLLECT_DEBUG
-       for (i = 0; i < argc; ++i)
-               log_debug ("argv[%i] = \"%s\"", i, argv[i]);
+       {
+               int i = 0;
+
+               for (i = 0; i < argc; ++i)
+                       log_debug ("argv[%i] = \"%s\"", i, argv[i]);
+       }
 #endif /* COLLECT_DEBUG */
 
        PERL_SYS_INIT3 (&argc, &argv, &environ);
@@ -923,51 +897,137 @@ static int init_pi (int argc, char **argv)
        return 0;
 } /* static int init_pi (const char **, const int) */
 
-static int perl_config (const char *key, const char *value)
+/*
+ * LoadPlugin "<Plugin>"
+ */
+static int perl_config_loadplugin (oconfig_item_t *ci)
 {
-       log_debug ("perl_config: key = \"%s\", value=\"%s\"", key, value);
+       char module_name[DATA_MAX_NAME_LEN];
+
+       char *value = NULL;
+
+       if ((0 != ci->children_num) || (1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+       }
 
-       if (0 == strcasecmp (key, "LoadPlugin")) {
-               char module_name[DATA_MAX_NAME_LEN];
+       value = ci->values[0].value.string;
 
-               if (get_module_name (module_name, sizeof (module_name), value)
-                               == NULL) {
-                       log_err ("Invalid module name %s", value);
-                       return (1);
-               } /* if (get_module_name == NULL) */
+       if (NULL == get_module_name (module_name, sizeof (module_name), value)) {
+               log_err ("Invalid module name %s", value);
+               return (1);
+       }
+
+       init_pi (perl_argc, perl_argv);
+
+       log_debug ("perl_config: loading perl plugin \"%s\"", value);
+       Perl_load_module (perl, PERL_LOADMOD_NOIMPORT,
+                       Perl_newSVpv (perl, module_name, strlen (module_name)),
+                       Nullsv);
+       return 0;
+} /* static int perl_config_loadplugin (oconfig_item_it *) */
 
-               init_pi (perl_argc, perl_argv);
+/*
+ * BaseName "<Name>"
+ */
+static int perl_config_basename (oconfig_item_t *ci)
+{
+       char *value = NULL;
 
-               log_debug ("perl_config: loading perl plugin \"%s\"", value);
-               Perl_load_module (perl, PERL_LOADMOD_NOIMPORT,
-                               Perl_newSVpv (perl, module_name, strlen (module_name)),
-                               Nullsv);
+       if ((0 != ci->children_num) || (1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
        }
-       else if (0 == strcasecmp (key, "BaseName")) {
-               log_debug ("perl_config: Setting plugin basename to \"%s\"", value);
-               strncpy (base_name, value, sizeof (base_name));
-               base_name[sizeof (base_name) - 1] = '\0';
+
+       value = ci->values[0].value.string;
+
+       log_debug ("perl_config: Setting plugin basename to \"%s\"", value);
+       strncpy (base_name, value, sizeof (base_name));
+       base_name[sizeof (base_name) - 1] = '\0';
+       return 0;
+} /* static int perl_config_basename (oconfig_item_it *) */
+
+/*
+ * EnableDebugger "<Package>"|""
+ */
+static int perl_config_enabledebugger (oconfig_item_t *ci)
+{
+       char *value = NULL;
+
+       if ((0 != ci->children_num) || (1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
        }
-       else if (0 == strcasecmp (key, "IncludeDir")) {
-               perl_argv = (char **)realloc (perl_argv,
-                               (++perl_argc + 1) * sizeof (char *));
 
-               if (NULL == perl_argv) {
-                       log_err ("perl_config: Not enough memory.");
-                       exit (3);
-               }
+       value = ci->values[0].value.string;
+
+       perl_argv = (char **)realloc (perl_argv,
+                       (++perl_argc + 1) * sizeof (char *));
 
-               perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 3);
-               sstrncpy(perl_argv[perl_argc - 1], "-I", 3);
-               sstrncpy(perl_argv[perl_argc - 1] + 2, value, strlen (value) + 1);
+       if (NULL == perl_argv) {
+               log_err ("perl_config: Not enough memory.");
+               exit (3);
+       }
 
-               perl_argv[perl_argc] = NULL;
+       if ('\0' == value[0]) {
+               perl_argv[perl_argc - 1] = "-d";
        }
        else {
-               return -1;
+               perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 4);
+               sstrncpy (perl_argv[perl_argc - 1], "-d:", 4);
+               sstrncpy (perl_argv[perl_argc - 1] + 3, value, strlen (value) + 1);
+       }
+
+       perl_argv[perl_argc] = NULL;
+       return 0;
+} /* static int perl_config_enabledebugger (oconfig_item_it *) */
+
+/*
+ * IncludeDir "<Dir>"
+ */
+static int perl_config_includedir (oconfig_item_t *ci)
+{
+       char *value = NULL;
+
+       if ((0 != ci->children_num) || (1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+       }
+
+       value = ci->values[0].value.string;
+
+       perl_argv = (char **)realloc (perl_argv,
+                       (++perl_argc + 1) * sizeof (char *));
+
+       if (NULL == perl_argv) {
+               log_err ("perl_config: Not enough memory.");
+               exit (3);
+       }
+
+       perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 3);
+       sstrncpy(perl_argv[perl_argc - 1], "-I", 3);
+       sstrncpy(perl_argv[perl_argc - 1] + 2, value, strlen (value) + 1);
+
+       perl_argv[perl_argc] = NULL;
+       return 0;
+} /* static int perl_config_includedir (oconfig_item_it *) */
+
+static int perl_config (oconfig_item_t *ci)
+{
+       int i = 0;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (0 == strcasecmp (c->key, "LoadPlugin"))
+                       perl_config_loadplugin (c);
+               else if (0 == strcasecmp (c->key, "BaseName"))
+                       perl_config_basename (c);
+               else if (0 == strcasecmp (c->key, "EnableDebugger"))
+                       perl_config_enabledebugger (c);
+               else if (0 == strcasecmp (c->key, "IncludeDir"))
+                       perl_config_includedir (c);
+               else
+                       log_warn ("Ignoring unknown config key \"%s\".", c->key);
        }
        return 0;
-} /* static int perl_config (char *, char *) */
+} /* static int perl_config (oconfig_item_t *) */
 
 void module_register (void)
 {
@@ -981,7 +1041,7 @@ void module_register (void)
        perl_argv[3] = "1";
        perl_argv[4] = NULL;
 
-       plugin_register_config ("perl", perl_config, config_keys, config_keys_num);
+       plugin_register_complex_config ("perl", perl_config);
        return;
 } /* void module_register (void) */