Mercurial > pidgin.yaz
comparison src/plugin.c @ 5205:fefad67de2c7
[gaim-migrate @ 5573]
I had a damn good commit message, but it was eaten. Let's try it again.
Announcing, Gaim Plugin API version 2.0, or GPAPIV2.0 for short.
There are lots'a cool thingies here.
Okay now, this isn't as cool as the previous message, but:
1) There's now a single entry function for all plugin types. It returns a
detailed information structure on the plugin. This removes a lot of the
ugliness from old plugins. Oh yeah, libicq wasn't converted to this, so
if you use it, well, you shouldn't have used it anyway, but now you
can't! bwahahaha. Use AIM/ICQ.
2) There are now 3 types of plugins: Standard, Loader, and Protocol
plugins.
Standard plugins are, well, standard, compiled plugins.
Loader plugins load other plugins. For example, the perl support is now
a loader plugin. It loads perl scripts. In the future, we'll have
Ruby and Python loader plugins.
Protocol plugins are, well, protocol plugins... yeah...
3) Plugins have unique IDs, so they can be referred to or automatically
updated from a plugin database in the future. Neat, huh?
4) Plugins will have dependency support in the future, and can be hidden,
so if you have, say, a logging core plugin, it won't have to show up,
but then you load the GTK+ logging plugin and it'll auto-load the core
plugin. Core/UI split plugins!
5) There will eventually be custom plugin signals and RPC of some sort, for
the core/ui split plugins.
So, okay, back up .gaimrc.
I'd like to thank my parents for their support, javabsp for helping convert
a bunch of protocol plugins, and Etan for helping convert a bunch of
standard plugins.
Have fun. If you have any problems, please let me know, but you probably
won't have anything major happen. You will have to convert your plugins,
though, and I'm not guaranteeing that all perl scripts will still work.
I'll end up changing the perl script API eventually, so I know they won't
down the road. Don't worry, though. It'll be mass cool.
faceprint wants me to just commit the damn code already. So, here we go!!!
..
..
I need a massage. From a young, cute girl. Are there any young, cute girls
in the audience? IM me plz k thx.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Fri, 25 Apr 2003 06:47:33 +0000 |
parents | |
children | 0241d6b6702d |
comparison
equal
deleted
inserted
replaced
5204:44de70702205 | 5205:fefad67de2c7 |
---|---|
1 /* | |
2 * gaim | |
3 * | |
4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
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 | |
21 /* | |
22 * ---------------- | |
23 * The Plug-in plugin | |
24 * | |
25 * Plugin support is currently being maintained by Mike Saraf | |
26 * msaraf@dwc.edu | |
27 * | |
28 * Well, I didn't see any work done on it for a while, so I'm going to try | |
29 * my hand at it. - Eric warmenhoven@yahoo.com | |
30 * | |
31 * Mike is my roomate. I can assure you that he's lazy :-P | |
32 * -- Rob rob@marko.net | |
33 * | |
34 * Yeah, well now I'm re-writing a good portion of it! The perl stuff was | |
35 * a hack. Tsk tsk! -- Christian <chipx86@gnupdate.org> | |
36 */ | |
37 | |
38 #ifdef HAVE_CONFIG_H | |
39 #include <config.h> | |
40 #endif | |
41 | |
42 #include "gaim.h" | |
43 #include "prpl.h" | |
44 #include "event.h" | |
45 | |
46 #include <string.h> | |
47 | |
48 #include <sys/types.h> | |
49 #include <sys/stat.h> | |
50 | |
51 #include <unistd.h> | |
52 #include <stdio.h> | |
53 #include <stdlib.h> | |
54 | |
55 #ifdef _WIN32 | |
56 #include "win32dep.h" | |
57 #endif | |
58 | |
59 #ifdef _WIN32 | |
60 # define PLUGIN_EXT ".dll" | |
61 #else | |
62 # define PLUGIN_EXT ".so" | |
63 #endif | |
64 | |
65 static GList *loaded_plugins = NULL; | |
66 static GList *plugins = NULL; | |
67 static GList *plugin_loaders = NULL; | |
68 | |
69 static size_t search_path_count = 0; | |
70 static char **search_paths = NULL; | |
71 | |
72 static void (*probe_cb)(void *) = NULL; | |
73 static void *probe_cb_data = NULL; | |
74 static void (*load_cb)(GaimPlugin *, void *) = NULL; | |
75 static void *load_cb_data = NULL; | |
76 static void (*unload_cb)(GaimPlugin *, void *) = NULL; | |
77 static void *unload_cb_data = NULL; | |
78 | |
79 #ifdef GAIM_PLUGINS | |
80 static int | |
81 is_so_file(const char *filename, const char *ext) | |
82 { | |
83 int len, extlen; | |
84 | |
85 if (filename == NULL || *filename == '\0' || ext == NULL) | |
86 return 0; | |
87 | |
88 extlen = strlen(ext); | |
89 len = strlen(filename) - extlen; | |
90 | |
91 if (len < 0) | |
92 return 0; | |
93 | |
94 return (!strncmp(filename + len, ext, extlen)); | |
95 } | |
96 | |
97 static gboolean | |
98 __loader_supports_file(GaimPlugin *loader, const char *filename) | |
99 { | |
100 GList *l, *exts; | |
101 GaimPlugin *plugin; | |
102 | |
103 for (l = plugin_loaders; l != NULL; l = l->next) { | |
104 plugin = l->data; | |
105 | |
106 for (exts = GAIM_PLUGIN_LOADER_INFO(plugin)->exts; | |
107 exts != NULL; | |
108 exts = exts->next) { | |
109 | |
110 if (is_so_file(filename, (char *)exts->data)) | |
111 return TRUE; | |
112 } | |
113 } | |
114 | |
115 return FALSE; | |
116 } | |
117 | |
118 static GaimPlugin * | |
119 __find_loader_for_plugin(const GaimPlugin *plugin) | |
120 { | |
121 GaimPlugin *loader; | |
122 GList *l; | |
123 | |
124 if (plugin->path == NULL) | |
125 return NULL; | |
126 | |
127 for (l = gaim_plugins_get_loaded(); l != NULL; l = l->next) { | |
128 loader = l->data; | |
129 | |
130 if (loader->info->type == GAIM_PLUGIN_LOADER && | |
131 __loader_supports_file(loader, plugin->path)) { | |
132 | |
133 return loader; | |
134 } | |
135 | |
136 loader = NULL; | |
137 } | |
138 | |
139 return NULL; | |
140 } | |
141 | |
142 static gint | |
143 compare_prpl(GaimPlugin *a, GaimPlugin *b) | |
144 { | |
145 /* neg if a before b, 0 if equal, pos if a after b */ | |
146 return ((GAIM_IS_PROTOCOL_PLUGIN(a) | |
147 ? GAIM_PLUGIN_PROTOCOL_INFO(a)->protocol : -1) - | |
148 ((GAIM_IS_PROTOCOL_PLUGIN(b) | |
149 ? GAIM_PLUGIN_PROTOCOL_INFO(b)->protocol : -1))); | |
150 } | |
151 | |
152 #endif /* GAIM_PLUGINS */ | |
153 | |
154 GaimPlugin * | |
155 gaim_plugin_new(gboolean native, const char *path) | |
156 { | |
157 GaimPlugin *plugin; | |
158 | |
159 plugin = g_new0(GaimPlugin, 1); | |
160 | |
161 plugin->native_plugin = native; | |
162 plugin->path = (path == NULL ? NULL : g_strdup(path)); | |
163 | |
164 return plugin; | |
165 } | |
166 | |
167 GaimPlugin * | |
168 gaim_plugin_probe(const char *filename) | |
169 { | |
170 #ifdef GAIM_PLUGINS | |
171 GaimPlugin *plugin = NULL; | |
172 GaimPlugin *loader; | |
173 gboolean (*gaim_init_plugin)(GaimPlugin *); | |
174 | |
175 g_return_val_if_fail(filename != NULL, NULL); | |
176 | |
177 plugin = gaim_plugins_find_with_filename(filename); | |
178 | |
179 if (plugin != NULL) | |
180 return plugin; | |
181 | |
182 plugin = gaim_plugin_new(is_so_file(filename, PLUGIN_EXT), filename); | |
183 | |
184 if (plugin->native_plugin) { | |
185 plugin->handle = g_module_open(filename, 0); | |
186 | |
187 if (plugin->handle == NULL) { | |
188 plugin->error = g_strdup(g_module_error()); | |
189 | |
190 return plugin; | |
191 } | |
192 | |
193 if (!g_module_symbol(plugin->handle, "gaim_init_plugin", | |
194 (gpointer *)&gaim_init_plugin)) { | |
195 g_module_close(plugin->handle); | |
196 plugin->handle = NULL; | |
197 | |
198 debug_printf("%s is unloadable %s\n", | |
199 plugin->path, g_module_error()); | |
200 | |
201 gaim_plugin_destroy(plugin); | |
202 | |
203 return NULL; | |
204 } | |
205 } | |
206 else { | |
207 loader = __find_loader_for_plugin(plugin); | |
208 | |
209 if (loader == NULL) { | |
210 gaim_plugin_destroy(plugin); | |
211 | |
212 return NULL; | |
213 } | |
214 | |
215 gaim_init_plugin = GAIM_PLUGIN_LOADER_INFO(loader)->probe; | |
216 } | |
217 | |
218 plugin->error = NULL; | |
219 | |
220 if (!gaim_init_plugin(plugin) || plugin->info == NULL) { | |
221 char buf[BUFSIZ]; | |
222 | |
223 g_snprintf(buf, sizeof(buf), | |
224 _("The plugin %s did not return any valid plugin " | |
225 "information"), | |
226 plugin->path); | |
227 | |
228 do_error_dialog(_("Gaim was unable to load your plugin."), buf, | |
229 GAIM_ERROR); | |
230 | |
231 gaim_plugin_destroy(plugin); | |
232 | |
233 return NULL; | |
234 } | |
235 | |
236 return plugin; | |
237 #else | |
238 return NULL; | |
239 #endif /* !GAIM_PLUGINS */ | |
240 } | |
241 | |
242 gboolean | |
243 gaim_plugin_load(GaimPlugin *plugin) | |
244 { | |
245 #ifdef GAIM_PLUGINS | |
246 g_return_val_if_fail(plugin != NULL, FALSE); | |
247 | |
248 if (gaim_plugin_is_loaded(plugin)) | |
249 return TRUE; | |
250 | |
251 if (plugin->native_plugin) { | |
252 if (plugin->info != NULL && plugin->info->load != NULL) | |
253 plugin->info->load(plugin); | |
254 } | |
255 else { | |
256 GaimPlugin *loader; | |
257 GaimPluginLoaderInfo *loader_info; | |
258 | |
259 loader = __find_loader_for_plugin(plugin); | |
260 | |
261 if (loader == NULL) | |
262 return FALSE; | |
263 | |
264 loader_info = GAIM_PLUGIN_LOADER_INFO(loader); | |
265 | |
266 if (loader_info->load != NULL) | |
267 loader_info->load(plugin); | |
268 } | |
269 | |
270 loaded_plugins = g_list_append(loaded_plugins, plugin); | |
271 | |
272 plugin->loaded = TRUE; | |
273 | |
274 /* TODO */ | |
275 if (load_cb != NULL) | |
276 load_cb(plugin, load_cb_data); | |
277 | |
278 return TRUE; | |
279 | |
280 #else | |
281 return FALSE; | |
282 #endif /* !GAIM_PLUGINS */ | |
283 } | |
284 | |
285 gboolean | |
286 gaim_plugin_unload(GaimPlugin *plugin) | |
287 { | |
288 #ifdef GAIM_PLUGINS | |
289 g_return_val_if_fail(plugin != NULL, FALSE); | |
290 | |
291 loaded_plugins = g_list_remove(loaded_plugins, plugin); | |
292 | |
293 g_return_val_if_fail(gaim_plugin_is_loaded(plugin), FALSE); | |
294 | |
295 debug_printf("Unloading plugin %s\n", plugin->info->name); | |
296 | |
297 /* cancel any pending dialogs the plugin has */ | |
298 do_ask_cancel_by_handle(plugin); | |
299 | |
300 plugin->loaded = FALSE; | |
301 | |
302 if (plugin->native_plugin) { | |
303 if (plugin->info->unload != NULL) | |
304 plugin->info->unload(plugin); | |
305 | |
306 if (plugin->info->type == GAIM_PLUGIN_PROTOCOL) { | |
307 GaimPluginProtocolInfo *prpl_info; | |
308 GList *l; | |
309 struct proto_user_split *pus; | |
310 struct proto_user_opt *puo; | |
311 | |
312 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(plugin); | |
313 | |
314 for (l = prpl_info->user_splits; l != NULL; l = l->next) { | |
315 pus = l->data; | |
316 | |
317 g_free(pus->label); | |
318 g_free(pus->def); | |
319 g_free(pus); | |
320 } | |
321 | |
322 g_list_free(prpl_info->user_splits); | |
323 | |
324 for (l = prpl_info->user_opts; l != NULL; l = l->next) { | |
325 puo = l->data; | |
326 | |
327 g_free(puo->label); | |
328 g_free(puo->def); | |
329 g_free(puo); | |
330 } | |
331 | |
332 g_list_free(prpl_info->user_opts); | |
333 } | |
334 } | |
335 else { | |
336 GaimPlugin *loader; | |
337 GaimPluginLoaderInfo *loader_info; | |
338 | |
339 loader = __find_loader_for_plugin(plugin); | |
340 | |
341 if (loader == NULL) | |
342 return FALSE; | |
343 | |
344 loader_info = GAIM_PLUGIN_LOADER_INFO(loader); | |
345 | |
346 if (loader_info->load != NULL) | |
347 loader_info->unload(plugin); | |
348 } | |
349 | |
350 gaim_signals_disconnect_by_handle(plugin); | |
351 | |
352 /* TODO */ | |
353 if (unload_cb != NULL) | |
354 unload_cb(plugin, unload_cb_data); | |
355 | |
356 return TRUE; | |
357 #endif /* GAIM_PLUGINS */ | |
358 } | |
359 | |
360 gboolean | |
361 gaim_plugin_reload(GaimPlugin *plugin) | |
362 { | |
363 #ifdef GAIM_PLUGINS | |
364 g_return_val_if_fail(plugin != NULL, FALSE); | |
365 g_return_val_if_fail(gaim_plugin_is_loaded(plugin), FALSE); | |
366 | |
367 if (!gaim_plugin_unload(plugin)) | |
368 return FALSE; | |
369 | |
370 if (!gaim_plugin_load(plugin)) | |
371 return FALSE; | |
372 | |
373 return TRUE; | |
374 #else | |
375 return NULL; | |
376 #endif /* !GAIM_PLUGINS */ | |
377 } | |
378 | |
379 void | |
380 gaim_plugin_destroy(GaimPlugin *plugin) | |
381 { | |
382 g_return_if_fail(plugin != NULL); | |
383 | |
384 if (gaim_plugin_is_loaded(plugin)) | |
385 gaim_plugin_unload(plugin); | |
386 | |
387 plugins = g_list_remove(plugins, plugin); | |
388 | |
389 /* XXX */ | |
390 if (plugin->info != NULL && plugin->info->type == GAIM_PLUGIN_PROTOCOL) | |
391 return; | |
392 | |
393 if (plugin->native_plugin) { | |
394 | |
395 if (plugin->info != NULL && plugin->info->type == GAIM_PLUGIN_LOADER) { | |
396 GList *exts, *l, *next_l; | |
397 GaimPlugin *p2; | |
398 | |
399 for (exts = GAIM_PLUGIN_LOADER_INFO(plugin)->exts; | |
400 exts != NULL; | |
401 exts = exts->next) { | |
402 | |
403 for (l = gaim_plugins_get_all(); l != NULL; l = next_l) { | |
404 next_l = l->next; | |
405 | |
406 p2 = l->data; | |
407 | |
408 if (p2->path != NULL && is_so_file(p2->path, exts->data)) | |
409 gaim_plugin_destroy(p2); | |
410 } | |
411 } | |
412 | |
413 g_list_free(GAIM_PLUGIN_LOADER_INFO(plugin)->exts); | |
414 | |
415 plugin_loaders = g_list_remove(plugin_loaders, plugin); | |
416 } | |
417 | |
418 if (plugin->info != NULL && plugin->info->destroy != NULL) | |
419 plugin->info->destroy(plugin); | |
420 | |
421 if (plugin->handle != NULL) | |
422 g_module_close(plugin->handle); | |
423 } | |
424 else { | |
425 GaimPlugin *loader; | |
426 GaimPluginLoaderInfo *loader_info; | |
427 | |
428 loader = __find_loader_for_plugin(plugin); | |
429 | |
430 if (loader == NULL) | |
431 return; | |
432 | |
433 loader_info = GAIM_PLUGIN_LOADER_INFO(loader); | |
434 | |
435 if (loader_info->destroy != NULL) | |
436 loader_info->destroy(plugin); | |
437 } | |
438 | |
439 if (plugin->info != NULL && plugin->info->dependencies != NULL) | |
440 g_list_free(plugin->info->dependencies); | |
441 | |
442 if (plugin->path != NULL) g_free(plugin->path); | |
443 if (plugin->error != NULL) g_free(plugin->error); | |
444 | |
445 g_free(plugin); | |
446 } | |
447 | |
448 gboolean | |
449 gaim_plugin_is_loaded(const GaimPlugin *plugin) | |
450 { | |
451 g_return_val_if_fail(plugin != NULL, FALSE); | |
452 | |
453 return plugin->loaded; | |
454 } | |
455 | |
456 void | |
457 gaim_plugins_set_search_paths(size_t count, char **paths) | |
458 { | |
459 size_t s; | |
460 | |
461 g_return_if_fail(count > 0); | |
462 g_return_if_fail(paths != NULL); | |
463 | |
464 if (search_paths != NULL) { | |
465 for (s = 0; s < search_path_count; s++) | |
466 g_free(search_paths[s]); | |
467 | |
468 g_free(search_paths); | |
469 } | |
470 | |
471 search_paths = g_new0(char *, count); | |
472 | |
473 for (s = 0; s < count; s++) { | |
474 if (paths[s] == NULL) | |
475 search_paths[s] = NULL; | |
476 else | |
477 search_paths[s] = g_strdup(paths[s]); | |
478 } | |
479 | |
480 search_path_count = count; | |
481 } | |
482 | |
483 void | |
484 gaim_plugins_unload_all(void) | |
485 { | |
486 #ifdef GAIM_PLUGINS | |
487 | |
488 while (loaded_plugins != NULL) | |
489 gaim_plugin_unload(loaded_plugins->data); | |
490 | |
491 #endif /* GAIM_PLUGINS */ | |
492 } | |
493 | |
494 void | |
495 gaim_plugins_probe(const char *ext) | |
496 { | |
497 #ifdef GAIM_PLUGINS | |
498 GDir *dir; | |
499 const gchar *file; | |
500 gchar *path; | |
501 GaimPlugin *plugin; | |
502 size_t i; | |
503 | |
504 if (!g_module_supported()) | |
505 return; | |
506 | |
507 for (i = 0; i < search_path_count; i++) { | |
508 if (search_paths[i] == NULL) | |
509 continue; | |
510 | |
511 dir = g_dir_open(search_paths[i], 0, NULL); | |
512 | |
513 if (dir != NULL) { | |
514 while ((file = g_dir_read_name(dir)) != NULL) { | |
515 path = g_build_filename(search_paths[i], file, NULL); | |
516 | |
517 if (ext == NULL || is_so_file(file, ext)) | |
518 plugin = gaim_plugin_probe(path); | |
519 | |
520 g_free(path); | |
521 } | |
522 | |
523 g_dir_close(dir); | |
524 } | |
525 } | |
526 | |
527 if (probe_cb != NULL) | |
528 probe_cb(probe_cb_data); | |
529 | |
530 #endif /* GAIM_PLUGINS */ | |
531 } | |
532 | |
533 gboolean | |
534 gaim_plugin_register(GaimPlugin *plugin) | |
535 { | |
536 #ifdef GAIM_PLUGINS | |
537 g_return_val_if_fail(plugin != NULL, FALSE); | |
538 | |
539 if (g_list_find(plugins, plugin)) | |
540 return TRUE; | |
541 | |
542 /* Special exception for loader plugins. We want them loaded NOW! */ | |
543 if (plugin->info->type == GAIM_PLUGIN_LOADER) { | |
544 GList *exts; | |
545 | |
546 /* We'll just load this right now. */ | |
547 if (!gaim_plugin_load(plugin)) { | |
548 | |
549 gaim_plugin_destroy(plugin); | |
550 | |
551 return FALSE; | |
552 } | |
553 | |
554 plugin_loaders = g_list_append(plugin_loaders, plugin); | |
555 | |
556 for (exts = GAIM_PLUGIN_LOADER_INFO(plugin)->exts; | |
557 exts != NULL; | |
558 exts = exts->next) { | |
559 | |
560 gaim_plugins_probe(exts->data); | |
561 } | |
562 } | |
563 else if (plugin->info->type == GAIM_PLUGIN_PROTOCOL) { | |
564 | |
565 /* We'll just load this right now. */ | |
566 if (!gaim_plugin_load(plugin)) { | |
567 | |
568 gaim_plugin_destroy(plugin); | |
569 | |
570 return FALSE; | |
571 } | |
572 | |
573 if (GAIM_PLUGIN_PROTOCOL_INFO(plugin)->protocol == GAIM_PROTO_ICQ || | |
574 gaim_find_prpl(GAIM_PLUGIN_PROTOCOL_INFO(plugin)->protocol)) { | |
575 | |
576 /* Nothing to see here--move along, move along */ | |
577 gaim_plugin_destroy(plugin); | |
578 | |
579 return FALSE; | |
580 } | |
581 | |
582 protocols = g_slist_insert_sorted(protocols, plugin, | |
583 (GCompareFunc)compare_prpl); | |
584 } | |
585 | |
586 plugins = g_list_append(plugins, plugin); | |
587 | |
588 return TRUE; | |
589 #else | |
590 return FALSE; | |
591 #endif /* !GAIM_PLUGINS */ | |
592 } | |
593 | |
594 gboolean | |
595 gaim_plugins_enabled(void) | |
596 { | |
597 #ifdef GAIM_PLUGINS | |
598 return TRUE; | |
599 #else | |
600 return FALSE; | |
601 #endif | |
602 } | |
603 | |
604 void | |
605 gaim_plugins_register_probe_notify_cb(void (*func)(void *), void *data) | |
606 { | |
607 /* TODO */ | |
608 probe_cb = func; | |
609 probe_cb_data = data; | |
610 } | |
611 | |
612 void | |
613 gaim_plugins_unregister_probe_notify_cb(void (*func)(void *)) | |
614 { | |
615 /* TODO */ | |
616 probe_cb = NULL; | |
617 probe_cb_data = NULL; | |
618 } | |
619 | |
620 void | |
621 gaim_plugins_register_load_notify_cb(void (*func)(GaimPlugin *, void *), | |
622 void *data) | |
623 { | |
624 /* TODO */ | |
625 load_cb = func; | |
626 load_cb_data = data; | |
627 } | |
628 | |
629 void | |
630 gaim_plugins_unregister_load_notify_cb(void (*func)(GaimPlugin *, void *)) | |
631 { | |
632 /* TODO */ | |
633 load_cb = NULL; | |
634 load_cb_data = NULL; | |
635 } | |
636 | |
637 void | |
638 gaim_plugins_register_unload_notify_cb(void (*func)(GaimPlugin *, void *), | |
639 void *data) | |
640 { | |
641 /* TODO */ | |
642 unload_cb = func; | |
643 unload_cb_data = data; | |
644 } | |
645 | |
646 void | |
647 gaim_plugins_unregister_unload_notify_cb(void (*func)(GaimPlugin *, void *)) | |
648 { | |
649 /* TODO */ | |
650 unload_cb = NULL; | |
651 unload_cb_data = NULL; | |
652 } | |
653 | |
654 GaimPlugin * | |
655 gaim_plugins_find_with_name(const char *name) | |
656 { | |
657 GaimPlugin *plugin; | |
658 GList *l; | |
659 | |
660 for (l = plugins; l != NULL; l = l->next) { | |
661 plugin = l->data; | |
662 | |
663 if (!strcmp(plugin->info->name, name)) | |
664 return plugin; | |
665 } | |
666 | |
667 return NULL; | |
668 } | |
669 | |
670 GaimPlugin * | |
671 gaim_plugins_find_with_filename(const char *filename) | |
672 { | |
673 GaimPlugin *plugin; | |
674 GList *l; | |
675 | |
676 for (l = plugins; l != NULL; l = l->next) { | |
677 plugin = l->data; | |
678 | |
679 if (plugin->path != NULL && !strcmp(plugin->path, filename)) | |
680 return plugin; | |
681 } | |
682 | |
683 return NULL; | |
684 } | |
685 | |
686 GaimPlugin * | |
687 gaim_plugins_find_with_id(const char *id) | |
688 { | |
689 GaimPlugin *plugin; | |
690 GList *l; | |
691 | |
692 g_return_val_if_fail(id != NULL, NULL); | |
693 | |
694 for (l = plugins; l != NULL; l = l->next) { | |
695 plugin = l->data; | |
696 | |
697 if (!strcmp(plugin->info->id, id)) | |
698 return plugin; | |
699 } | |
700 | |
701 return NULL; | |
702 } | |
703 | |
704 GList * | |
705 gaim_plugins_get_loaded(void) | |
706 { | |
707 return loaded_plugins; | |
708 } | |
709 | |
710 GList * | |
711 gaim_plugins_get_all(void) | |
712 { | |
713 return plugins; | |
714 } | |
715 |