|
14192
|
1 /*
|
|
|
2 * gaim
|
|
|
3 *
|
|
|
4 * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
|
|
|
5 *
|
|
|
6 * This program is free software; you can redistribute it and/or modify
|
|
|
7 * it under the terms of the GNU General Public License as published by
|
|
|
8 * the Free Software Foundation; either version 2 of the License, or
|
|
|
9 * (at your option) any later version.
|
|
|
10 *
|
|
|
11 * This program is distributed in the hope that it will be useful,
|
|
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
14 * GNU General Public License for more details.
|
|
|
15 *
|
|
|
16 * You should have received a copy of the GNU General Public License
|
|
|
17 * along with this program; if not, write to the Free Software
|
|
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
19 */
|
|
|
20 #ifdef HAVE_CONFIG_H
|
|
|
21 #include <config.h>
|
|
|
22 # ifdef HAVE_LIMITS_H
|
|
|
23 # include <limits.h>
|
|
|
24 # ifndef NAME_MAX
|
|
|
25 # define NAME_MAX _POSIX_NAME_MAX
|
|
|
26 # endif
|
|
|
27 # endif
|
|
|
28 #endif
|
|
|
29
|
|
|
30 #ifdef DEBUG
|
|
|
31 # undef DEBUG
|
|
|
32 #endif
|
|
|
33
|
|
|
34 #undef PACKAGE
|
|
|
35
|
|
|
36 #define group perl_group
|
|
|
37
|
|
|
38 #ifdef _WIN32
|
|
|
39 /* This took me an age to figure out.. without this __declspec(dllimport)
|
|
|
40 * will be ignored.
|
|
|
41 */
|
|
|
42 # define HASATTRIBUTE
|
|
|
43 #endif
|
|
|
44
|
|
|
45 #include <EXTERN.h>
|
|
|
46
|
|
|
47 #ifndef _SEM_SEMUN_UNDEFINED
|
|
|
48 # define HAS_UNION_SEMUN
|
|
|
49 #endif
|
|
|
50
|
|
|
51 #include <perl.h>
|
|
|
52 #include <XSUB.h>
|
|
|
53
|
|
|
54 #ifndef _WIN32
|
|
|
55 # include <sys/mman.h>
|
|
|
56 #endif
|
|
|
57
|
|
|
58 #undef PACKAGE
|
|
|
59
|
|
|
60 #ifndef _WIN32
|
|
|
61 # include <dirent.h>
|
|
|
62 #else
|
|
|
63 /* We're using perl's win32 port of this */
|
|
|
64 # define dirent direct
|
|
|
65 #endif
|
|
|
66
|
|
|
67 #undef group
|
|
|
68
|
|
|
69 /* perl module support */
|
|
|
70 #ifdef OLD_PERL
|
|
|
71 extern void boot_DynaLoader _((CV * cv));
|
|
|
72 #else
|
|
|
73 extern void boot_DynaLoader _((pTHX_ CV * cv)); /* perl is so wacky */
|
|
|
74 #endif
|
|
|
75
|
|
|
76 #undef _
|
|
|
77 #ifdef DEBUG
|
|
|
78 # undef DEBUG
|
|
|
79 #endif
|
|
|
80 #ifdef _WIN32
|
|
|
81 # undef pipe
|
|
|
82 #endif
|
|
|
83
|
|
|
84 #ifdef _WIN32
|
|
|
85 #define _WIN32DEP_H_
|
|
|
86 #endif
|
|
|
87 #include "internal.h"
|
|
|
88 #include "debug.h"
|
|
|
89 #include "plugin.h"
|
|
|
90 #include "signals.h"
|
|
|
91 #include "version.h"
|
|
|
92
|
|
|
93 #include "perl-common.h"
|
|
|
94 #include "perl-handlers.h"
|
|
|
95
|
|
|
96 #define PERL_PLUGIN_ID "core-perl"
|
|
|
97
|
|
|
98 PerlInterpreter *my_perl = NULL;
|
|
|
99
|
|
|
100 static GaimPluginUiInfo ui_info =
|
|
|
101 {
|
|
|
102 gaim_perl_get_plugin_frame,
|
|
|
103 0, /* page_num (Reserved) */
|
|
|
104 NULL /* frame (Reserved) */
|
|
|
105 };
|
|
|
106
|
|
|
107 static GaimGtkPluginUiInfo gtk_ui_info =
|
|
|
108 {
|
|
|
109 gaim_perl_gtk_get_plugin_frame,
|
|
|
110 0 /* page_num (Reserved) */
|
|
|
111 };
|
|
|
112
|
|
|
113 static void
|
|
|
114 #ifdef OLD_PERL
|
|
|
115 xs_init()
|
|
|
116 #else
|
|
|
117 xs_init(pTHX)
|
|
|
118 #endif
|
|
|
119 {
|
|
|
120 char *file = __FILE__;
|
|
|
121
|
|
|
122 /* This one allows dynamic loading of perl modules in perl scripts by
|
|
|
123 * the 'use perlmod;' construction */
|
|
|
124 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
|
|
|
125 }
|
|
|
126
|
|
|
127 static void
|
|
|
128 perl_init(void)
|
|
|
129 {
|
|
|
130 /* changed the name of the variable from load_file to perl_definitions
|
|
|
131 * since now it does much more than defining the load_file sub.
|
|
|
132 * Moreover, deplaced the initialisation to the xs_init function.
|
|
|
133 * (TheHobbit) */
|
|
|
134 char *perl_args[] = { "", "-e", "0", "-w" };
|
|
|
135 char perl_definitions[] =
|
|
|
136 {
|
|
|
137 /* We use to function one to load a file the other to execute
|
|
|
138 * the string obtained from the first and holding the file
|
|
|
139 * contents. This allows to have a really local $/ without
|
|
|
140 * introducing temp variables to hold the old value. Just a
|
|
|
141 * question of style:) */
|
|
|
142 "package Gaim::PerlLoader;"
|
|
|
143 "use Symbol;"
|
|
|
144
|
|
|
145 "sub load_file {"
|
|
|
146 "my $f_name=shift;"
|
|
|
147 "local $/=undef;"
|
|
|
148 "open FH,$f_name or return \"__FAILED__\";"
|
|
|
149 "$_=<FH>;"
|
|
|
150 "close FH;"
|
|
|
151 "return $_;"
|
|
|
152 "}"
|
|
|
153
|
|
|
154 "sub destroy_package {"
|
|
|
155 "eval { $_[0]->UNLOAD() if $_[0]->can('UNLOAD'); };"
|
|
|
156 "Symbol::delete_package($_[0]);"
|
|
|
157 "}"
|
|
|
158
|
|
|
159 "sub load_n_eval {"
|
|
|
160 "my ($f_name, $package) = @_;"
|
|
|
161 "destroy_package($package);"
|
|
|
162 "my $strin=load_file($f_name);"
|
|
|
163 "return 2 if($strin eq \"__FAILED__\");"
|
|
|
164 "my $eval = qq{package $package; $strin;};"
|
|
|
165
|
|
|
166 "{"
|
|
|
167 " eval $eval;"
|
|
|
168 "}"
|
|
|
169
|
|
|
170 "if($@) {"
|
|
|
171 /*" #something went wrong\n"*/
|
|
|
172 "die(\"Errors loading file $f_name: $@\");"
|
|
|
173 "}"
|
|
|
174
|
|
|
175 "return 0;"
|
|
|
176 "}"
|
|
|
177 };
|
|
|
178
|
|
|
179 my_perl = perl_alloc();
|
|
|
180 PERL_SET_CONTEXT(my_perl);
|
|
|
181 PL_perl_destruct_level = 1;
|
|
|
182 perl_construct(my_perl);
|
|
|
183 #ifdef DEBUG
|
|
|
184 perl_parse(my_perl, xs_init, 4, perl_args, NULL);
|
|
|
185 #else
|
|
|
186 perl_parse(my_perl, xs_init, 3, perl_args, NULL);
|
|
|
187 #endif
|
|
|
188 #ifdef HAVE_PERL_EVAL_PV
|
|
|
189 eval_pv(perl_definitions, TRUE);
|
|
|
190 #else
|
|
|
191 perl_eval_pv(perl_definitions, TRUE); /* deprecated */
|
|
|
192 #endif
|
|
|
193 perl_run(my_perl);
|
|
|
194 }
|
|
|
195
|
|
|
196 static void
|
|
|
197 perl_end(void)
|
|
|
198 {
|
|
|
199 if (my_perl == NULL)
|
|
|
200 return;
|
|
|
201
|
|
|
202 PL_perl_destruct_level = 1;
|
|
|
203 PERL_SET_CONTEXT(my_perl);
|
|
|
204 perl_eval_pv(
|
|
|
205 "foreach my $lib (@DynaLoader::dl_modules) {"
|
|
|
206 "if ($lib =~ /^Gaim\\b/) {"
|
|
|
207 "$lib .= '::deinit();';"
|
|
|
208 "eval $lib;"
|
|
|
209 "}"
|
|
|
210 "}",
|
|
|
211 TRUE);
|
|
|
212
|
|
|
213 PL_perl_destruct_level = 1;
|
|
|
214 PERL_SET_CONTEXT(my_perl);
|
|
|
215 perl_destruct(my_perl);
|
|
|
216 perl_free(my_perl);
|
|
|
217 my_perl = NULL;
|
|
|
218 }
|
|
|
219
|
|
|
220 void
|
|
|
221 gaim_perl_callXS(void (*subaddr)(pTHX_ CV *cv), CV *cv, SV **mark)
|
|
|
222 {
|
|
|
223 dSP;
|
|
|
224
|
|
|
225 PUSHMARK(mark);
|
|
|
226 (*subaddr)(aTHX_ cv);
|
|
|
227
|
|
|
228 PUTBACK;
|
|
|
229 }
|
|
|
230
|
|
|
231 static gboolean
|
|
|
232 probe_perl_plugin(GaimPlugin *plugin)
|
|
|
233 {
|
|
|
234 /* XXX This would be much faster if I didn't create a new
|
|
|
235 * PerlInterpreter every time I probed a plugin */
|
|
|
236
|
|
|
237 PerlInterpreter *prober = perl_alloc();
|
|
|
238 char *argv[] = {"", plugin->path };
|
|
|
239 gboolean status = TRUE;
|
|
|
240 HV *plugin_info;
|
|
|
241 PERL_SET_CONTEXT(prober);
|
|
|
242 PL_perl_destruct_level = 1;
|
|
|
243 perl_construct(prober);
|
|
|
244
|
|
|
245 perl_parse(prober, xs_init, 2, argv, NULL);
|
|
|
246
|
|
|
247 perl_run(prober);
|
|
|
248
|
|
|
249 plugin_info = perl_get_hv("PLUGIN_INFO", FALSE);
|
|
|
250
|
|
|
251 if (plugin_info == NULL)
|
|
|
252 status = FALSE;
|
|
|
253 else if (!hv_exists(plugin_info, "perl_api_version",
|
|
|
254 strlen("perl_api_version")) ||
|
|
|
255 !hv_exists(plugin_info, "name", strlen("name")) ||
|
|
|
256 !hv_exists(plugin_info, "load", strlen("load"))) {
|
|
|
257 /* Not a valid plugin. */
|
|
|
258
|
|
|
259 status = FALSE;
|
|
|
260 } else {
|
|
|
261 SV **key;
|
|
|
262 int perl_api_ver;
|
|
|
263
|
|
|
264 key = hv_fetch(plugin_info, "perl_api_version",
|
|
|
265 strlen("perl_api_version"), 0);
|
|
|
266
|
|
|
267 perl_api_ver = SvIV(*key);
|
|
|
268
|
|
|
269 if (perl_api_ver != 2)
|
|
|
270 status = FALSE;
|
|
|
271 else {
|
|
|
272 GaimPluginInfo *info;
|
|
|
273 GaimPerlScript *gps;
|
|
|
274 char *basename;
|
|
|
275 STRLEN len;
|
|
|
276
|
|
|
277 gaim_debug(GAIM_DEBUG_INFO, "perl",
|
|
|
278 "Found plugin info\n");
|
|
|
279
|
|
|
280 info = g_new0(GaimPluginInfo, 1);
|
|
|
281 gps = g_new0(GaimPerlScript, 1);
|
|
|
282
|
|
|
283 info->magic = GAIM_PLUGIN_MAGIC;
|
|
|
284 info->major_version = GAIM_MAJOR_VERSION;
|
|
|
285 info->minor_version = GAIM_MINOR_VERSION;
|
|
|
286 info->type = GAIM_PLUGIN_STANDARD;
|
|
|
287
|
|
|
288 info->dependencies = g_list_append(info->dependencies,
|
|
|
289 PERL_PLUGIN_ID);
|
|
|
290
|
|
|
291 gps->plugin = plugin;
|
|
|
292
|
|
|
293 basename = g_path_get_basename(plugin->path);
|
|
|
294 gaim_perl_normalize_script_name(basename);
|
|
|
295 gps->package = g_strdup_printf("Gaim::Script::%s",
|
|
|
296 basename);
|
|
|
297 g_free(basename);
|
|
|
298
|
|
|
299 /* We know this one exists. */
|
|
|
300 key = hv_fetch(plugin_info, "name", strlen("name"), 0);
|
|
|
301 info->name = g_strdup(SvPV(*key, len));
|
|
|
302 /* Set id here in case we don't find one later. */
|
|
|
303 info->id = g_strdup(SvPV(*key, len));
|
|
|
304
|
|
|
305 if ((key = hv_fetch(plugin_info, "GTK_UI",
|
|
|
306 strlen("GTK_UI"), 0)))
|
|
|
307 info->ui_requirement = GAIM_GTK_PLUGIN_TYPE;
|
|
|
308
|
|
|
309 if ((key = hv_fetch(plugin_info, "url",
|
|
|
310 strlen("url"), 0)))
|
|
|
311 info->homepage = g_strdup(SvPV(*key, len));
|
|
|
312
|
|
|
313 if ((key = hv_fetch(plugin_info, "author",
|
|
|
314 strlen("author"), 0)))
|
|
|
315 info->author = g_strdup(SvPV(*key, len));
|
|
|
316
|
|
|
317 if ((key = hv_fetch(plugin_info, "summary",
|
|
|
318 strlen("summary"), 0)))
|
|
|
319 info->summary = g_strdup(SvPV(*key, len));
|
|
|
320
|
|
|
321 if ((key = hv_fetch(plugin_info, "description",
|
|
|
322 strlen("description"), 0)))
|
|
|
323 info->description = g_strdup(SvPV(*key, len));
|
|
|
324
|
|
|
325 if ((key = hv_fetch(plugin_info, "version",
|
|
|
326 strlen("version"), 0)))
|
|
|
327 info->version = g_strdup(SvPV(*key, len));
|
|
|
328
|
|
|
329 /* We know this one exists. */
|
|
|
330 key = hv_fetch(plugin_info, "load", strlen("load"), 0);
|
|
|
331 gps->load_sub = g_strdup_printf("%s::%s", gps->package,
|
|
|
332 SvPV(*key, len));
|
|
|
333
|
|
|
334 if ((key = hv_fetch(plugin_info, "unload",
|
|
|
335 strlen("unload"), 0)))
|
|
|
336 gps->unload_sub = g_strdup_printf("%s::%s",
|
|
|
337 gps->package,
|
|
|
338 SvPV(*key, len));
|
|
|
339
|
|
|
340 if ((key = hv_fetch(plugin_info, "id",
|
|
|
341 strlen("id"), 0))) {
|
|
|
342 g_free(info->id);
|
|
|
343 info->id = g_strdup_printf("perl-%s",
|
|
|
344 SvPV(*key, len));
|
|
|
345 }
|
|
|
346
|
|
|
347 /********************************************************/
|
|
|
348 /* Only one of the next two options should be present */
|
|
|
349 /* */
|
|
|
350 /* prefs_info - Uses non-GUI (read GTK) gaim API calls */
|
|
|
351 /* and creates a GaimPluginPrefInfo type. */
|
|
|
352 /* */
|
|
|
353 /* gtk_prefs_info - Requires gtk2-perl be installed by */
|
|
|
354 /* the user and he must create a */
|
|
|
355 /* GtkWidget the user and he must */
|
|
|
356 /* create a GtkWidget representing the */
|
|
|
357 /* plugin preferences page. */
|
|
|
358 /********************************************************/
|
|
|
359 if ((key = hv_fetch(plugin_info, "prefs_info",
|
|
|
360 strlen("prefs_info"), 0))) {
|
|
|
361 /* key now is the name of the Perl sub that
|
|
|
362 * will create a frame for us */
|
|
|
363 gps->prefs_sub = g_strdup_printf("%s::%s",
|
|
|
364 gps->package,
|
|
|
365 SvPV(*key, len));
|
|
|
366 info->prefs_info = &ui_info;
|
|
|
367 }
|
|
|
368
|
|
|
369 if ((key = hv_fetch(plugin_info, "gtk_prefs_info",
|
|
|
370 strlen("gtk_prefs_info"), 0))) {
|
|
|
371 /* key now is the name of the Perl sub that
|
|
|
372 * will create a frame for us */
|
|
|
373 gps->gtk_prefs_sub = g_strdup_printf("%s::%s",
|
|
|
374 gps->package,
|
|
|
375 SvPV(*key, len));
|
|
|
376 info->ui_info = >k_ui_info;
|
|
|
377 }
|
|
|
378
|
|
|
379 if ((key = hv_fetch(plugin_info, "plugin_action_sub",
|
|
|
380 strlen("plugin_action_sub"), 0))) {
|
|
|
381 gps->plugin_action_sub = g_strdup_printf("%s::%s",
|
|
|
382 gps->package,
|
|
|
383 SvPV(*key, len));
|
|
|
384 info->actions = gaim_perl_plugin_actions;
|
|
|
385 }
|
|
|
386
|
|
|
387 plugin->info = info;
|
|
|
388 info->extra_info = gps;
|
|
|
389
|
|
|
390 status = gaim_plugin_register(plugin);
|
|
|
391 }
|
|
|
392 }
|
|
|
393
|
|
|
394 PL_perl_destruct_level = 1;
|
|
|
395 PERL_SET_CONTEXT(prober);
|
|
|
396 perl_destruct(prober);
|
|
|
397 perl_free(prober);
|
|
|
398 return status;
|
|
|
399 }
|
|
|
400
|
|
|
401 static gboolean
|
|
|
402 load_perl_plugin(GaimPlugin *plugin)
|
|
|
403 {
|
|
|
404 GaimPerlScript *gps = (GaimPerlScript *)plugin->info->extra_info;
|
|
|
405 char *atmp[3] = { plugin->path, NULL, NULL };
|
|
|
406
|
|
|
407 if (gps == NULL || gps->load_sub == NULL)
|
|
|
408 return FALSE;
|
|
|
409
|
|
|
410 gaim_debug(GAIM_DEBUG_INFO, "perl", "Loading perl script\n");
|
|
|
411
|
|
|
412 if (my_perl == NULL)
|
|
|
413 perl_init();
|
|
|
414
|
|
|
415 plugin->handle = gps;
|
|
|
416
|
|
|
417 atmp[1] = gps->package;
|
|
|
418
|
|
|
419 PERL_SET_CONTEXT(my_perl);
|
|
|
420 execute_perl("Gaim::PerlLoader::load_n_eval", 2, atmp);
|
|
|
421
|
|
|
422 {
|
|
|
423 dSP;
|
|
|
424 PERL_SET_CONTEXT(my_perl);
|
|
|
425 SPAGAIN;
|
|
|
426 ENTER;
|
|
|
427 SAVETMPS;
|
|
|
428 PUSHMARK(sp);
|
|
|
429 XPUSHs(sv_2mortal(gaim_perl_bless_object(plugin,
|
|
|
430 "Gaim::Plugin")));
|
|
|
431 PUTBACK;
|
|
|
432
|
|
|
433 perl_call_pv(gps->load_sub, G_EVAL | G_SCALAR);
|
|
|
434 SPAGAIN;
|
|
|
435
|
|
|
436 if (SvTRUE(ERRSV)) {
|
|
|
437 STRLEN len;
|
|
|
438
|
|
|
439 gaim_debug(GAIM_DEBUG_ERROR, "perl",
|
|
|
440 "Perl function %s exited abnormally: %s\n",
|
|
|
441 gps->load_sub, SvPV(ERRSV, len));
|
|
|
442 }
|
|
|
443
|
|
|
444 PUTBACK;
|
|
|
445 FREETMPS;
|
|
|
446 LEAVE;
|
|
|
447 }
|
|
|
448
|
|
|
449 return TRUE;
|
|
|
450 }
|
|
|
451
|
|
|
452 static void
|
|
|
453 destroy_package(const char *package)
|
|
|
454 {
|
|
|
455 dSP;
|
|
|
456 PERL_SET_CONTEXT(my_perl);
|
|
|
457 SPAGAIN;
|
|
|
458
|
|
|
459 ENTER;
|
|
|
460 SAVETMPS;
|
|
|
461
|
|
|
462 PUSHMARK(SP);
|
|
|
463 XPUSHs(sv_2mortal(newSVpv(package, strlen(package))));
|
|
|
464 PUTBACK;
|
|
|
465
|
|
|
466 perl_call_pv("Gaim::PerlLoader::destroy_package",
|
|
|
467 G_VOID | G_EVAL | G_DISCARD);
|
|
|
468
|
|
|
469 SPAGAIN;
|
|
|
470
|
|
|
471 PUTBACK;
|
|
|
472 FREETMPS;
|
|
|
473 LEAVE;
|
|
|
474 }
|
|
|
475
|
|
|
476 static gboolean
|
|
|
477 unload_perl_plugin(GaimPlugin *plugin)
|
|
|
478 {
|
|
|
479 GaimPerlScript *gps = (GaimPerlScript *)plugin->info->extra_info;
|
|
|
480
|
|
|
481 if (gps == NULL)
|
|
|
482 return FALSE;
|
|
|
483
|
|
|
484 gaim_debug(GAIM_DEBUG_INFO, "perl", "Unloading perl script\n");
|
|
|
485
|
|
|
486 if (gps->unload_sub != NULL) {
|
|
|
487 dSP;
|
|
|
488 PERL_SET_CONTEXT(my_perl);
|
|
|
489 SPAGAIN;
|
|
|
490 ENTER;
|
|
|
491 SAVETMPS;
|
|
|
492 PUSHMARK(sp);
|
|
|
493 XPUSHs(sv_2mortal(gaim_perl_bless_object(plugin,
|
|
|
494 "Gaim::Plugin")));
|
|
|
495 PUTBACK;
|
|
|
496
|
|
|
497 perl_call_pv(gps->unload_sub, G_EVAL | G_SCALAR);
|
|
|
498 SPAGAIN;
|
|
|
499
|
|
|
500 if (SvTRUE(ERRSV)) {
|
|
|
501 STRLEN len;
|
|
|
502
|
|
|
503 gaim_debug(GAIM_DEBUG_ERROR, "perl",
|
|
|
504 "Perl function %s exited abnormally: %s\n",
|
|
|
505 gps->load_sub, SvPV(ERRSV, len));
|
|
|
506 }
|
|
|
507
|
|
|
508 PUTBACK;
|
|
|
509 FREETMPS;
|
|
|
510 LEAVE;
|
|
|
511 }
|
|
|
512
|
|
|
513 gaim_perl_cmd_clear_for_plugin(plugin);
|
|
|
514 gaim_perl_signal_clear_for_plugin(plugin);
|
|
|
515 gaim_perl_timeout_clear_for_plugin(plugin);
|
|
|
516
|
|
|
517 destroy_package(gps->package);
|
|
|
518
|
|
|
519 return TRUE;
|
|
|
520 }
|
|
|
521
|
|
|
522 static void
|
|
|
523 destroy_perl_plugin(GaimPlugin *plugin)
|
|
|
524 {
|
|
|
525 if (plugin->info != NULL) {
|
|
|
526 GaimPerlScript *gps;
|
|
|
527
|
|
|
528 g_free(plugin->info->name);
|
|
|
529 g_free(plugin->info->version);
|
|
|
530 g_free(plugin->info->summary);
|
|
|
531 g_free(plugin->info->description);
|
|
|
532 g_free(plugin->info->author);
|
|
|
533 g_free(plugin->info->homepage);
|
|
|
534
|
|
|
535 gps = (GaimPerlScript *)plugin->info->extra_info;
|
|
|
536 if (gps != NULL) {
|
|
|
537 g_free(gps->load_sub);
|
|
|
538 g_free(gps->unload_sub);
|
|
|
539 g_free(gps->package);
|
|
|
540 g_free(gps->prefs_sub);
|
|
|
541 g_free(gps->gtk_prefs_sub);
|
|
|
542 g_free(gps);
|
|
|
543 plugin->info->extra_info = NULL;
|
|
|
544 }
|
|
|
545 }
|
|
|
546 }
|
|
|
547
|
|
|
548 static gboolean
|
|
|
549 plugin_load(GaimPlugin *plugin)
|
|
|
550 {
|
|
|
551 return TRUE;
|
|
|
552 }
|
|
|
553
|
|
|
554 static gboolean
|
|
|
555 plugin_unload(GaimPlugin *plugin)
|
|
|
556 {
|
|
|
557 perl_end();
|
|
|
558
|
|
|
559 return TRUE;
|
|
|
560 }
|
|
|
561
|
|
|
562 static GaimPluginLoaderInfo loader_info =
|
|
|
563 {
|
|
|
564 NULL, /**< exts */
|
|
|
565 probe_perl_plugin, /**< probe */
|
|
|
566 load_perl_plugin, /**< load */
|
|
|
567 unload_perl_plugin, /**< unload */
|
|
|
568 destroy_perl_plugin /**< destroy */
|
|
|
569 };
|
|
|
570
|
|
|
571 static GaimPluginInfo info =
|
|
|
572 {
|
|
|
573 GAIM_PLUGIN_MAGIC,
|
|
|
574 GAIM_MAJOR_VERSION,
|
|
|
575 GAIM_MINOR_VERSION,
|
|
|
576 GAIM_PLUGIN_LOADER, /**< type */
|
|
|
577 NULL, /**< ui_requirement */
|
|
|
578 0, /**< flags */
|
|
|
579 NULL, /**< dependencies */
|
|
|
580 GAIM_PRIORITY_DEFAULT, /**< priority */
|
|
|
581
|
|
|
582 PERL_PLUGIN_ID, /**< id */
|
|
|
583 N_("Perl Plugin Loader"), /**< name */
|
|
|
584 VERSION, /**< version */
|
|
|
585 N_("Provides support for loading perl plugins."), /**< summary */
|
|
|
586 N_("Provides support for loading perl plugins."), /**< description */
|
|
|
587 "Christian Hammond <chipx86@gnupdate.org>", /**< author */
|
|
|
588 GAIM_WEBSITE, /**< homepage */
|
|
|
589
|
|
|
590 plugin_load, /**< load */
|
|
|
591 plugin_unload, /**< unload */
|
|
|
592 NULL, /**< destroy */
|
|
|
593
|
|
|
594 NULL, /**< ui_info */
|
|
|
595 &loader_info, /**< extra_info */
|
|
|
596 NULL,
|
|
|
597 NULL
|
|
|
598 };
|
|
|
599
|
|
|
600 static void
|
|
|
601 init_plugin(GaimPlugin *plugin)
|
|
|
602 {
|
|
|
603 loader_info.exts = g_list_append(loader_info.exts, "pl");
|
|
|
604 }
|
|
|
605
|
|
|
606 GAIM_INIT_PLUGIN(perl, init_plugin, info)
|