00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define DEFAULTMODULE "OpenSER"
00028 #define MAX_LIB_PATHS 10
00029
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <dlfcn.h>
00034
00035 #include "../../sr_module.h"
00036 #include "../../mem/mem.h"
00037 #include "../../mi/mi.h"
00038 #include "../rr/api.h"
00039 #include "../sl/sl_api.h"
00040
00041
00042 #ifdef USE_SYSV_SEM
00043 # define HAS_UNION_SEMUN
00044 #endif
00045
00046 #include "perlfunc.h"
00047 #include "perl.h"
00048
00049
00050
00051 MODULE_VERSION
00052
00053
00054 char *filename = NULL;
00055
00056
00057
00058 char *modpath = NULL;
00059
00060
00061
00062 int unsafemodfnc = 0;
00063
00064
00065 PerlInterpreter *my_perl = NULL;
00066
00067
00068 struct sl_binds slb;
00069
00070
00071
00072
00073 static void destroy(void);
00074
00075
00076
00077
00078
00079 static int mod_init(void);
00080
00081
00082
00083
00084
00085 struct mi_root* perl_mi_reload(struct mi_root *cmd_tree, void *param);
00086
00087
00088
00089
00090
00091
00092 static cmd_export_t cmds[] = {
00093 { "perl_exec_simple", (cmd_function)perl_exec_simple1, 1, NULL, 0,
00094 REQUEST_ROUTE | FAILURE_ROUTE
00095 | ONREPLY_ROUTE | BRANCH_ROUTE },
00096 { "perl_exec_simple", (cmd_function)perl_exec_simple2, 2, NULL, 0,
00097 REQUEST_ROUTE | FAILURE_ROUTE
00098 | ONREPLY_ROUTE | BRANCH_ROUTE },
00099 { "perl_exec", (cmd_function)perl_exec1, 1, NULL, 0,
00100 REQUEST_ROUTE | FAILURE_ROUTE
00101 | ONREPLY_ROUTE | BRANCH_ROUTE },
00102 { "perl_exec", (cmd_function)perl_exec2, 2, NULL, 0,
00103 REQUEST_ROUTE | FAILURE_ROUTE
00104 | ONREPLY_ROUTE | BRANCH_ROUTE },
00105 { 0, 0, 0, 0, 0, 0 }
00106 };
00107
00108
00109
00110
00111
00112 static param_export_t params[] = {
00113 {"filename", STR_PARAM, &filename},
00114 {"modpath", STR_PARAM, &modpath},
00115 {"unsafemodfnc", INT_PARAM, &unsafemodfnc},
00116 { 0, 0, 0 }
00117 };
00118
00119
00120
00121
00122
00123 static mi_export_t mi_cmds[] = {
00124
00125
00126 { 0, 0, 0, 0, 0}
00127
00128 };
00129
00130
00131
00132
00133
00134
00135
00136
00137 #ifndef RTLD_NOW
00138
00139 #define RTLD_NOW DL_LAZY
00140 #endif
00141
00142 #ifndef RTLD_GLOBAL
00143
00144 #define RTLD_GLOBAL 0
00145 #endif
00146
00147
00148
00149
00150 struct module_exports exports = {
00151 "perl",
00152 RTLD_NOW | RTLD_GLOBAL,
00153 cmds,
00154 params,
00155 0,
00156 mi_cmds,
00157 0,
00158 0,
00159 mod_init,
00160 0,
00161 destroy,
00162 0
00163 };
00164
00165
00166
00167 EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
00168 EXTERN_C void boot_OpenSER(pTHX_ CV* cv);
00169
00170
00171
00172
00173
00174
00175 EXTERN_C void xs_init(pTHX) {
00176 char *file = __FILE__;
00177 dXSUB_SYS;
00178
00179 newXS("OpenSER::bootstrap", boot_OpenSER, file);
00180
00181 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
00182 }
00183
00184
00185
00186
00187
00188
00189 PerlInterpreter *parser_init(void) {
00190 int argc = 0;
00191 char *argv[MAX_LIB_PATHS + 3];
00192 PerlInterpreter *new_perl = NULL;
00193 char *entry, *stop, *end;
00194 int modpathset_start = 0;
00195 int modpathset_end = 0;
00196 int i;
00197
00198 new_perl = perl_alloc();
00199
00200 if (!new_perl) {
00201 LM_ERR("could not allocate perl.\n");
00202 return NULL;
00203 }
00204
00205 perl_construct(new_perl);
00206
00207 argv[0] = ""; argc++;
00208
00209
00210 if (modpath && (strlen(modpath) > 0)) {
00211 modpathset_start = argc;
00212
00213 entry = modpath;
00214 stop = modpath + strlen(modpath);
00215 for (end = modpath; end <= stop; end++) {
00216 if ( (end[0] == ':') || (end[0] == '\0') ) {
00217 end[0] = '\0';
00218 if (argc > MAX_LIB_PATHS) {
00219 LM_ERR("too many lib paths, skipping lib path: '%s'\n", entry);
00220 } else {
00221 LM_INFO("setting lib path: '%s'\n", entry);
00222 argv[argc] = pkg_malloc(strlen(entry)+20);
00223 sprintf(argv[argc], "-I%s", entry);
00224 modpathset_end = argc;
00225 argc++;
00226 }
00227 entry = end + 1;
00228 }
00229 }
00230 }
00231
00232 argv[argc] = "-M"DEFAULTMODULE; argc++;
00233
00234 argv[argc] = filename;
00235 argc++;
00236
00237 if (perl_parse(new_perl, xs_init, argc, argv, NULL)) {
00238 LM_ERR("failed to load perl file \"%s\".\n", argv[argc-1]);
00239 if (modpathset_start) {
00240 for (i = modpathset_start; i <= modpathset_end; i++) {
00241 pkg_free(argv[i]);
00242 }
00243 }
00244 return NULL;
00245 } else {
00246 LM_INFO("successfully loaded perl file \"%s\"\n", argv[argc-1]);
00247 }
00248
00249 if (modpathset_start) {
00250 for (i = modpathset_start; i <= modpathset_end; i++) {
00251 pkg_free(argv[i]);
00252 }
00253 }
00254 perl_run(new_perl);
00255
00256 return new_perl;
00257
00258 }
00259
00260
00261
00262
00263 int unload_perl(PerlInterpreter *p) {
00264 perl_destruct(p);
00265 perl_free(p);
00266
00267 return 0;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276 int perl_reload(struct sip_msg *m, char *a, char *b) {
00277
00278 PerlInterpreter *new_perl;
00279
00280 new_perl = parser_init();
00281
00282 if (new_perl) {
00283 unload_perl(my_perl);
00284 my_perl = new_perl;
00285 #ifdef PERL_EXIT_DESTRUCT_END
00286 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
00287 #else
00288 #warning Perl 5.8.x should be used. Please upgrade.
00289 #warning This binary will be unsupported.
00290 PL_exit_flags |= PERL_EXIT_EXPECTED;
00291 #endif
00292 return 1;
00293 } else {
00294 return 0;
00295 }
00296
00297 }
00298
00299
00300
00301
00302
00303
00304 struct mi_root* perl_mi_reload(struct mi_root *cmd_tree, void *param)
00305 {
00306 if (perl_reload(NULL, NULL, NULL)) {
00307 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00308 } else {
00309 return init_mi_tree( 500, "Perl reload failed", 18);
00310 }
00311
00312 }
00313
00314
00315
00316
00317
00318
00319 static int mod_init(void) {
00320
00321 int ret = 0;
00322
00323 if (!filename) {
00324 LM_ERR("insufficient module parameters. Module not loaded.\n");
00325 return -1;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335 if (load_sl_api(&slb)!=0) {
00336 LM_ERR("can't load SL API\n");
00337 return -1;
00338 }
00339
00340 PERL_SYS_INIT3(NULL, NULL, &environ);
00341
00342 if ((my_perl = parser_init())) {
00343 ret = 0;
00344 #ifdef PERL_EXIT_DESTRUCT_END
00345 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
00346 #else
00347 PL_exit_flags |= PERL_EXIT_EXPECTED;
00348 #endif
00349
00350 } else {
00351 ret = -1;
00352 }
00353
00354 return ret;
00355 }
00356
00357
00358
00359
00360
00361 static void destroy(void)
00362 {
00363 if(my_perl==NULL)
00364 return;
00365 unload_perl(my_perl);
00366 PERL_SYS_TERM();
00367 my_perl = NULL;
00368 }