summaryrefslogtreecommitdiff
path: root/agent/snmp_perl.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/snmp_perl.c')
-rw-r--r--agent/snmp_perl.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/agent/snmp_perl.c b/agent/snmp_perl.c
new file mode 100644
index 0000000..48d9695
--- /dev/null
+++ b/agent/snmp_perl.c
@@ -0,0 +1,186 @@
+#if defined(_WIN32) && !defined(_WIN32_WINNT)
+#define _WIN32_WINNT 0x501
+#endif
+
+#include <EXTERN.h>
+#include "perl.h"
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "snmp_perl.h"
+
+static PerlInterpreter *my_perl;
+
+void boot_DynaLoader(pTHX_ CV * cv);
+
+void
+xs_init(pTHX)
+{
+ char myfile[] = __FILE__;
+ char modulename[] = "DynaLoader::boot_DynaLoader";
+ /*
+ * DynaLoader is a special case
+ */
+ newXS(modulename, boot_DynaLoader, myfile);
+}
+
+void
+maybe_source_perl_startup(void)
+{
+ int argc;
+ char **argv;
+ char **env;
+ char *embedargs[] = { NULL, NULL };
+ const char *perl_init_file = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_PERL_INIT_FILE);
+ char init_file[SNMP_MAXBUF];
+ int res;
+
+ static int have_done_init = 0;
+
+ if (have_done_init)
+ return;
+ have_done_init = 1;
+
+ embedargs[0] = strdup("");
+ if (!perl_init_file) {
+ snprintf(init_file, sizeof(init_file) - 1,
+ "%s/%s", SNMPSHAREPATH, "snmp_perl.pl");
+ perl_init_file = init_file;
+ }
+ embedargs[1] = strdup(perl_init_file);
+
+ DEBUGMSGTL(("perl", "initializing perl (%s)\n", embedargs[1]));
+ argc = 0;
+ argv = NULL;
+ env = NULL;
+ PERL_SYS_INIT3(&argc, &argv, &env);
+ my_perl = perl_alloc();
+ if (!my_perl) {
+ snmp_log(LOG_ERR,
+ "embedded perl support failed to initialize (perl_alloc())\n");
+ goto bail_out;
+ }
+
+ perl_construct(my_perl);
+
+#ifdef PERL_EXIT_DESTRUCT_END
+ PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
+#endif
+
+ res = perl_parse(my_perl, xs_init, 2, embedargs, NULL);
+ if (res) {
+ snmp_log(LOG_ERR,
+ "embedded perl support failed to initialize (perl_parse(%s)"
+ " returned %d)\n", embedargs[1], res);
+ goto bail_out;
+ }
+
+ res = perl_run(my_perl);
+ if (res) {
+ snmp_log(LOG_ERR,
+ "embedded perl support failed to initialize (perl_run()"
+ " returned %d)\n", res);
+ goto bail_out;
+ }
+
+ free(embedargs[0]);
+ free(embedargs[1]);
+
+ DEBUGMSGTL(("perl", "done initializing perl\n"));
+
+ return;
+
+ bail_out:
+ free(embedargs[0]);
+ free(embedargs[1]);
+ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_DISABLE_PERL, 1);
+ return;
+}
+
+void
+do_something_perlish(char *something)
+{
+ if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_DISABLE_PERL)) {
+ return;
+ }
+ maybe_source_perl_startup();
+ if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_DISABLE_PERL)) {
+ return;
+ }
+ DEBUGMSGTL(("perl", "calling perl\n"));
+#if defined(HAVE_EVAL_PV) || defined(eval_pv)
+ /* newer perl */
+ eval_pv(something, TRUE);
+#else
+#if defined(HAVE_PERL_EVAL_PV_LC) || defined(perl_eval_pv)
+ /* older perl? */
+ perl_eval_pv(something, TRUE);
+#else /* HAVE_PERL_EVAL_PV_LC */
+#ifdef HAVE_PERL_EVAL_PV_UC
+ /* older perl? */
+ Perl_eval_pv(my_perl, something, TRUE);
+#else /* !HAVE_PERL_EVAL_PV_UC */
+#error embedded perl broken
+#endif /* !HAVE_PERL_EVAL_PV_LC */
+#endif /* !HAVE_PERL_EVAL_PV_UC */
+#endif /* !HAVE_EVAL_PV */
+ DEBUGMSGTL(("perl", "finished calling perl\n"));
+}
+
+void
+perl_config_handler(const char *token, char *line)
+{
+ do_something_perlish(line);
+}
+
+void
+init_perl(void)
+{
+ const char *appid = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
+ NETSNMP_DS_LIB_APPTYPE);
+ const char *defaultid = "snmpd";
+
+ if (!appid) {
+ appid = defaultid;
+ }
+
+ /*
+ * register config handlers
+ */
+ snmpd_register_config_handler("perl", perl_config_handler, NULL,
+ "PERLCODE");
+
+ /*
+ * define the perlInitFile token to point to an init file
+ */
+ netsnmp_ds_register_premib(ASN_OCTET_STR, appid, "perlInitFile",
+ NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_PERL_INIT_FILE);
+
+ /*
+ * define the perlInitFile token to point to an init file
+ */
+ netsnmp_ds_register_premib(ASN_BOOLEAN, appid, "disablePerl",
+ NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_DISABLE_PERL);
+}
+
+void
+shutdown_perl(void)
+{
+ if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_DISABLE_PERL) ||
+ my_perl == NULL) {
+ return;
+ }
+ DEBUGMSGTL(("perl", "shutting down perl\n"));
+ perl_destruct(my_perl);
+ my_perl = NULL;
+ DEBUGMSGTL(("perl", "finished shutting down perl\n"));
+}