net-snmp 5.7
snmp_perl.c
00001 #include <EXTERN.h>
00002 #include "perl.h"
00003 
00004 #include <net-snmp/net-snmp-config.h>
00005 #include <net-snmp/net-snmp-includes.h>
00006 #include <net-snmp/agent/net-snmp-agent-includes.h>
00007 
00008 #include "snmp_perl.h"
00009 
00010 static PerlInterpreter *my_perl;
00011 
00012 void            boot_DynaLoader(pTHX_ CV * cv);
00013 
00014 void
00015 xs_init(pTHX)
00016 {
00017     char            myfile[] = __FILE__;
00018     char            modulename[] = "DynaLoader::boot_DynaLoader";
00019     /*
00020      * DynaLoader is a special case 
00021      */
00022     newXS(modulename, boot_DynaLoader, myfile);
00023 }
00024 
00025 void
00026 maybe_source_perl_startup(void)
00027 {
00028     int             argc;
00029     char          **argv;
00030     char          **env;
00031     char           *embedargs[] = { NULL, NULL };
00032     const char     *perl_init_file = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
00033                                                            NETSNMP_DS_AGENT_PERL_INIT_FILE);
00034     char            init_file[SNMP_MAXBUF];
00035 
00036     static int      have_done_init = 0;
00037 
00038     if (have_done_init)
00039         return;
00040     have_done_init = 1;
00041 
00042     embedargs[0] = strdup("");
00043     if (!perl_init_file) {
00044         snprintf(init_file, sizeof(init_file) - 1,
00045                  "%s/%s", SNMPSHAREPATH, "snmp_perl.pl");
00046         perl_init_file = init_file;
00047     }
00048     embedargs[1] = strdup(perl_init_file);
00049 
00050     DEBUGMSGTL(("perl", "initializing perl (%s)\n", embedargs[1]));
00051     argc = 0;
00052     argv = NULL;
00053     env = NULL;
00054     PERL_SYS_INIT3(&argc, &argv, &env);
00055     my_perl = perl_alloc();
00056     if (!my_perl)
00057         goto bail_out;
00058 
00059     perl_construct(my_perl);
00060 
00061 #ifdef PERL_EXIT_DESTRUCT_END
00062     PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
00063 #endif
00064 
00065     if (perl_parse(my_perl, xs_init, 2, embedargs, NULL))
00066         goto bail_out;
00067 
00068     if (perl_run(my_perl))
00069         goto bail_out;
00070 
00071     free(embedargs[0]);
00072     free(embedargs[1]);
00073 
00074     DEBUGMSGTL(("perl", "done initializing perl\n"));
00075 
00076     return;
00077 
00078   bail_out:
00079     free(embedargs[0]);
00080     free(embedargs[1]);
00081     snmp_log(LOG_ERR, "embedded perl support failed to initialize\n");
00082     netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
00083                            NETSNMP_DS_AGENT_DISABLE_PERL, 1);
00084     return;
00085 }
00086 
00087 void
00088 do_something_perlish(char *something)
00089 {
00090     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00091                                NETSNMP_DS_AGENT_DISABLE_PERL)) {
00092         return;
00093     }
00094     maybe_source_perl_startup();
00095     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00096                                NETSNMP_DS_AGENT_DISABLE_PERL)) {
00097         return;
00098     }
00099     DEBUGMSGTL(("perl", "calling perl\n"));
00100 #if defined(HAVE_EVAL_PV) || defined(eval_pv)
00101     /* newer perl */
00102     eval_pv(something, TRUE);
00103 #else
00104 #if defined(HAVE_PERL_EVAL_PV_LC) || defined(perl_eval_pv)
00105     /* older perl? */
00106     perl_eval_pv(something, TRUE);
00107 #else /* HAVE_PERL_EVAL_PV_LC */
00108 #ifdef HAVE_PERL_EVAL_PV_UC
00109     /* older perl? */
00110     Perl_eval_pv(my_perl, something, TRUE);
00111 #else /* !HAVE_PERL_EVAL_PV_UC */
00112 #error embedded perl broken 
00113 #endif /* !HAVE_PERL_EVAL_PV_LC */
00114 #endif /* !HAVE_PERL_EVAL_PV_UC */
00115 #endif /* !HAVE_EVAL_PV */
00116     DEBUGMSGTL(("perl", "finished calling perl\n"));
00117 }
00118 
00119 void
00120 perl_config_handler(const char *token, char *line)
00121 {
00122     do_something_perlish(line);
00123 }
00124 
00125 void
00126 init_perl(void)
00127 {
00128     const char     *appid = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
00129                                                   NETSNMP_DS_LIB_APPTYPE);
00130     const char     *defaultid = "snmpd";
00131 
00132     if (!appid) {
00133         appid = defaultid;
00134     }
00135 
00136     /*
00137      * register config handlers 
00138      */
00139     snmpd_register_config_handler("perl", perl_config_handler, NULL,
00140                                   "PERLCODE");
00141 
00142     /*
00143      * define the perlInitFile token to point to an init file 
00144      */
00145     netsnmp_ds_register_premib(ASN_OCTET_STR, appid, "perlInitFile",
00146                                NETSNMP_DS_APPLICATION_ID, 
00147                                NETSNMP_DS_AGENT_PERL_INIT_FILE);
00148 
00149     /*
00150      * define the perlInitFile token to point to an init file 
00151      */
00152     netsnmp_ds_register_premib(ASN_BOOLEAN, appid, "disablePerl",
00153                                NETSNMP_DS_APPLICATION_ID,
00154                                NETSNMP_DS_AGENT_DISABLE_PERL);
00155 }
00156 
00157 void
00158 shutdown_perl(void)
00159 {
00160     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00161                                NETSNMP_DS_AGENT_DISABLE_PERL) ||
00162         my_perl == NULL) {
00163         return;
00164     }
00165     DEBUGMSGTL(("perl", "shutting down perl\n"));
00166     perl_destruct(my_perl);
00167     DEBUGMSGTL(("perl", "finished shutting down perl\n"));
00168 }