]> jfr.im git - solanum.git/blame - ircd/modules.c
filter: make the kill reason more honest
[solanum.git] / ircd / modules.c
CommitLineData
212380e3
AC
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * modules.c: A module loader.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
212380e3
AC
23 */
24
25#include "stdinc.h"
212380e3 26#include "modules.h"
4016731b 27#include "logger.h"
212380e3
AC
28#include "ircd.h"
29#include "client.h"
30#include "send.h"
31#include "s_conf.h"
32#include "s_newconf.h"
33#include "numeric.h"
34#include "parse.h"
35#include "ircd_defs.h"
4562c604 36#include "match.h"
15feac53 37#include "s_serv.h"
8e9c6a75 38#include "capability.h"
212380e3 39
f272e7ab
AC
40#include <ltdl.h>
41
9abdcf1c
EM
42#ifndef LT_MODULE_EXT
43# error "Charybdis requires loadable module support."
44#endif
45
e55a9d6a
AC
46rb_dlink_list module_list;
47rb_dlink_list mod_paths;
212380e3
AC
48
49static const char *core_module_table[] = {
431a1a27 50 "m_ban",
212380e3
AC
51 "m_die",
52 "m_error",
53 "m_join",
54 "m_kick",
55 "m_kill",
56 "m_message",
57 "m_mode",
78946542 58 "m_modules",
212380e3
AC
59 "m_nick",
60 "m_part",
61 "m_quit",
62 "m_server",
212380e3
AC
63 "m_squit",
64 NULL
65};
66
81204be8
EM
67#define MOD_WARN_DELTA (90 * 86400) /* time in seconds, 86400 seconds in a day */
68
212380e3 69void
92dad483 70init_modules(void)
212380e3 71{
f272e7ab
AC
72 if(lt_dlinit())
73 {
74 ilog(L_MAIN, "lt_dlinit failed");
c173a8ad 75 exit(EXIT_FAILURE);
f272e7ab
AC
76 }
77
212380e3 78 /* Add the default paths we look in to the module system --nenolod */
4d8cfacd
AC
79 mod_add_path(ircd_paths[IRCD_PATH_MODULES]);
80 mod_add_path(ircd_paths[IRCD_PATH_AUTOLOAD_MODULES]);
212380e3
AC
81}
82
28cc8bb9
EK
83static unsigned int prev_caps;
84
85void
86mod_remember_clicaps(void)
87{
88 prev_caps = capability_index_mask(cli_capindex);
89}
90
91void
92mod_notify_clicaps(void)
93{
94 unsigned int cur_caps = capability_index_mask(cli_capindex);
95 unsigned int del = prev_caps & ~cur_caps;
96 unsigned int new = cur_caps & ~prev_caps;
97
98 if (del)
99 sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :%s",
100 me.name, capability_index_list(cli_capindex, del));
101 if (new)
102 sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * NEW :%s",
103 me.name, capability_index_list(cli_capindex, new));
104}
105
212380e3
AC
106/* mod_find_path()
107 *
108 * input - path
109 * output - none
110 * side effects - returns a module path from path
111 */
26c6ac3d 112static char *
212380e3
AC
113mod_find_path(const char *path)
114{
330fc5c1 115 rb_dlink_node *ptr;
26c6ac3d 116 char *mpath;
212380e3 117
5cefa1d6 118 RB_DLINK_FOREACH(ptr, mod_paths.head)
212380e3
AC
119 {
120 mpath = ptr->data;
121
26c6ac3d 122 if(!strcmp(path, mpath))
212380e3
AC
123 return mpath;
124 }
125
126 return NULL;
127}
128
129/* mod_add_path
130 *
131 * input - path
55abcbb2 132 * ouput -
212380e3
AC
133 * side effects - adds path to list
134 */
135void
136mod_add_path(const char *path)
137{
26c6ac3d 138 char *pathst;
212380e3
AC
139
140 if(mod_find_path(path))
141 return;
142
26c6ac3d 143 pathst = rb_strdup(path);
330fc5c1 144 rb_dlinkAddAlloc(pathst, &mod_paths);
212380e3
AC
145}
146
147/* mod_clear_paths()
148 *
149 * input -
150 * output -
151 * side effects - clear the lists of paths
152 */
153void
154mod_clear_paths(void)
155{
637c4932 156 rb_dlink_node *ptr, *next_ptr;
212380e3 157
637c4932 158 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
212380e3 159 {
637c4932 160 rb_free(ptr->data);
30106156 161 rb_free_rb_dlink_node(ptr);
212380e3
AC
162 }
163
164 mod_paths.head = mod_paths.tail = NULL;
165 mod_paths.length = 0;
166}
167
212380e3
AC
168/* findmodule_byname
169 *
aa483e55
EM
170 * input - module to load
171 * output - index of module on success, -1 on failure
172 * side effects - none
212380e3 173 */
e55a9d6a 174struct module *
212380e3
AC
175findmodule_byname(const char *name)
176{
e55a9d6a 177 rb_dlink_node *ptr;
c9108ea0
AC
178 char name_ext[PATH_MAX + 1];
179
dd92c99b
AC
180 rb_strlcpy(name_ext, name, sizeof name_ext);
181 rb_strlcat(name_ext, LT_MODULE_EXT, sizeof name_ext);
212380e3 182
e55a9d6a 183 RB_DLINK_FOREACH(ptr, module_list.head)
212380e3 184 {
e55a9d6a
AC
185 struct module *mod = ptr->data;
186
187 if(!irccmp(mod->name, name))
188 return mod;
c9108ea0 189
e55a9d6a
AC
190 if(!irccmp(mod->name, name_ext))
191 return mod;
212380e3 192 }
c9108ea0 193
e55a9d6a 194 return NULL;
212380e3
AC
195}
196
197/* load_all_modules()
198 *
199 * input -
200 * output -
201 * side effects -
202 */
203void
aa483e55 204load_all_modules(bool warn)
212380e3
AC
205{
206 DIR *system_module_dir = NULL;
207 struct dirent *ldirent = NULL;
208 char module_fq_name[PATH_MAX + 1];
1db8a313
EM
209 size_t module_ext_len = strlen(LT_MODULE_EXT);
210
4d8cfacd 211 system_module_dir = opendir(ircd_paths[IRCD_PATH_AUTOLOAD_MODULES]);
212380e3
AC
212
213 if(system_module_dir == NULL)
214 {
4d8cfacd 215 ilog(L_MAIN, "Could not load modules from %s: %s", ircd_paths[IRCD_PATH_AUTOLOAD_MODULES], strerror(errno));
212380e3
AC
216 return;
217 }
218
219 while ((ldirent = readdir(system_module_dir)) != NULL)
220 {
66031753 221 size_t len = strlen(ldirent->d_name);
9abdcf1c 222
66031753 223 if(len > module_ext_len &&
f956cb0f 224 rb_strncasecmp(ldirent->d_name + (len - module_ext_len), LT_MODULE_EXT, module_ext_len) == 0)
5203cba5 225 {
66031753
EM
226 (void) snprintf(module_fq_name, sizeof(module_fq_name), "%s%c%s",
227 ircd_paths[IRCD_PATH_AUTOLOAD_MODULES], RB_PATH_SEPARATOR, ldirent->d_name);
aa483e55 228 (void) load_a_module(module_fq_name, warn, MAPI_ORIGIN_CORE, false);
5203cba5 229 }
212380e3
AC
230
231 }
232 (void) closedir(system_module_dir);
233}
234
235/* load_core_modules()
236 *
237 * input -
238 * output -
239 * side effects - core modules are loaded, if any fail, kill ircd
240 */
241void
aa483e55 242load_core_modules(bool warn)
212380e3 243{
d74fa5b5 244 char module_name[PATH_MAX];
212380e3
AC
245 int i;
246
247
248 for (i = 0; core_module_table[i]; i++)
249 {
aa483e55
EM
250 snprintf(module_name, sizeof(module_name), "%s%c%s", ircd_paths[IRCD_PATH_MODULES], RB_PATH_SEPARATOR,
251 core_module_table[i]);
212380e3 252
aa483e55 253 if(load_a_module(module_name, warn, MAPI_ORIGIN_CORE, true) == false)
212380e3
AC
254 {
255 ilog(L_MAIN,
9abdcf1c
EM
256 "Error loading core module %s: terminating ircd",
257 core_module_table[i]);
c173a8ad 258 exit(EXIT_FAILURE);
212380e3
AC
259 }
260 }
261}
262
263/* load_one_module()
264 *
265 * input -
266 * output -
267 * side effects -
268 */
aa483e55
EM
269bool
270load_one_module(const char *path, int origin, bool coremodule)
212380e3 271{
d74fa5b5 272 char modpath[PATH_MAX];
330fc5c1 273 rb_dlink_node *pathst;
212380e3 274
503727d1 275 if (server_state_foreground)
55abcbb2 276 inotice("loading module %s ...", path);
212380e3 277
aa483e55 278 if(coremodule)
216d70e9 279 origin = MAPI_ORIGIN_CORE;
216d70e9 280
5cefa1d6 281 RB_DLINK_FOREACH(pathst, mod_paths.head)
212380e3 282 {
aa483e55
EM
283 struct stat statbuf;
284 const char *mpath = pathst->data;
212380e3 285
aa483e55 286 snprintf(modpath, sizeof(modpath), "%s%c%s%s", mpath, RB_PATH_SEPARATOR, path, LT_MODULE_EXT);
212380e3
AC
287 if((strstr(modpath, "../") == NULL) && (strstr(modpath, "/..") == NULL))
288 {
aa483e55 289 if(stat(modpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
212380e3 290 {
aa483e55
EM
291 /* Regular files only please */
292 return load_a_module(modpath, true, origin, coremodule);
212380e3
AC
293 }
294
295 }
296 }
297
298 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot locate module %s", path);
aa483e55 299 return false;
212380e3
AC
300}
301
212380e3 302static char unknown_ver[] = "<unknown>";
8e9c6a75 303static char unknown_description[] = "<none>";
212380e3 304
212380e3
AC
305/* unload_one_module()
306 *
307 * inputs - name of module to unload
aa483e55
EM
308 * - true to say modules unloaded, false to not
309 * output - true if successful, false if error
212380e3
AC
310 * side effects - module is unloaded
311 */
aa483e55
EM
312bool
313unload_one_module(const char *name, bool warn)
212380e3 314{
e55a9d6a 315 struct module *mod;
212380e3 316
e55a9d6a 317 if((mod = findmodule_byname(name)) == NULL)
aa483e55 318 return false;
b5cfad03 319
212380e3
AC
320 /*
321 ** XXX - The type system in C does not allow direct conversion between
322 ** data and function pointers, but as it happens, most C compilers will
55abcbb2
KB
323 ** safely do this, however it is a theoretical overlow to cast as we
324 ** must do here. I have library functions to take care of this, but
325 ** despite being more "correct" for the C language, this is more
212380e3
AC
326 ** practical. Removing the abuse of the ability to cast ANY pointer
327 ** to and from an integer value here will break some compilers.
328 ** -jmallett
329 */
330 /* Left the comment in but the code isn't here any more -larne */
e55a9d6a 331 switch (mod->mapi_version)
212380e3
AC
332 {
333 case 1:
334 {
e55a9d6a 335 struct mapi_mheader_av1 *mheader = mod->mapi_header;
212380e3
AC
336 if(mheader->mapi_command_list)
337 {
338 struct Message **m;
339 for (m = mheader->mapi_command_list; *m; ++m)
340 mod_del_cmd(*m);
341 }
342
343 /* hook events are never removed, we simply lose the
344 * ability to call them --fl
345 */
346 if(mheader->mapi_hfn_list)
347 {
348 mapi_hfn_list_av1 *m;
349 for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
350 remove_hook(m->hapi_name, m->fn);
351 }
352
353 if(mheader->mapi_unregister)
354 mheader->mapi_unregister();
355 break;
356 }
8e9c6a75
EM
357 case 2:
358 {
e55a9d6a 359 struct mapi_mheader_av2 *mheader = mod->mapi_header;
8e9c6a75
EM
360
361 /* XXX duplicate code :( */
362 if(mheader->mapi_command_list)
363 {
364 struct Message **m;
365 for (m = mheader->mapi_command_list; *m; ++m)
366 mod_del_cmd(*m);
367 }
368
369 /* hook events are never removed, we simply lose the
370 * ability to call them --fl
371 */
372 if(mheader->mapi_hfn_list)
373 {
374 mapi_hfn_list_av1 *m;
375 for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
376 remove_hook(m->hapi_name, m->fn);
377 }
378
379 if(mheader->mapi_unregister)
380 mheader->mapi_unregister();
381
382 if(mheader->mapi_cap_list)
383 {
384 mapi_cap_list_av2 *m;
385 for (m = mheader->mapi_cap_list; m->cap_name; ++m)
386 {
387 struct CapabilityIndex *idx;
388
978b7232 389 switch (m->cap_index)
8e9c6a75
EM
390 {
391 case MAPI_CAP_CLIENT:
392 idx = cli_capindex;
393 break;
394 case MAPI_CAP_SERVER:
395 idx = serv_capindex;
396 break;
397 default:
398 sendto_realops_snomask(SNO_GENERAL, L_ALL,
399 "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s",
e55a9d6a 400 m->cap_index, m->cap_name, mod->name);
8e9c6a75
EM
401 ilog(L_MAIN,
402 "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s",
e55a9d6a 403 m->cap_index, m->cap_name, mod->name);
8e9c6a75
EM
404 continue;
405 }
406
3256156a 407 if (m->cap_id != NULL)
3256156a 408 capability_orphan(idx, m->cap_name);
8e9c6a75
EM
409 }
410 }
e8de2bfa 411 break;
8e9c6a75 412 }
212380e3
AC
413 default:
414 sendto_realops_snomask(SNO_GENERAL, L_ALL,
415 "Unknown/unsupported MAPI version %d when unloading %s!",
e55a9d6a 416 mod->mapi_version, mod->name);
212380e3 417 ilog(L_MAIN, "Unknown/unsupported MAPI version %d when unloading %s!",
e55a9d6a 418 mod->mapi_version, mod->name);
212380e3
AC
419 break;
420 }
421
e55a9d6a 422 lt_dlclose(mod->address);
212380e3 423
e55a9d6a
AC
424 rb_dlinkDelete(&mod->node, &module_list);
425 rb_free(mod->name);
426 rb_free(mod);
212380e3 427
aa483e55 428 if(warn)
212380e3
AC
429 {
430 ilog(L_MAIN, "Module %s unloaded", name);
431 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Module %s unloaded", name);
432 }
433
aa483e55 434 return true;
212380e3
AC
435}
436
212380e3
AC
437/*
438 * load_a_module()
439 *
aa483e55
EM
440 * inputs - path name of module, bool to notice, int of origin, bool if core
441 * output - false if error true if success
212380e3
AC
442 * side effects - loads a module if successful
443 */
aa483e55
EM
444bool
445load_a_module(const char *path, bool warn, int origin, bool core)
212380e3 446{
e55a9d6a 447 struct module *mod;
f272e7ab 448 lt_dlhandle tmpptr;
0a87075b 449 char *mod_displayname, *c;
8e9c6a75 450 const char *ver, *description = NULL;
212380e3
AC
451
452 int *mapi_version;
453
0a87075b
EM
454 mod_displayname = rb_basename(path);
455
456 /* Trim off the ending for the display name if we have to */
457 if((c = rb_strcasestr(mod_displayname, LT_MODULE_EXT)) != NULL)
458 *c = '\0';
212380e3 459
9abdcf1c 460 tmpptr = lt_dlopenext(path);
212380e3
AC
461
462 if(tmpptr == NULL)
463 {
f272e7ab 464 const char *err = lt_dlerror();
212380e3
AC
465
466 sendto_realops_snomask(SNO_GENERAL, L_ALL,
0a87075b
EM
467 "Error loading module %s: %s", mod_displayname, err);
468 ilog(L_MAIN, "Error loading module %s: %s", mod_displayname, err);
469 rb_free(mod_displayname);
aa483e55 470 return false;
212380e3
AC
471 }
472
212380e3
AC
473 /*
474 * _mheader is actually a struct mapi_mheader_*, but mapi_version
475 * is always the first member of this structure, so we treate it
476 * as a single int in order to determine the API version.
477 * -larne.
478 */
f272e7ab 479 mapi_version = (int *) (uintptr_t) lt_dlsym(tmpptr, "_mheader");
212380e3 480 if((mapi_version == NULL
f272e7ab 481 && (mapi_version = (int *) (uintptr_t) lt_dlsym(tmpptr, "__mheader")) == NULL)
212380e3
AC
482 || MAPI_MAGIC(*mapi_version) != MAPI_MAGIC_HDR)
483 {
484 sendto_realops_snomask(SNO_GENERAL, L_ALL,
485 "Data format error: module %s has no MAPI header.",
0a87075b
EM
486 mod_displayname);
487 ilog(L_MAIN, "Data format error: module %s has no MAPI header.", mod_displayname);
f272e7ab 488 (void) lt_dlclose(tmpptr);
0a87075b 489 rb_free(mod_displayname);
aa483e55 490 return false;
212380e3
AC
491 }
492
493 switch (MAPI_VERSION(*mapi_version))
494 {
495 case 1:
496 {
29c92cf9 497 struct mapi_mheader_av1 *mheader = (struct mapi_mheader_av1 *)(void *)mapi_version; /* see above */
212380e3
AC
498 if(mheader->mapi_register && (mheader->mapi_register() == -1))
499 {
500 ilog(L_MAIN, "Module %s indicated failure during load.",
0a87075b 501 mod_displayname);
212380e3
AC
502 sendto_realops_snomask(SNO_GENERAL, L_ALL,
503 "Module %s indicated failure during load.",
0a87075b 504 mod_displayname);
f272e7ab 505 lt_dlclose(tmpptr);
0a87075b 506 rb_free(mod_displayname);
aa483e55 507 return false;
212380e3
AC
508 }
509 if(mheader->mapi_command_list)
510 {
511 struct Message **m;
512 for (m = mheader->mapi_command_list; *m; ++m)
513 mod_add_cmd(*m);
514 }
515
516 if(mheader->mapi_hook_list)
517 {
518 mapi_hlist_av1 *m;
519 for (m = mheader->mapi_hook_list; m->hapi_name; ++m)
520 *m->hapi_id = register_hook(m->hapi_name);
521 }
522
523 if(mheader->mapi_hfn_list)
524 {
525 mapi_hfn_list_av1 *m;
526 for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
527 add_hook(m->hapi_name, m->fn);
528 }
529
530 ver = mheader->mapi_module_version;
531 break;
532 }
8e9c6a75
EM
533 case 2:
534 {
535 struct mapi_mheader_av2 *mheader = (struct mapi_mheader_av2 *)(void *)mapi_version; /* see above */
212380e3 536
8e9c6a75 537 /* XXX duplicated code :( */
5eb3d7a7 538 if(mheader->mapi_register && (mheader->mapi_register() == -1))
8e9c6a75
EM
539 {
540 ilog(L_MAIN, "Module %s indicated failure during load.",
0a87075b 541 mod_displayname);
8e9c6a75
EM
542 sendto_realops_snomask(SNO_GENERAL, L_ALL,
543 "Module %s indicated failure during load.",
0a87075b 544 mod_displayname);
8e9c6a75 545 lt_dlclose(tmpptr);
0a87075b 546 rb_free(mod_displayname);
aa483e55 547 return false;
8e9c6a75 548 }
81204be8
EM
549
550 /* Basic date code checks
551 *
552 * Don't make them fatal, but do complain about differences within a certain time frame.
553 * Later on if there are major API changes we can add fatal checks.
554 * -- Elizafox
555 */
556 if(mheader->mapi_datecode != datecode && mheader->mapi_datecode > 0)
557 {
3089f59c 558 long int delta = datecode - mheader->mapi_datecode;
81204be8
EM
559 if (delta > MOD_WARN_DELTA)
560 {
561 delta /= 86400;
881acf00 562 iwarn("Module %s build date is out of sync with ircd build date by %ld days, expect problems",
0a87075b 563 mod_displayname, delta);
81204be8
EM
564 sendto_realops_snomask(SNO_GENERAL, L_ALL,
565 "Module %s build date is out of sync with ircd build date by %ld days, expect problems",
0a87075b 566 mod_displayname, delta);
81204be8
EM
567 }
568 }
569
8e9c6a75
EM
570 if(mheader->mapi_command_list)
571 {
572 struct Message **m;
573 for (m = mheader->mapi_command_list; *m; ++m)
574 mod_add_cmd(*m);
575 }
576
577 if(mheader->mapi_hook_list)
578 {
579 mapi_hlist_av1 *m;
580 for (m = mheader->mapi_hook_list; m->hapi_name; ++m)
581 *m->hapi_id = register_hook(m->hapi_name);
582 }
583
584 if(mheader->mapi_hfn_list)
585 {
586 mapi_hfn_list_av1 *m;
587 for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
588 add_hook(m->hapi_name, m->fn);
589 }
590
591 /* New in MAPI v2 - version replacement */
592 ver = mheader->mapi_module_version ? mheader->mapi_module_version : ircd_version;
593 description = mheader->mapi_module_description;
594
595 if(mheader->mapi_cap_list)
596 {
597 mapi_cap_list_av2 *m;
598 for (m = mheader->mapi_cap_list; m->cap_name; ++m)
599 {
600 struct CapabilityIndex *idx;
601 int result;
602
978b7232 603 switch (m->cap_index)
8e9c6a75
EM
604 {
605 case MAPI_CAP_CLIENT:
606 idx = cli_capindex;
607 break;
608 case MAPI_CAP_SERVER:
609 idx = serv_capindex;
610 break;
611 default:
612 sendto_realops_snomask(SNO_GENERAL, L_ALL,
613 "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
0a87075b 614 m->cap_index, m->cap_name, mod_displayname);
8e9c6a75
EM
615 ilog(L_MAIN,
616 "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
0a87075b 617 m->cap_index, m->cap_name, mod_displayname);
8e9c6a75
EM
618 continue;
619 }
620
621 result = capability_put(idx, m->cap_name, m->cap_ownerdata);
622 if (m->cap_id != NULL)
623 *(m->cap_id) = result;
624 }
625 }
626 }
0e5bf029
EM
627
628 break;
212380e3
AC
629 default:
630 ilog(L_MAIN, "Module %s has unknown/unsupported MAPI version %d.",
0a87075b 631 mod_displayname, MAPI_VERSION(*mapi_version));
212380e3
AC
632 sendto_realops_snomask(SNO_GENERAL, L_ALL,
633 "Module %s has unknown/unsupported MAPI version %d.",
0a87075b 634 mod_displayname, *mapi_version);
f272e7ab 635 lt_dlclose(tmpptr);
0a87075b 636 rb_free(mod_displayname);
aa483e55 637 return false;
212380e3
AC
638 }
639
640 if(ver == NULL)
641 ver = unknown_ver;
642
8e9c6a75
EM
643 if(description == NULL)
644 description = unknown_description;
645
e55a9d6a
AC
646 mod = rb_malloc(sizeof(struct module));
647 mod->address = tmpptr;
648 mod->version = ver;
649 mod->description = description;
650 mod->core = core;
651 mod->name = rb_strdup(mod_displayname);
652 mod->mapi_header = mapi_version;
653 mod->mapi_version = MAPI_VERSION(*mapi_version);
654 mod->origin = origin;
655 rb_dlinkAdd(mod, &mod->node, &module_list);
212380e3 656
aa483e55 657 if(warn)
212380e3 658 {
c63aeb44
EM
659 const char *o;
660
978b7232 661 switch (origin)
c63aeb44 662 {
c63aeb44
EM
663 case MAPI_ORIGIN_EXTENSION:
664 o = "extension";
665 break;
666 case MAPI_ORIGIN_CORE:
667 o = "core";
668 break;
669 default:
670 o = "unknown";
671 break;
672 }
673
212380e3 674 sendto_realops_snomask(SNO_GENERAL, L_ALL,
02831b6f 675 "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at %p",
0a87075b 676 mod_displayname, ver, MAPI_VERSION(*mapi_version), o, description,
02831b6f
AC
677 (void *) tmpptr);
678 ilog(L_MAIN, "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at %p",
0a87075b 679 mod_displayname, ver, MAPI_VERSION(*mapi_version), o, description, (void *) tmpptr);
212380e3 680 }
0a87075b 681 rb_free(mod_displayname);
aa483e55 682 return true;
212380e3 683}
41390bfe
AJ
684
685void
686modules_do_restart(void *unused)
687{
688 unsigned int modnum = 0;
689 rb_dlink_node *ptr, *nptr;
690
28cc8bb9
EK
691 mod_remember_clicaps();
692
41390bfe
AJ
693 RB_DLINK_FOREACH_SAFE(ptr, nptr, module_list.head)
694 {
695 struct module *mod = ptr->data;
696 if(!unload_one_module(mod->name, false))
697 {
698 ilog(L_MAIN, "Module Restart: %s was not unloaded %s",
699 mod->name,
700 mod->core? "(core module)" : "");
701
702 if(!mod->core)
703 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
704 "Module Restart: %s failed to unload",
705 mod->name);
706 continue;
707 }
708
709 modnum++;
710 }
711
712 load_all_modules(false);
713 load_core_modules(false);
714 rehash(false);
715
28cc8bb9
EK
716 mod_notify_clicaps();
717
41390bfe
AJ
718 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
719 "Module Restart: %u modules unloaded, %lu modules loaded",
720 modnum, rb_dlink_list_length(&module_list));
721 ilog(L_MAIN, "Module Restart: %u modules unloaded, %lu modules loaded", modnum, rb_dlink_list_length(&module_list));
722}