net-snmp/agent/snmp_perl.c

187 lines
4.6 KiB
C

#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"));
}