| 109 { |
110 { |
| 110 char *file = __FILE__; |
111 char *file = __FILE__; |
| 111 |
112 |
| 112 /* This one allows dynamic loading of perl modules in perl |
113 /* This one allows dynamic loading of perl modules in perl |
| 113 scripts by the 'use perlmod;' construction*/ |
114 scripts by the 'use perlmod;' construction*/ |
| 114 newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); |
115 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); |
| 115 } |
116 } |
| 116 |
117 |
| 117 |
118 |
| 118 static void |
119 static void |
| 119 perl_init(void) |
120 perl_init(void) |
| 128 /* We use to function one to load a file the other to |
129 /* We use to function one to load a file the other to |
| 129 execute the string obtained from the first and holding |
130 execute the string obtained from the first and holding |
| 130 the file conents. This allows to have a realy local $/ |
131 the file conents. This allows to have a realy local $/ |
| 131 without introducing temp variables to hold the old |
132 without introducing temp variables to hold the old |
| 132 value. Just a question of style:) */ |
133 value. Just a question of style:) */ |
| 133 "sub load_file{" |
134 "package Gaim::PerlLoader;" |
| |
135 "use Symbol;" |
| |
136 |
| |
137 "sub load_file {" |
| 134 "my $f_name=shift;" |
138 "my $f_name=shift;" |
| 135 "local $/=undef;" |
139 "local $/=undef;" |
| 136 "open FH,$f_name or return \"__FAILED__\";" |
140 "open FH,$f_name or return \"__FAILED__\";" |
| 137 "$_=<FH>;" |
141 "$_=<FH>;" |
| 138 "close FH;" |
142 "close FH;" |
| 139 "return $_;" |
143 "return $_;" |
| 140 "}" |
144 "}" |
| 141 "sub load_n_eval{" |
145 |
| 142 "my $f_name=shift;" |
146 "sub destroy_package {" |
| |
147 "eval { $_[0]->UNLOAD() if $_[0]->can('UNLOAD'); };" |
| |
148 "Symbol::delete_package($_[0]);" |
| |
149 "}" |
| |
150 |
| |
151 "sub load_n_eval {" |
| |
152 "my ($f_name, $package) = @_;" |
| |
153 "destroy_package($package);" |
| 143 "my $strin=load_file($f_name);" |
154 "my $strin=load_file($f_name);" |
| 144 "return 2 if($strin eq \"__FAILED__\");" |
155 "return 2 if($strin eq \"__FAILED__\");" |
| 145 "eval $strin;" |
156 "my $eval = qq{package $package; $strin;};" |
| 146 "if($@){" |
157 |
| |
158 "{" |
| |
159 " eval $eval;" |
| |
160 "}" |
| |
161 |
| |
162 "if($@) {" |
| 147 /*" #something went wrong\n"*/ |
163 /*" #something went wrong\n"*/ |
| 148 "Gaim::debug(\"perl\", \"Errors loading file $f_name:\\n$@\");" |
164 "die(\"Errors loading file $f_name: $@\");" |
| 149 "return 1;" |
|
| 150 "}" |
165 "}" |
| |
166 |
| 151 "return 0;" |
167 "return 0;" |
| 152 "}" |
168 "}" |
| 153 }; |
169 }; |
| 154 |
170 |
| 155 my_perl = perl_alloc(); |
171 my_perl = perl_alloc(); |
| 197 (*subaddr)(aTHX_ cv); |
213 (*subaddr)(aTHX_ cv); |
| 198 |
214 |
| 199 PUTBACK; |
215 PUTBACK; |
| 200 } |
216 } |
| 201 |
217 |
| |
218 static void |
| |
219 normalize_script_name(char *name) |
| |
220 { |
| |
221 char *c; |
| |
222 |
| |
223 c = strrchr(name, '.'); |
| |
224 |
| |
225 if (c != NULL) |
| |
226 *c = '\0'; |
| |
227 |
| |
228 for (c = name; *c != '\0'; c++) |
| |
229 { |
| |
230 if (*c == '_' && !g_ascii_isalnum(*c)) |
| |
231 *c = '_'; |
| |
232 } |
| |
233 } |
| |
234 |
| 202 static gboolean |
235 static gboolean |
| 203 probe_perl_plugin(GaimPlugin *plugin) |
236 probe_perl_plugin(GaimPlugin *plugin) |
| 204 { |
237 { |
| 205 /* XXX This would be much faster if I didn't create a new |
238 /* XXX This would be much faster if I didn't create a new |
| 206 * PerlInterpreter every time I probed a plugin */ |
239 * PerlInterpreter every time I probed a plugin */ |
| 254 |
288 |
| 255 info->dependencies = g_list_append(info->dependencies, |
289 info->dependencies = g_list_append(info->dependencies, |
| 256 PERL_PLUGIN_ID); |
290 PERL_PLUGIN_ID); |
| 257 |
291 |
| 258 gps->plugin = plugin; |
292 gps->plugin = plugin; |
| |
293 |
| |
294 basename = g_path_get_basename(plugin->path); |
| |
295 normalize_script_name(basename); |
| |
296 gps->package = g_strdup_printf("Gaim::Script::%s", basename); |
| |
297 g_free(basename); |
| 259 |
298 |
| 260 /* We know this one exists. */ |
299 /* We know this one exists. */ |
| 261 key = hv_fetch(plugin_info, "name", strlen("name"), 0); |
300 key = hv_fetch(plugin_info, "name", strlen("name"), 0); |
| 262 info->name = g_strdup(SvPV(*key, len)); |
301 info->name = g_strdup(SvPV(*key, len)); |
| 263 |
302 |
| 277 |
316 |
| 278 if ((key = hv_fetch(plugin_info, "version", strlen("version"), 0))) |
317 if ((key = hv_fetch(plugin_info, "version", strlen("version"), 0))) |
| 279 info->version = g_strdup(SvPV(*key, len)); |
318 info->version = g_strdup(SvPV(*key, len)); |
| 280 |
319 |
| 281 if ((key = hv_fetch(plugin_info, "load", strlen("load"), 0))) |
320 if ((key = hv_fetch(plugin_info, "load", strlen("load"), 0))) |
| 282 gps->load_sub = g_strdup(SvPV(*key, len)); |
321 gps->load_sub = g_strdup_printf("%s::%s", gps->package, |
| |
322 SvPV(*key, len)); |
| 283 |
323 |
| 284 if ((key = hv_fetch(plugin_info, "unload", strlen("unload"), 0))) |
324 if ((key = hv_fetch(plugin_info, "unload", strlen("unload"), 0))) |
| 285 gps->unload_sub = g_strdup(SvPV(*key, len)); |
325 gps->unload_sub = g_strdup_printf("%s::%s", gps->package, |
| |
326 SvPV(*key, len)); |
| 286 |
327 |
| 287 plugin->info = info; |
328 plugin->info = info; |
| 288 info->extra_info = gps; |
329 info->extra_info = gps; |
| 289 |
330 |
| 290 status = gaim_plugin_register(plugin); |
331 status = gaim_plugin_register(plugin); |
| 299 |
340 |
| 300 static gboolean |
341 static gboolean |
| 301 load_perl_plugin(GaimPlugin *plugin) |
342 load_perl_plugin(GaimPlugin *plugin) |
| 302 { |
343 { |
| 303 GaimPerlScript *gps = (GaimPerlScript *)plugin->info->extra_info; |
344 GaimPerlScript *gps = (GaimPerlScript *)plugin->info->extra_info; |
| 304 char *atmp[2] = { plugin->path, NULL }; |
345 char *atmp[3] = { plugin->path, NULL, NULL }; |
| 305 |
346 |
| 306 if (gps == NULL || gps->load_sub == NULL) |
347 if (gps == NULL || gps->load_sub == NULL) |
| 307 return FALSE; |
348 return FALSE; |
| 308 |
349 |
| 309 gaim_debug(GAIM_DEBUG_INFO, "perl", "Loading perl script\n"); |
350 gaim_debug(GAIM_DEBUG_INFO, "perl", "Loading perl script\n"); |
| 310 |
351 |
| 311 if (my_perl == NULL) |
352 if (my_perl == NULL) |
| 312 perl_init(); |
353 perl_init(); |
| 313 |
354 |
| 314 plugin->handle = plugin->path; |
355 plugin->handle = gps; |
| 315 |
356 |
| 316 execute_perl("load_n_eval", 1, atmp); |
357 atmp[1] = gps->package; |
| |
358 |
| |
359 execute_perl("Gaim::PerlLoader::load_n_eval", 2, atmp); |
| 317 |
360 |
| 318 { |
361 { |
| 319 dSP; |
362 dSP; |
| 320 ENTER; |
363 ENTER; |
| 321 SAVETMPS; |
364 SAVETMPS; |
| 369 gaim_debug(GAIM_DEBUG_ERROR, "perl", |
434 gaim_debug(GAIM_DEBUG_ERROR, "perl", |
| 370 "Perl function %s exited abnormally: %s\n", |
435 "Perl function %s exited abnormally: %s\n", |
| 371 gps->load_sub, SvPV(ERRSV, len)); |
436 gps->load_sub, SvPV(ERRSV, len)); |
| 372 } |
437 } |
| 373 |
438 |
| 374 |
|
| 375 PUTBACK; |
439 PUTBACK; |
| 376 FREETMPS; |
440 FREETMPS; |
| 377 LEAVE; |
441 LEAVE; |
| 378 } |
442 } |
| 379 |
443 |
| 380 gaim_perl_signal_clear_for_plugin(plugin); |
444 gaim_perl_signal_clear_for_plugin(plugin); |
| 381 gaim_perl_timeout_clear_for_plugin(plugin); |
445 gaim_perl_timeout_clear_for_plugin(plugin); |
| 382 |
446 |
| |
447 destroy_package(gps->package); |
| |
448 |
| 383 return TRUE; |
449 return TRUE; |
| 384 } |
450 } |
| 385 |
451 |
| 386 static void |
452 static void |
| 387 destroy_perl_plugin(GaimPlugin *plugin) |
453 destroy_perl_plugin(GaimPlugin *plugin) |
| 415 if (gps->load_sub != NULL) |
481 if (gps->load_sub != NULL) |
| 416 g_free(gps->load_sub); |
482 g_free(gps->load_sub); |
| 417 |
483 |
| 418 if (gps->unload_sub != NULL) |
484 if (gps->unload_sub != NULL) |
| 419 g_free(gps->unload_sub); |
485 g_free(gps->unload_sub); |
| |
486 |
| |
487 if (gps->package != NULL) |
| |
488 g_free(gps->package); |
| 420 |
489 |
| 421 g_free(gps); |
490 g_free(gps); |
| 422 plugin->info->extra_info = NULL; |
491 plugin->info->extra_info = NULL; |
| 423 } |
492 } |
| 424 } |
493 } |