2 * ircd-ratbox: A slightly useful ircd.
3 * modules.c: A module loader.
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
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.
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.
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
32 #include "s_newconf.h"
35 #include "ircd_defs.h"
38 #include "capability.h"
43 # error "Charybdis requires loadable module support."
46 struct module **modlist
= NULL
;
48 static const char *core_module_table
[] = {
65 #define MOD_WARN_DELTA (90 * 86400) /* time in seconds, 86400 seconds in a day */
67 #define MODS_INCREMENT 10
69 int max_mods
= MODS_INCREMENT
;
71 static rb_dlink_list mod_paths
;
73 static void mo_modload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
74 static void mo_modlist(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
75 static void mo_modreload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
76 static void mo_modunload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
77 static void mo_modrestart(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
79 static void me_modload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
80 static void me_modlist(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
81 static void me_modreload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
82 static void me_modunload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
83 static void me_modrestart(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
85 static void do_modload(struct Client
*, const char *);
86 static void do_modunload(struct Client
*, const char *);
87 static void do_modreload(struct Client
*, const char *);
88 static void do_modlist(struct Client
*, const char *);
89 static void do_modrestart(struct Client
*);
91 struct Message modload_msgtab
= {
92 "MODLOAD", 0, 0, 0, 0,
93 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modload
, 2}, {mo_modload
, 2}}
96 struct Message modunload_msgtab
= {
97 "MODUNLOAD", 0, 0, 0, 0,
98 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modunload
, 2}, {mo_modunload
, 2}}
101 struct Message modreload_msgtab
= {
102 "MODRELOAD", 0, 0, 0, 0,
103 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modreload
, 2}, {mo_modreload
, 2}}
106 struct Message modlist_msgtab
= {
107 "MODLIST", 0, 0, 0, 0,
108 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modlist
, 0}, {mo_modlist
, 0}}
111 struct Message modrestart_msgtab
= {
112 "MODRESTART", 0, 0, 0, 0,
113 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modrestart
, 0}, {mo_modrestart
, 0}}
121 ilog(L_MAIN
, "lt_dlinit failed");
125 mod_add_cmd(&modload_msgtab
);
126 mod_add_cmd(&modunload_msgtab
);
127 mod_add_cmd(&modreload_msgtab
);
128 mod_add_cmd(&modlist_msgtab
);
129 mod_add_cmd(&modrestart_msgtab
);
131 /* Add the default paths we look in to the module system --nenolod */
132 mod_add_path(ircd_paths
[IRCD_PATH_MODULES
]);
133 mod_add_path(ircd_paths
[IRCD_PATH_AUTOLOAD_MODULES
]);
140 * side effects - returns a module path from path
143 mod_find_path(const char *path
)
148 RB_DLINK_FOREACH(ptr
, mod_paths
.head
)
152 if(!strcmp(path
, mpath
))
163 * side effects - adds path to list
166 mod_add_path(const char *path
)
170 if(mod_find_path(path
))
173 pathst
= rb_strdup(path
);
174 rb_dlinkAddAlloc(pathst
, &mod_paths
);
181 * side effects - clear the lists of paths
184 mod_clear_paths(void)
186 rb_dlink_node
*ptr
, *next_ptr
;
188 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, mod_paths
.head
)
191 rb_free_rb_dlink_node(ptr
);
194 mod_paths
.head
= mod_paths
.tail
= NULL
;
195 mod_paths
.length
= 0;
200 * input - module to load
201 * output - index of module on success, -1 on failure
202 * side effects - none
205 findmodule_byname(const char *name
)
208 char name_ext
[PATH_MAX
+ 1];
210 rb_strlcpy(name_ext
, name
, sizeof name_ext
);
211 rb_strlcat(name_ext
, LT_MODULE_EXT
, sizeof name_ext
);
213 for (i
= 0; i
< num_mods
; i
++)
215 if(!irccmp(modlist
[i
]->name
, name
))
218 if(!irccmp(modlist
[i
]->name
, name_ext
))
225 /* load_all_modules()
232 load_all_modules(bool warn
)
234 DIR *system_module_dir
= NULL
;
235 struct dirent
*ldirent
= NULL
;
236 char module_fq_name
[PATH_MAX
+ 1];
237 size_t module_ext_len
= strlen(LT_MODULE_EXT
);
241 modlist
= (struct module **) rb_malloc(sizeof(struct module *) * (MODS_INCREMENT
));
243 max_mods
= MODS_INCREMENT
;
245 system_module_dir
= opendir(ircd_paths
[IRCD_PATH_AUTOLOAD_MODULES
]);
247 if(system_module_dir
== NULL
)
249 ilog(L_MAIN
, "Could not load modules from %s: %s", ircd_paths
[IRCD_PATH_AUTOLOAD_MODULES
], strerror(errno
));
253 while ((ldirent
= readdir(system_module_dir
)) != NULL
)
255 size_t len
= strlen(ldirent
->d_name
);
257 if(len
> module_ext_len
&&
258 strncasecmp(ldirent
->d_name
+ (len
- module_ext_len
), LT_MODULE_EXT
, module_ext_len
) == 0)
260 (void) snprintf(module_fq_name
, sizeof(module_fq_name
), "%s%c%s",
261 ircd_paths
[IRCD_PATH_AUTOLOAD_MODULES
], RB_PATH_SEPARATOR
, ldirent
->d_name
);
262 (void) load_a_module(module_fq_name
, warn
, MAPI_ORIGIN_CORE
, false);
266 (void) closedir(system_module_dir
);
269 /* load_core_modules()
273 * side effects - core modules are loaded, if any fail, kill ircd
276 load_core_modules(bool warn
)
278 char module_name
[PATH_MAX
];
282 for (i
= 0; core_module_table
[i
]; i
++)
284 snprintf(module_name
, sizeof(module_name
), "%s%c%s", ircd_paths
[IRCD_PATH_MODULES
], RB_PATH_SEPARATOR
,
285 core_module_table
[i
]);
287 if(load_a_module(module_name
, warn
, MAPI_ORIGIN_CORE
, true) == false)
290 "Error loading core module %s: terminating ircd",
291 core_module_table
[i
]);
304 load_one_module(const char *path
, int origin
, bool coremodule
)
306 char modpath
[PATH_MAX
];
307 rb_dlink_node
*pathst
;
309 if (server_state_foreground
)
310 inotice("loading module %s ...", path
);
313 origin
= MAPI_ORIGIN_CORE
;
315 RB_DLINK_FOREACH(pathst
, mod_paths
.head
)
318 const char *mpath
= pathst
->data
;
320 snprintf(modpath
, sizeof(modpath
), "%s%c%s%s", mpath
, RB_PATH_SEPARATOR
, path
, LT_MODULE_EXT
);
321 if((strstr(modpath
, "../") == NULL
) && (strstr(modpath
, "/..") == NULL
))
323 if(stat(modpath
, &statbuf
) == 0 && S_ISREG(statbuf
.st_mode
))
325 /* Regular files only please */
326 return load_a_module(modpath
, true, origin
, coremodule
);
332 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Cannot locate module %s", path
);
337 /* load a module .. */
339 mo_modload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
341 if(!IsOperAdmin(source_p
))
343 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
344 me
.name
, source_p
->name
, "admin");
350 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
351 "ENCAP %s MODLOAD %s", parv
[2], parv
[1]);
352 if(match(parv
[2], me
.name
) == 0)
356 do_modload(source_p
, parv
[1]);
360 me_modload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
362 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
364 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
365 "to load modules on this server.");
369 do_modload(source_p
, parv
[1]);
373 /* unload a module .. */
375 mo_modunload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
377 if(!IsOperAdmin(source_p
))
379 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
380 me
.name
, source_p
->name
, "admin");
386 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
387 "ENCAP %s MODUNLOAD %s", parv
[2], parv
[1]);
388 if(match(parv
[2], me
.name
) == 0)
392 do_modunload(source_p
, parv
[1]);
396 me_modunload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
398 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
400 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
401 "to load modules on this server.");
405 do_modunload(source_p
, parv
[1]);
408 /* unload and load in one! */
410 mo_modreload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
412 if(!IsOperAdmin(source_p
))
414 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
415 me
.name
, source_p
->name
, "admin");
421 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
422 "ENCAP %s MODRELOAD %s", parv
[2], parv
[1]);
423 if(match(parv
[2], me
.name
) == 0)
427 do_modreload(source_p
, parv
[1]);
431 me_modreload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
433 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
435 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
436 "to load modules on this server.");
440 do_modreload(source_p
, parv
[1]);
443 /* list modules .. */
445 mo_modlist(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
447 if(!IsOperAdmin(source_p
))
449 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
450 me
.name
, source_p
->name
, "admin");
456 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
457 "ENCAP %s MODLIST %s", parv
[2], parv
[1]);
458 if(match(parv
[2], me
.name
) == 0)
462 do_modlist(source_p
, parc
> 1 ? parv
[1] : 0);
466 me_modlist(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
468 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
470 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
471 "to load modules on this server.");
475 do_modlist(source_p
, parv
[1]);
478 /* unload and reload all modules */
480 mo_modrestart(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
482 if(!IsOperAdmin(source_p
))
484 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
485 me
.name
, source_p
->name
, "admin");
491 sendto_match_servs(source_p
, parv
[1], CAP_ENCAP
, NOCAPS
,
492 "ENCAP %s MODRESTART", parv
[1]);
493 if(match(parv
[1], me
.name
) == 0)
497 do_modrestart(source_p
);
501 me_modrestart(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
503 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
505 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
506 "to load modules on this server.");
510 do_modrestart(source_p
);
514 do_modload(struct Client
*source_p
, const char *module)
516 char *m_bn
= rb_basename(module);
519 if(findmodule_byname(m_bn
) != -1)
521 sendto_one_notice(source_p
, ":Module %s is already loaded", m_bn
);
526 origin
= strcmp(module, m_bn
) == 0 ? MAPI_ORIGIN_CORE
: MAPI_ORIGIN_EXTENSION
;
527 load_one_module(module, origin
, false);
533 do_modunload(struct Client
*source_p
, const char *module)
536 char *m_bn
= rb_basename(module);
538 if((modindex
= findmodule_byname(m_bn
)) == -1)
540 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
545 if(modlist
[modindex
]->core
)
547 sendto_one_notice(source_p
, ":Module %s is a core module and may not be unloaded", m_bn
);
552 if(unload_one_module(m_bn
, true) == false)
553 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
559 do_modreload(struct Client
*source_p
, const char *module)
563 char *m_bn
= rb_basename(module);
565 if((modindex
= findmodule_byname(m_bn
)) == -1)
567 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
572 check_core
= modlist
[modindex
]->core
;
574 if(unload_one_module(m_bn
, true) == false)
576 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
581 if((load_one_module(m_bn
, modlist
[modindex
]->origin
, check_core
) == false) && check_core
)
583 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
584 "Error reloading core module: %s: terminating ircd", m_bn
);
585 ilog(L_MAIN
, "Error loading core module %s: terminating ircd", m_bn
);
593 do_modrestart(struct Client
*source_p
)
597 sendto_one_notice(source_p
, ":Reloading all modules");
601 unload_one_module(modlist
[0]->name
, false);
603 load_all_modules(false);
604 load_core_modules(false);
607 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
608 "Module Restart: %d modules unloaded, %d modules loaded",
610 ilog(L_MAIN
, "Module Restart: %d modules unloaded, %d modules loaded", modnum
, num_mods
);
614 do_modlist(struct Client
*source_p
, const char *pattern
)
618 for (i
= 0; i
< num_mods
; i
++)
621 switch (modlist
[i
]->origin
)
623 case MAPI_ORIGIN_EXTENSION
:
624 origin
= "extension";
626 case MAPI_ORIGIN_CORE
:
636 if(match(pattern
, modlist
[i
]->name
))
638 sendto_one(source_p
, form_str(RPL_MODLIST
),
639 me
.name
, source_p
->name
,
641 (unsigned long)(uintptr_t)modlist
[i
]->address
, origin
,
642 modlist
[i
]->core
? " (core)" : "", modlist
[i
]->version
, modlist
[i
]->description
);
647 sendto_one(source_p
, form_str(RPL_MODLIST
),
648 me
.name
, source_p
->name
, modlist
[i
]->name
,
649 (unsigned long)(uintptr_t)modlist
[i
]->address
, origin
,
650 modlist
[i
]->core
? " (core)" : "", modlist
[i
]->version
, modlist
[i
]->description
);
654 sendto_one(source_p
, form_str(RPL_ENDOFMODLIST
), me
.name
, source_p
->name
);
657 static void increase_modlist(void);
659 #define MODS_INCREMENT 10
661 static char unknown_ver
[] = "<unknown>";
662 static char unknown_description
[] = "<none>";
664 /* unload_one_module()
666 * inputs - name of module to unload
667 * - true to say modules unloaded, false to not
668 * output - true if successful, false if error
669 * side effects - module is unloaded
672 unload_one_module(const char *name
, bool warn
)
676 if((modindex
= findmodule_byname(name
)) == -1)
680 ** XXX - The type system in C does not allow direct conversion between
681 ** data and function pointers, but as it happens, most C compilers will
682 ** safely do this, however it is a theoretical overlow to cast as we
683 ** must do here. I have library functions to take care of this, but
684 ** despite being more "correct" for the C language, this is more
685 ** practical. Removing the abuse of the ability to cast ANY pointer
686 ** to and from an integer value here will break some compilers.
689 /* Left the comment in but the code isn't here any more -larne */
690 switch (modlist
[modindex
]->mapi_version
)
694 struct mapi_mheader_av1
*mheader
= modlist
[modindex
]->mapi_header
;
695 if(mheader
->mapi_command_list
)
698 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
702 /* hook events are never removed, we simply lose the
703 * ability to call them --fl
705 if(mheader
->mapi_hfn_list
)
707 mapi_hfn_list_av1
*m
;
708 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
709 remove_hook(m
->hapi_name
, m
->fn
);
712 if(mheader
->mapi_unregister
)
713 mheader
->mapi_unregister();
718 struct mapi_mheader_av2
*mheader
= modlist
[modindex
]->mapi_header
;
720 /* XXX duplicate code :( */
721 if(mheader
->mapi_command_list
)
724 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
728 /* hook events are never removed, we simply lose the
729 * ability to call them --fl
731 if(mheader
->mapi_hfn_list
)
733 mapi_hfn_list_av1
*m
;
734 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
735 remove_hook(m
->hapi_name
, m
->fn
);
738 if(mheader
->mapi_unregister
)
739 mheader
->mapi_unregister();
741 if(mheader
->mapi_cap_list
)
743 mapi_cap_list_av2
*m
;
744 for (m
= mheader
->mapi_cap_list
; m
->cap_name
; ++m
)
746 struct CapabilityIndex
*idx
;
748 switch (m
->cap_index
)
750 case MAPI_CAP_CLIENT
:
753 case MAPI_CAP_SERVER
:
757 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
758 "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s",
759 m
->cap_index
, m
->cap_name
, modlist
[modindex
]->name
);
761 "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s",
762 m
->cap_index
, m
->cap_name
, modlist
[modindex
]->name
);
766 if (m
->cap_id
!= NULL
)
768 capability_orphan(idx
, m
->cap_name
);
769 sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY
, ":%s CAP * DEL :%s", me
.name
, m
->cap_name
);
775 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
776 "Unknown/unsupported MAPI version %d when unloading %s!",
777 modlist
[modindex
]->mapi_version
, modlist
[modindex
]->name
);
778 ilog(L_MAIN
, "Unknown/unsupported MAPI version %d when unloading %s!",
779 modlist
[modindex
]->mapi_version
, modlist
[modindex
]->name
);
783 lt_dlclose(modlist
[modindex
]->address
);
785 rb_free(modlist
[modindex
]->name
);
786 rb_free(modlist
[modindex
]);
787 memmove(&modlist
[modindex
], &modlist
[modindex
+ 1],
788 sizeof(struct module *) * ((num_mods
- 1) - modindex
));
795 ilog(L_MAIN
, "Module %s unloaded", name
);
796 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Module %s unloaded", name
);
805 * inputs - path name of module, bool to notice, int of origin, bool if core
806 * output - false if error true if success
807 * side effects - loads a module if successful
810 load_a_module(const char *path
, bool warn
, int origin
, bool core
)
814 const char *ver
, *description
= NULL
;
818 mod_basename
= rb_basename(path
);
820 tmpptr
= lt_dlopenext(path
);
824 const char *err
= lt_dlerror();
826 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
827 "Error loading module %s: %s", mod_basename
, err
);
828 ilog(L_MAIN
, "Error loading module %s: %s", mod_basename
, err
);
829 rb_free(mod_basename
);
834 * _mheader is actually a struct mapi_mheader_*, but mapi_version
835 * is always the first member of this structure, so we treate it
836 * as a single int in order to determine the API version.
839 mapi_version
= (int *) (uintptr_t) lt_dlsym(tmpptr
, "_mheader");
840 if((mapi_version
== NULL
841 && (mapi_version
= (int *) (uintptr_t) lt_dlsym(tmpptr
, "__mheader")) == NULL
)
842 || MAPI_MAGIC(*mapi_version
) != MAPI_MAGIC_HDR
)
844 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
845 "Data format error: module %s has no MAPI header.",
847 ilog(L_MAIN
, "Data format error: module %s has no MAPI header.", mod_basename
);
848 (void) lt_dlclose(tmpptr
);
849 rb_free(mod_basename
);
853 switch (MAPI_VERSION(*mapi_version
))
857 struct mapi_mheader_av1
*mheader
= (struct mapi_mheader_av1
*)(void *)mapi_version
; /* see above */
858 if(mheader
->mapi_register
&& (mheader
->mapi_register() == -1))
860 ilog(L_MAIN
, "Module %s indicated failure during load.",
862 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
863 "Module %s indicated failure during load.",
866 rb_free(mod_basename
);
869 if(mheader
->mapi_command_list
)
872 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
876 if(mheader
->mapi_hook_list
)
879 for (m
= mheader
->mapi_hook_list
; m
->hapi_name
; ++m
)
880 *m
->hapi_id
= register_hook(m
->hapi_name
);
883 if(mheader
->mapi_hfn_list
)
885 mapi_hfn_list_av1
*m
;
886 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
887 add_hook(m
->hapi_name
, m
->fn
);
890 ver
= mheader
->mapi_module_version
;
895 struct mapi_mheader_av2
*mheader
= (struct mapi_mheader_av2
*)(void *)mapi_version
; /* see above */
897 /* XXX duplicated code :( */
898 if(mheader
->mapi_register
&& (mheader
->mapi_register() == -1))
900 ilog(L_MAIN
, "Module %s indicated failure during load.",
902 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
903 "Module %s indicated failure during load.",
906 rb_free(mod_basename
);
910 /* Basic date code checks
912 * Don't make them fatal, but do complain about differences within a certain time frame.
913 * Later on if there are major API changes we can add fatal checks.
916 if(mheader
->mapi_datecode
!= datecode
&& mheader
->mapi_datecode
> 0)
918 long int delta
= datecode
- mheader
->mapi_datecode
;
919 if (delta
> MOD_WARN_DELTA
)
922 iwarn("Module %s build date is out of sync with ircd build date by %ld days, expect problems",
923 mod_basename
, delta
);
924 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
925 "Module %s build date is out of sync with ircd build date by %ld days, expect problems",
926 mod_basename
, delta
);
930 if(mheader
->mapi_command_list
)
933 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
937 if(mheader
->mapi_hook_list
)
940 for (m
= mheader
->mapi_hook_list
; m
->hapi_name
; ++m
)
941 *m
->hapi_id
= register_hook(m
->hapi_name
);
944 if(mheader
->mapi_hfn_list
)
946 mapi_hfn_list_av1
*m
;
947 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
948 add_hook(m
->hapi_name
, m
->fn
);
951 /* New in MAPI v2 - version replacement */
952 ver
= mheader
->mapi_module_version
? mheader
->mapi_module_version
: ircd_version
;
953 description
= mheader
->mapi_module_description
;
955 if(mheader
->mapi_cap_list
)
957 mapi_cap_list_av2
*m
;
958 for (m
= mheader
->mapi_cap_list
; m
->cap_name
; ++m
)
960 struct CapabilityIndex
*idx
;
963 switch (m
->cap_index
)
965 case MAPI_CAP_CLIENT
:
968 case MAPI_CAP_SERVER
:
972 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
973 "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
974 m
->cap_index
, m
->cap_name
, mod_basename
);
976 "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
977 m
->cap_index
, m
->cap_name
, mod_basename
);
981 result
= capability_put(idx
, m
->cap_name
, m
->cap_ownerdata
);
982 if (m
->cap_id
!= NULL
)
984 *(m
->cap_id
) = result
;
985 sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY
, ":%s CAP * ADD :%s", me
.name
, m
->cap_name
);
993 ilog(L_MAIN
, "Module %s has unknown/unsupported MAPI version %d.",
994 mod_basename
, MAPI_VERSION(*mapi_version
));
995 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
996 "Module %s has unknown/unsupported MAPI version %d.",
997 mod_basename
, *mapi_version
);
999 rb_free(mod_basename
);
1006 if(description
== NULL
)
1007 description
= unknown_description
;
1011 modlist
[num_mods
] = rb_malloc(sizeof(struct module));
1012 modlist
[num_mods
]->address
= tmpptr
;
1013 modlist
[num_mods
]->version
= ver
;
1014 modlist
[num_mods
]->description
= description
;
1015 modlist
[num_mods
]->core
= core
;
1016 modlist
[num_mods
]->name
= rb_strdup(mod_basename
);
1017 modlist
[num_mods
]->mapi_header
= mapi_version
;
1018 modlist
[num_mods
]->mapi_version
= MAPI_VERSION(*mapi_version
);
1019 modlist
[num_mods
]->origin
= origin
;
1028 case MAPI_ORIGIN_EXTENSION
:
1031 case MAPI_ORIGIN_CORE
:
1039 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1040 "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at %p",
1041 mod_basename
, ver
, MAPI_VERSION(*mapi_version
), o
, description
,
1043 ilog(L_MAIN
, "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at %p",
1044 mod_basename
, ver
, MAPI_VERSION(*mapi_version
), o
, description
, (void *) tmpptr
);
1046 rb_free(mod_basename
);
1055 * side effects - expand the size of modlist if necessary
1058 increase_modlist(void)
1060 struct module **new_modlist
= NULL
;
1062 if((num_mods
+ 1) < max_mods
)
1065 new_modlist
= (struct module **) rb_malloc(sizeof(struct module *) *
1066 (max_mods
+ MODS_INCREMENT
));
1067 memcpy((void *) new_modlist
, (void *) modlist
, sizeof(struct module *) * num_mods
);
1070 modlist
= new_modlist
;
1071 max_mods
+= MODS_INCREMENT
;