1 /* modules.c - NeonServ v5.3
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 /* 000-011 */ #include "main.h"
20 /* 012 */ #include "BanNode.h"
21 /* 013-019 */ #include "bots.h"
22 /* 020-025 */ #include "ChanNode.h"
23 /* 026-029 */ #include "ChanUser.h"
24 /* 030-036 */ #include "ClientSocket.h"
25 /* 037-038 */ #include "ConfigParser.h"
26 /* 039-048 */ #include "DBHelper.h"
27 /* 049 */ #include "EventLogger.h"
28 /* 050 */ #include "HandleInfoHandler.h"
29 /* 051-088 */ #include "IRCEvents.h"
30 /* 089-091 */ #include "IRCParser.h"
31 /* 092-098 */ #include "lang.h"
32 #ifdef ENABLE_MEMORY_DEBUG
33 /* 099-102 */ #include "memoryDebug.h"
35 /* 103-106 */ #include "memoryInfo.h"
36 /* 107-125 */ #include "modcmd.h"
37 /* 126-136 */ #include "ModeNode.h"
38 /* 137-142 */ #include "mysqlConn.h"
39 /* 143-149 */ #include "timeq.h"
40 /* 150-169 */ #include "tools.h"
41 /* 170-178 */ #include "UserNode.h"
42 /* 179 */ #include "version.h"
43 /* 180-182 */ #include "WHOHandler.h"
45 void **global_functions = {
46 /* 000 */ getStartTime,
47 /* 001 */ getRunningThreads,
48 /* 002 */ exit_daemon,
51 /* 005 */ restart_process,
53 /* 007 */ restart_bot,
55 /* 009 */ reload_config,
58 /* 011 */ getCurrentThreadID,
62 /* 012 */ getMatchingChannelBan,
63 /* 013 */ getChannelBot,
65 /* 015 */ channel_ban_timeout,
66 /* 016 */ general_event_privctcp,
67 /* 017 */ set_bot_alias,
68 /* 018 */ resolve_botid,
69 /* 019 */ resolve_botalias,
70 /* 020 */ is_valid_chan,
71 /* 021 */ getAllChans,
72 /* 022 */ getChanByName,
73 /* 023 */ getChannelCount,
74 /* 024 */ getChanUserCount,
75 /* 025 */ getChanBanCount,
76 /* 026 */ isUserOnChan,
77 /* 027 */ getChanUser,
78 /* 028 */ getChannelUsers,
79 /* 029 */ getUserChannels,
80 /* 030 */ create_socket,
81 /* 031 */ connect_socket,
82 /* 032 */ close_socket,
83 /* 033 */ disconnect_socket,
84 /* 034 */ write_socket,
87 /* 037 */ get_int_field,
88 /* 038 */ get_string_field,
89 /* 039 */ _loadUserSettings,
91 /* 041 */ getChanDefault,
92 /* 042 */ getChannelAccess,
93 /* 043 */ checkChannelAccess,
94 /* 044 */ _loadChannelSettings,
95 /* 045 */ isUserProtected,
96 /* 046 */ getBanAffectingMask,
97 /* 047 */ renameAccount,
100 /* 050 */ lookup_authname,
102 /* 052 */ unbind_join,
104 /* 054 */ unbind_nick,
106 /* 056 */ unbind_part,
108 /* 058 */ unbind_quit,
110 /* 060 */ unbind_kick,
111 /* 061 */ bind_topic,
112 /* 062 */ unbind_topic,
114 /* 064 */ unbind_mode,
115 /* 065 */ bind_chanmsg,
116 /* 066 */ unbind_chanmsg,
117 /* 067 */ bind_privmsg,
118 /* 068 */ unbind_privmsg,
119 /* 069 */ bind_channotice,
120 /* 070 */ unbind_channotice,
121 /* 071 */ bind_privnotice,
122 /* 072 */ unbind_privnotice,
123 /* 073 */ bind_chanctcp,
124 /* 074 */ unbind_chanctcp,
125 /* 075 */ bind_privctcp,
126 /* 076 */ unbind_privctcp,
127 /* 077 */ bind_invite,
128 /* 078 */ unbind_invite,
130 /* 080 */ unbind_raw,
131 /* 081 */ bind_bot_ready,
132 /* 082 */ unbind_bot_ready,
133 /* 083 */ bind_registered,
134 /* 084 */ unbind_registered,
135 /* 085 */ bind_freeuser,
136 /* 086 */ unbind_freeuser,
137 /* 087 */ bind_freechan,
138 /* 088 */ unbind_freechan,
140 /* 090 */ merge_argv,
141 /* 091 */ merge_argv_char,
142 /* 092 */ get_language_by_tag,
143 /* 093 */ get_language_by_name,
144 /* 094 */ get_default_language,
145 /* 095 */ load_language,
146 /* 096 */ register_default_language_table,
147 /* 097 */ get_language_string,
148 /* 098 */ build_language_string,
149 #ifdef ENABLE_MEMORY_DEBUG
160 /* 103 */ getMemoryInfoFiles,
161 /* 104 */ freeMemoryInfoFiles,
162 /* 105 */ getMemoryInfoLines,
163 /* 106 */ freeMemoryInfoLines,
164 /* 107 */ get_botwise_prefered_bot,
165 /* 108 */ register_command,
166 /* 109 */ set_trigger_callback,
167 /* 110 */ flush_trigger_cache,
168 /* 111 */ changeBotwiseChannelTrigger,
169 /* 112 */ bind_botwise_cmd_to_function,
170 /* 113 */ bind_botwise_cmd_to_command,
171 /* 114 */ unbind_botwise_cmd,
172 /* 115 */ unbind_botwise_allcmd,
173 /* 116 */ bind_botwise_set_parameters,
174 /* 117 */ bind_botwise_set_global_access,
175 /* 118 */ bind_botwise_set_channel_access,
176 /* 119 */ bind_botwise_set_bind_flags,
177 /* 120 */ find_botwise_cmd_binding,
178 /* 121 */ bind_botwise_unbound_required_functions,
179 /* 122 */ find_cmd_function,
180 /* 123 */ getTextBot,
181 /* 124 */ register_command_alias,
182 /* 125 */ getAllBinds,
183 /* 126 */ createModeNode,
184 /* 127 */ freeModeNode,
186 /* 129 */ isModeAffected,
187 /* 130 */ getModeValue,
188 /* 131 */ getModeType,
189 /* 132 */ parseModes,
190 /* 133 */ parseModeString,
192 /* 135 */ getModeString,
193 /* 136 */ getFullModeString,
195 /* 138 */ mysql_free,
196 /* 139 */ printf_mysql_query,
197 /* 140 */ printf_long_mysql_query,
198 /* 141 */ escape_string,
199 /* 142 */ get_mysql_conn,
201 /* 144 */ timeq_uadd,
202 /* 145 */ timeq_add_name,
203 /* 146 */ timeq_uadd_name,
205 /* 148 */ timeq_del_name,
206 /* 149 */ timeq_name_exists,
208 /* 151 */ table_init,
210 /* 153 */ table_change,
211 /* 154 */ table_change_field,
212 /* 155 */ table_set_bold,
214 /* 157 */ table_free,
217 /* 160 */ initModeBuffer,
218 /* 161 */ modeBufferSet,
219 /* 162 */ flushModeBuffer,
220 /* 163 */ freeModeBuffer,
221 /* 164 */ is_ircmask,
222 /* 165 */ generate_banmask,
223 /* 166 */ make_banmask,
224 /* 167 */ isFakeHost,
225 /* 168 */ mask_match,
227 /* 170 */ is_valid_nick,
228 /* 171 */ getUserByNick,
229 /* 172 */ getUserByMask,
230 /* 173 */ countUsersWithHost,
231 /* 174 */ getAuthFakehost,
232 /* 175 */ searchUserByNick,
233 /* 176 */ getAllUsers,
234 /* 177 */ getUsersWithAuth,
235 /* 178 */ getUserCount,
236 /* 179 */ get_userlist,
237 /* 180 */ _get_userlist_with_invisible,
238 /* 181 */ get_userauth,
239 /* 182 */ &compilation,
242 /* 185 */ &codelines,
243 /* 186 */ &patchlevel
246 #define MODINFO_STATE_STARTED 0x01
260 struct ModuleInfo *next;
263 static int module_id_counter = 1;
264 static struct ModuleInfo *modules = NULL;
266 static void unregister_module_hooks(int module_id);
268 int loadModule(char *name) {
271 sprintf(fname, "%s.so", name);
272 void* module = dlopen(fname, RTLD_LAZY);
274 putlog(LOGLEVEL_ERROR, "Error loading module '%s': %s not found.", name, fname);
277 void* initfunc = dlsym(module, "init_module");
278 void* startfunc = dlsym(module, "start_module");
279 void* loopfunc = dlsym(module, "loop_module");
280 void* stopfunc = dlsym(module, "stop_module");
281 void* modversion = dlsym(module, "modversion");
283 sprintf(fname, "%s.dll", name);
284 HMODULE module = LoadLibrary(fname);
286 putlog(LOGLEVEL_ERROR, "Error loading module '%s': %s not found.", name, fname);
289 FARPROC initfunc = GetProcAddress(module, "init_module");
290 FARPROC startfunc = GetProcAddress(module, "start_module");
291 FARPROC loopfunc = GetProcAddress(module, "loop_module");
292 FARPROC stopfunc = GetProcAddress(module, "stop_module");
293 FARPROC modversion = GetProcAddress(module, "modversion");
295 if(!startfunc || !loopfunc || !stopfunc || !modversion) {
296 putlog(LOGLEVEL_ERROR, "Error loading module '%s': required symbols not found.", name);
299 int version = ((int (*)(void)) modversion)();
300 if(version != MODULE_VERSION) {
301 putlog(LOGLEVEL_ERROR, "Error loading module '%s': version mismatch ('%d' main code, '%d' module)", name, MODULE_VERSION, version);
306 int module_id = module_id_counter++;
307 if((errid = ((int (*)(void **, int)) initfunc)(global_functions, module_id))) {
308 putlog(LOGLEVEL_ERROR, "Error loading module '%s': module reported error (errid: %d)", name, errid);
311 struct ModuleInfo *modinfo = malloc(sizeof(*modinfo));
313 unregister_module_hooks(module_id);
316 modinfo->name = strdup(name);
317 modinfo->module_id = module_id;
318 modinfo->module = module;
319 modinfo->startfunc = startfunc;
320 modinfo->loopfunc = loopfunc;
321 modinfo->stopfunc = stopfunc;
322 modinfo->next = modules;
328 static void closemodule(void *module) {
332 static void closemodule(HMODULE module) {
337 int reload_module(char *name) {
338 struct ModuleInfo *old_modinfo, *old_prev = NULL;
339 for(old_modinfo = modules; old_modinfo; old_modinfo = old_modinfo->next) {
341 old_prev->next = old_modinfo->next;
343 modules = old_modinfo->next;
344 unregister_module_hooks(old_modinfo->module_id);
345 ((void (*)(void)) old_modinfo->stopfunc)(MODSTATE_RELOAD);
346 closemodule(old_modinfo->module);
347 free(old_modinfo->name);
351 old_prev = old_modinfo;
352 if(!loadModule(name)) return 0;
353 struct ModuleInfo *modinfo;
354 for(modinfo = modules; modinfo; modinfo = modinfo->next) {
355 if(!(modinfo->state & MODINFO_STATE_STARTED)) {
356 modinfo->state |= MODINFO_STATE_STARTED;
357 ((void (*)(void)) modinfo->startfunc)(MODSTATE_STARTSTOP);
359 ((void (*)(void)) modinfo->startfunc)(MODSTATE_REBIND);
363 void start_modules() {
364 struct ModuleInfo *modinfo;
365 for(modinfo = modules; modinfo; modinfo = modinfo->next) {
366 if(!(modinfo->state & MODINFO_STATE_STARTED)) {
367 modinfo->state |= MODINFO_STATE_STARTED;
368 ((void (*)(void)) modinfo->startfunc)(MODSTATE_STARTSTOP);
373 void loop_modules() {
374 struct ModuleInfo *modinfo;
375 for(modinfo = modules; modinfo; modinfo = modinfo->next) {
376 ((void (*)(void)) modinfo->loopfunc)();
380 void stop_modules() {
381 struct ModuleInfo *modinfo, *next;
382 for(modinfo = modules; modinfo; modinfo = next) {
383 next = modinfo->next;
384 unregister_module_hooks(modinfo->module_id);
385 ((void (*)(int)) modinfo->stopfunc)(MODSTATE_STARTSTOP);
386 closemodule(modinfo->module);
393 static void unregister_module_hooks(int module_id) {
394 unregister_module_commands(module_id);
395 unregister_module_events(module_id);
396 unregister_module_timers(module_id);
399 int module_loaded(int module_id) {
400 if(!module_id) return 1;
401 struct ModuleInfo *modinfo;
402 for(modinfo = modules; modinfo; modinfo = modinfo->next) {
403 if(modinfo->module_id == module_id)