diff options
Diffstat (limited to 'agent/snmp_perl.c')
-rw-r--r-- | agent/snmp_perl.c | 186 |
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")); +} |