#if defined(_WIN32) && !defined(_WIN32_WINNT) #define _WIN32_WINNT 0x501 #endif #include #include "perl.h" #include #include #include #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")); }