e4e26d256f3eb0d64a97de714ed2a6621e5dbc04
[jelmer/ctrlproxy.git] / src / plugins.c
1 /*
2         ctrlproxy: A modular IRC proxy
3         (c) 2002-2004 Jelmer Vernooij <jelmer@nl.linux.org>
4
5         This program is free software; you can redistribute it and/or modify
6         it under the terms of the GNU General Public License as published by
7         the Free Software Foundation; either version 2 of the License, or
8         (at your option) any later version.
9
10         This program is distributed in the hope that it will be useful,
11         but WITHOUT ANY WARRANTY; without even the implied warranty of
12         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13         GNU General Public License for more details.
14
15         You should have received a copy of the GNU General Public License
16         along with this program; if not, write to the Free Software
17         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "internals.h"
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 /* globals */
26 struct plugin *current_plugin = NULL;
27 GList *plugins = NULL;
28
29 gboolean plugin_loaded(const char *name)
30 {
31         GList *gl;
32         for (gl = plugins; gl; gl = gl->next) {
33                 struct plugin *p = (struct plugin *)gl->data;
34                 if (p && p->ops && p->ops->name && !strcmp(p->ops->name, name)) 
35                         return TRUE;
36         }
37         return FALSE;
38 }
39
40 struct plugin *load_plugin(const char *modulesdir, const char *name)
41 {
42         GModule *m = NULL;
43         struct plugin_ops *ops = NULL;
44         struct plugin *p = g_new0(struct plugin, 1);
45         gchar *path_name = NULL;
46
47         /* Try to load from .so file */
48         if (!ops) {
49
50                 if (g_file_test(name, G_FILE_TEST_EXISTS))path_name = g_strdup(name);
51                 else path_name = g_module_build_path(modulesdir, name);
52         
53                 m = g_module_open(path_name, 0);
54
55                 if (!m) {
56                         log_global(LOG_ERROR, "Unable to open module %s(%s), ignoring", path_name, g_module_error());
57                         g_free(path_name);
58                         g_free(p);
59                         return NULL;
60                 }
61
62                 if (!g_module_symbol(m, "plugin", (gpointer)&ops)) {
63                         log_global(LOG_ERROR, "%s: No valid plugin information found", 
64                                 strchr(path_name, '/')?(strrchr(path_name, '/')+1):"error"
65                                            );
66                         g_free(path_name);
67                         g_free(p);
68                         return NULL;
69                 }
70         }
71
72         if (plugin_loaded(ops->name)) {
73                 log_global(LOG_WARNING, "%s: Plugin already loaded", ops->name);
74                 g_free(path_name);
75                 g_free(p);
76                 return NULL;
77         }
78
79         g_free(path_name);
80
81         p->module = m;
82         p->ops = ops;
83
84         if (!p->ops->init()) {
85                 log_global( LOG_ERROR, "%s: Error during initialization.", p->ops->name);
86                 g_free(p);
87                 return NULL;
88         }
89
90         plugins = g_list_append(plugins, p);
91
92         return p;
93 }
94
95 gboolean init_plugins(const char *plugin_dir)
96 {
97         gboolean ret = TRUE;
98
99         if (!g_module_supported()) {
100                 log_global(LOG_WARNING, "DSO's not supported on this platform. Not loading any plugins");
101         } else {
102                 const char *name;
103                 GDir *dir = g_dir_open(plugin_dir, 0, NULL);
104                 if (!dir) {
105                         log_global(LOG_WARNING, "Plugin dir does not exist, not loading plugins");
106                         return FALSE;
107                 }
108
109                 while ((name = g_dir_read_name(dir))) {
110                         if (strcmp(name + strlen(name) - strlen(G_MODULE_SUFFIX), G_MODULE_SUFFIX) != 0)
111                                 continue;
112
113                         if (!load_plugin(plugin_dir, name))
114                                 ret = FALSE;
115                 }
116
117                 g_dir_close(dir);
118         }
119
120         return ret;
121 }
122
123 GList *get_plugin_list() {
124         return plugins;
125 }