Added SILC Thread Queue API
[crypto.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 + 3*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                 list[count++] = g_strconcat("fe_common_", name, NULL);
146         }
147         list[count] = NULL;
148
149         return list;
150 }
151
152 static void module_prefixes_free(char **list)
153 {
154         char **pos = list+1;
155
156         while (*pos != NULL) {
157                 g_free(*pos);
158                 pos++;
159         }
160         g_free(list);
161 }
162
163 /* SYNTAX: LOAD <module> [<submodule>] */
164 static void cmd_load(const char *data)
165 {
166         char *rootmodule, *submodule;
167         char **module_prefixes;
168         void *free_arg;
169
170         g_return_if_fail(data != NULL);
171
172         if (!cmd_get_params(data, &free_arg, 2 , &rootmodule, &submodule))
173                 return;
174
175         if (*rootmodule == '\0')
176                 cmd_load_list();
177         else {
178                 module_prefixes = module_prefixes_get();
179                 if (*submodule == '\0')
180                         module_load(rootmodule, module_prefixes);
181                 else {
182                         module_load_sub(rootmodule, submodule,
183                                         module_prefixes);
184                 }
185                 module_prefixes_free(module_prefixes);
186         }
187
188         cmd_params_free(free_arg);
189 }
190
191 /* SYNTAX: UNLOAD <module> [<submodule>] */
192 static void cmd_unload(const char *data)
193 {
194         MODULE_REC *module;
195         MODULE_FILE_REC *file;
196         char *rootmodule, *submodule;
197         void *free_arg;
198
199         g_return_if_fail(data != NULL);
200
201         if (!cmd_get_params(data, &free_arg, 2 , &rootmodule, &submodule))
202                 return;
203         if (*rootmodule == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
204
205         module = module_find(rootmodule);
206         if (module != NULL) {
207                 if (*submodule == '\0')
208                         module_unload(module);
209                 else {
210                         file = module_file_find(module, submodule);
211                         if (file != NULL)
212                                 module_file_unload(file);
213                         else
214                                 module = NULL;
215                 }
216         }
217
218         if (module == NULL) {
219                 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
220                             TXT_MODULE_NOT_LOADED, rootmodule, submodule);
221         }
222
223         cmd_params_free(free_arg);
224 }
225
226 void fe_modules_init(void)
227 {
228         signal_add("module error", (SIGNAL_FUNC) sig_module_error);
229         signal_add("module loaded", (SIGNAL_FUNC) sig_module_loaded);
230         signal_add("module unloaded", (SIGNAL_FUNC) sig_module_unloaded);
231
232         command_bind("load", NULL, (SIGNAL_FUNC) cmd_load);
233         command_bind("unload", NULL, (SIGNAL_FUNC) cmd_unload);
234 }
235
236 void fe_modules_deinit(void)
237 {
238         signal_remove("module error", (SIGNAL_FUNC) sig_module_error);
239         signal_remove("module loaded", (SIGNAL_FUNC) sig_module_loaded);
240         signal_remove("module unloaded", (SIGNAL_FUNC) sig_module_unloaded);
241
242         command_unbind("load", (SIGNAL_FUNC) cmd_load);
243         command_unbind("unload", (SIGNAL_FUNC) cmd_unload);
244 }
245
246 #else /* !HAVE_GMODULE */
247
248 static void cmd_load(const char *data)
249 {
250         printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
251                   "Dynamic modules loading not supported");
252 }
253
254 void fe_modules_init(void)
255 {
256         command_bind("load", NULL, (SIGNAL_FUNC) cmd_load);
257 }
258
259 void fe_modules_deinit(void)
260 {
261         command_unbind("load", (SIGNAL_FUNC) cmd_load);
262 }
263 #endif