5bbcf0b53ab61a5e54898a6ca845e8db1eb3cc28
[silc.git] / apps / irssi / src / fe-common / core / fe-modules.c
1 /*
2  fe-common-core.c : irssi
3
4     Copyright (C) 1999-2000 Timo Sirainen
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 #include "module.h"
22 #include "modules.h"
23 #include "modules-load.h"
24 #include "module-formats.h"
25 #include "signals.h"
26 #include "commands.h"
27 #include "levels.h"
28 #include "chat-protocols.h"
29
30 #include "printtext.h"
31
32 #ifdef HAVE_GMODULE
33
34 static void sig_module_error(void *number, const char *data,
35                              const char *rootmodule, const char *submodule)
36 {
37         switch (GPOINTER_TO_INT(number)) {
38         case MODULE_ERROR_ALREADY_LOADED:
39                 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
40                             TXT_MODULE_ALREADY_LOADED, rootmodule, submodule);
41                 break;
42         case MODULE_ERROR_LOAD:
43                 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
44                             TXT_MODULE_LOAD_ERROR, rootmodule, submodule, data);
45                 break;
46         case MODULE_ERROR_INVALID:
47                 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
48                             TXT_MODULE_INVALID, rootmodule, submodule);
49                 break;
50         }
51 }
52
53 static void sig_module_loaded(MODULE_REC *module, MODULE_FILE_REC *file)
54 {
55         printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
56                     TXT_MODULE_LOADED, module->name, file->name);
57 }
58
59 static void sig_module_unloaded(MODULE_REC *module, MODULE_FILE_REC *file)
60 {
61         if (file != NULL && file->gmodule != NULL) {
62                 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
63                             TXT_MODULE_UNLOADED, module->name, file->name);
64         }
65 }
66
67 static int module_list_sub(MODULE_REC *module, int mark_type,
68                            GString *submodules)
69 {
70         GSList *tmp;
71         int all_dynamic, dynamic;
72
73         g_string_truncate(submodules, 0);
74
75         all_dynamic = -1;
76         for (tmp = module->files; tmp != NULL; tmp = tmp->next) {
77                 MODULE_FILE_REC *file = tmp->data;
78
79                 /* if there's dynamic and static modules mixed, we'll need
80                    to specify them separately */
81                 if (!mark_type) {
82                         dynamic = file->gmodule != NULL;
83                         if (all_dynamic != -1 && all_dynamic != dynamic) {
84                                 return module_list_sub(module, TRUE,
85                                                        submodules);
86                         }
87                         all_dynamic = dynamic;
88                 }
89
90                 if (submodules->len > 0)
91                         g_string_append_c(submodules, ' ');
92                 g_string_append(submodules, file->name);
93                 if (mark_type) {
94                         g_string_append(submodules, file->gmodule == NULL ?
95                                         " (static)" : " (dynamic)");
96                 }
97         }
98
99         return all_dynamic;
100 }
101
102 static void cmd_load_list(void)
103 {
104         GSList *tmp;
105         GString *submodules;
106         const char *type;
107         int dynamic;
108
109         submodules = g_string_new(NULL);
110
111         printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_MODULE_HEADER);
112         for (tmp = modules; tmp != NULL; tmp = tmp->next) {
113                 MODULE_REC *rec = tmp->data;
114
115                 dynamic = module_list_sub(rec, FALSE, submodules);
116                 type = dynamic == -1 ? "mixed" :
117                         dynamic ? "dynamic" : "static";
118
119                 printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
120                             TXT_MODULE_LINE, rec->name, type, submodules->str);
121         }
122         printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_MODULE_FOOTER);
123
124         g_string_free(submodules, TRUE);
125 }
126
127 static char **module_prefixes_get(void)
128 {
129         GSList *tmp;
130         char **list, *name;
131         int count;
132
133         list = g_new(char *, 2 + 2*g_slist_length(chat_protocols));
134         list[0] = "fe";
135
136         count = 1;
137         for (tmp = chat_protocols; tmp != NULL; tmp = tmp->next) {
138                 CHAT_PROTOCOL_REC *rec = tmp->data;
139
140                 name = g_strdup(rec->name);
141                 g_strdown(name);
142
143                 list[count++] = name;
144                 list[count++] = g_strconcat("fe_", name, NULL);
145         }
146         list[count] = NULL;
147
148         return list;
149 }
150
151 static void module_prefixes_free(char **list)
152 {
153         char **pos = list+1;
154
155         while (*pos != NULL) {
156                 g_free(*pos);
157                 pos++;
158         }
159         g_free(list);
160 }
161
162 /* SYNTAX: LOAD <module> [<submodule>] */
163 static void cmd_load(const char *data)
164 {
165         char *rootmodule, *submodule;
166         char **module_prefixes;
167         void *free_arg;
168
169         g_return_if_fail(data != NULL);
170
171         if (!cmd_get_params(data, &free_arg, 2 , &rootmodule, &submodule))
172                 return;
173
174         if (*rootmodule == '\0')
175                 cmd_load_list();
176         else {
177                 module_prefixes = module_prefixes_get();
178                 if (*submodule == '\0')
179                         module_load(rootmodule, module_prefixes);
180                 else {
181                         module_load_sub(rootmodule, submodule,
182                                         module_prefixes);
183                 }
184                 module_prefixes_free(module_prefixes);
185         }
186
187         cmd_params_free(free_arg);
188 }
189
190 /* SYNTAX: UNLOAD <module> [<submodule>] */
191 static void cmd_unload(const char *data)
192 {
193         MODULE_REC *module;
194         MODULE_FILE_REC *file;
195         char *rootmodule, *submodule;
196         void *free_arg;
197
198         g_return_if_fail(data != NULL);
199
200         if (!cmd_get_params(data, &free_arg, 2 , &rootmodule, &submodule))
201                 return;
202         if (*rootmodule == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
203
204         module = module_find(rootmodule);
205         if (module != NULL) {
206                 if (*submodule == '\0')
207                         module_unload(module);
208                 else {
209                         file = module_file_find(module, submodule);
210                         if (file != NULL)
211                                 module_file_unload(file);
212                         else
213                                 module = NULL;
214                 }
215         }
216
217         if (module == NULL) {
218                 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
219                             TXT_MODULE_NOT_LOADED, rootmodule, submodule);
220         }
221
222         cmd_params_free(free_arg);
223 }
224
225 void fe_modules_init(void)
226 {
227         signal_add("module error", (SIGNAL_FUNC) sig_module_error);
228         signal_add("module loaded", (SIGNAL_FUNC) sig_module_loaded);
229         signal_add("module unloaded", (SIGNAL_FUNC) sig_module_unloaded);
230
231         command_bind("load", NULL, (SIGNAL_FUNC) cmd_load);
232         command_bind("unload", NULL, (SIGNAL_FUNC) cmd_unload);
233 }
234
235 void fe_modules_deinit(void)
236 {
237         signal_remove("module error", (SIGNAL_FUNC) sig_module_error);
238         signal_remove("module loaded", (SIGNAL_FUNC) sig_module_loaded);
239         signal_remove("module unloaded", (SIGNAL_FUNC) sig_module_unloaded);
240
241         command_unbind("load", (SIGNAL_FUNC) cmd_load);
242         command_unbind("unload", (SIGNAL_FUNC) cmd_unload);
243 }
244
245 #else /* !HAVE_GMODULE */
246
247 static void cmd_load(const char *data)
248 {
249         printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
250                   "Dynamic modules loading not supported");
251 }
252
253 void fe_modules_init(void)
254 {
255         command_bind("load", NULL, (SIGNAL_FUNC) cmd_load);
256 }
257
258 void fe_modules_deinit(void)
259 {
260         command_unbind("load", (SIGNAL_FUNC) cmd_load);
261 }
262 #endif