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"
42 struct module **modlist
= NULL
;
44 static const char *core_module_table
[] = {
61 #define MOD_WARN_DELTA (90 * 86400) /* time in seconds, 86400 seconds in a day */
63 #define MODS_INCREMENT 10
65 int max_mods
= MODS_INCREMENT
;
67 static rb_dlink_list mod_paths
;
69 static void mo_modload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
70 static void mo_modlist(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
71 static void mo_modreload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
72 static void mo_modunload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
73 static void mo_modrestart(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
75 static void me_modload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
76 static void me_modlist(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
77 static void me_modreload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
78 static void me_modunload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
79 static void me_modrestart(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
81 static void do_modload(struct Client
*, const char *);
82 static void do_modunload(struct Client
*, const char *);
83 static void do_modreload(struct Client
*, const char *);
84 static void do_modlist(struct Client
*, const char *);
85 static void do_modrestart(struct Client
*);
87 struct Message modload_msgtab
= {
88 "MODLOAD", 0, 0, 0, 0,
89 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modload
, 2}, {mo_modload
, 2}}
92 struct Message modunload_msgtab
= {
93 "MODUNLOAD", 0, 0, 0, 0,
94 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modunload
, 2}, {mo_modunload
, 2}}
97 struct Message modreload_msgtab
= {
98 "MODRELOAD", 0, 0, 0, 0,
99 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modreload
, 2}, {mo_modreload
, 2}}
102 struct Message modlist_msgtab
= {
103 "MODLIST", 0, 0, 0, 0,
104 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modlist
, 0}, {mo_modlist
, 0}}
107 struct Message modrestart_msgtab
= {
108 "MODRESTART", 0, 0, 0, 0,
109 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modrestart
, 0}, {mo_modrestart
, 0}}
117 ilog(L_MAIN
, "lt_dlinit failed");
121 mod_add_cmd(&modload_msgtab
);
122 mod_add_cmd(&modunload_msgtab
);
123 mod_add_cmd(&modreload_msgtab
);
124 mod_add_cmd(&modlist_msgtab
);
125 mod_add_cmd(&modrestart_msgtab
);
127 /* Add the default paths we look in to the module system --nenolod */
128 mod_add_path(MODPATH
);
129 mod_add_path(AUTOMODPATH
);
136 * side effects - returns a module path from path
139 mod_find_path(const char *path
)
144 RB_DLINK_FOREACH(ptr
, mod_paths
.head
)
148 if(!strcmp(path
, mpath
))
159 * side effects - adds path to list
162 mod_add_path(const char *path
)
166 if(mod_find_path(path
))
169 pathst
= rb_strdup(path
);
170 rb_dlinkAddAlloc(pathst
, &mod_paths
);
177 * side effects - clear the lists of paths
180 mod_clear_paths(void)
182 rb_dlink_node
*ptr
, *next_ptr
;
184 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, mod_paths
.head
)
187 rb_free_rb_dlink_node(ptr
);
190 mod_paths
.head
= mod_paths
.tail
= NULL
;
191 mod_paths
.length
= 0;
202 findmodule_byname(const char *name
)
206 for (i
= 0; i
< num_mods
; i
++)
208 if(!irccmp(modlist
[i
]->name
, name
))
214 /* load_all_modules()
221 load_all_modules(int warn
)
223 DIR *system_module_dir
= NULL
;
224 struct dirent
*ldirent
= NULL
;
225 char module_fq_name
[PATH_MAX
+ 1];
230 modlist
= (struct module **) rb_malloc(sizeof(struct module *) * (MODS_INCREMENT
));
232 max_mods
= MODS_INCREMENT
;
234 system_module_dir
= opendir(AUTOMODPATH
);
236 if(system_module_dir
== NULL
)
238 ilog(L_MAIN
, "Could not load modules from %s: %s", AUTOMODPATH
, strerror(errno
));
242 while ((ldirent
= readdir(system_module_dir
)) != NULL
)
244 len
= strlen(ldirent
->d_name
);
245 if((len
> 3) && !strcmp(ldirent
->d_name
+len
-3, ".la"))
247 (void) snprintf(module_fq_name
, sizeof(module_fq_name
), "%s/%s", AUTOMODPATH
, ldirent
->d_name
);
248 (void) load_a_module(module_fq_name
, warn
, MAPI_ORIGIN_CORE
, 0);
252 (void) closedir(system_module_dir
);
255 /* load_core_modules()
259 * side effects - core modules are loaded, if any fail, kill ircd
262 load_core_modules(int warn
)
264 char module_name
[PATH_MAX
];
268 for (i
= 0; core_module_table
[i
]; i
++)
270 snprintf(module_name
, sizeof(module_name
), "%s/%s%s", MODPATH
,
271 core_module_table
[i
], ".la");
273 if(load_a_module(module_name
, warn
, MAPI_ORIGIN_CORE
, 1) == -1)
276 "Error loading core module %s%s: terminating ircd",
277 core_module_table
[i
], ".la");
290 load_one_module(const char *path
, int origin
, int coremodule
)
292 char modpath
[PATH_MAX
];
293 rb_dlink_node
*pathst
;
298 if (server_state_foreground
== 1)
299 inotice("loading module %s ...", path
);
304 origin
= MAPI_ORIGIN_CORE
;
307 RB_DLINK_FOREACH(pathst
, mod_paths
.head
)
309 mpath
= pathst
->data
;
311 snprintf(modpath
, sizeof(modpath
), "%s/%s", mpath
, path
);
312 if((strstr(modpath
, "../") == NULL
) && (strstr(modpath
, "/..") == NULL
))
314 if(stat(modpath
, &statbuf
) == 0)
316 if(S_ISREG(statbuf
.st_mode
))
318 /* Regular files only please */
319 return load_a_module(modpath
, 1, origin
, coremodule
);
326 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Cannot locate module %s", path
);
331 /* load a module .. */
333 mo_modload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
335 if(!IsOperAdmin(source_p
))
337 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
338 me
.name
, source_p
->name
, "admin");
344 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
345 "ENCAP %s MODLOAD %s", parv
[2], parv
[1]);
346 if (match(parv
[2], me
.name
) == 0)
350 do_modload(source_p
, parv
[1]);
354 me_modload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
356 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
358 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
359 "to load modules on this server.");
363 do_modload(source_p
, parv
[1]);
367 /* unload a module .. */
369 mo_modunload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
371 if(!IsOperAdmin(source_p
))
373 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
374 me
.name
, source_p
->name
, "admin");
380 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
381 "ENCAP %s MODUNLOAD %s", parv
[2], parv
[1]);
382 if (match(parv
[2], me
.name
) == 0)
386 do_modunload(source_p
, parv
[1]);
390 me_modunload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
392 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
394 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
395 "to load modules on this server.");
399 do_modunload(source_p
, parv
[1]);
402 /* unload and load in one! */
404 mo_modreload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
406 if(!IsOperAdmin(source_p
))
408 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
409 me
.name
, source_p
->name
, "admin");
415 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
416 "ENCAP %s MODRELOAD %s", parv
[2], parv
[1]);
417 if (match(parv
[2], me
.name
) == 0)
421 do_modreload(source_p
, parv
[1]);
425 me_modreload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
427 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
429 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
430 "to load modules on this server.");
434 do_modreload(source_p
, parv
[1]);
437 /* list modules .. */
439 mo_modlist(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
441 if(!IsOperAdmin(source_p
))
443 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
444 me
.name
, source_p
->name
, "admin");
450 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
451 "ENCAP %s MODLIST %s", parv
[2], parv
[1]);
452 if (match(parv
[2], me
.name
) == 0)
456 do_modlist(source_p
, parc
> 1 ? parv
[1] : 0);
460 me_modlist(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
462 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
464 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
465 "to load modules on this server.");
469 do_modlist(source_p
, parv
[1]);
472 /* unload and reload all modules */
474 mo_modrestart(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
476 if(!IsOperAdmin(source_p
))
478 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
479 me
.name
, source_p
->name
, "admin");
485 sendto_match_servs(source_p
, parv
[1], CAP_ENCAP
, NOCAPS
,
486 "ENCAP %s MODRESTART", parv
[1]);
487 if (match(parv
[1], me
.name
) == 0)
491 do_modrestart(source_p
);
495 me_modrestart(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
497 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
499 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
500 "to load modules on this server.");
504 do_modrestart(source_p
);
508 do_modload(struct Client
*source_p
, const char *module)
510 char *m_bn
= rb_basename(module);
513 if(findmodule_byname(m_bn
) != -1)
515 sendto_one_notice(source_p
, ":Module %s is already loaded", m_bn
);
520 origin
= strcmp(module, m_bn
) == 0 ? MAPI_ORIGIN_CORE
: MAPI_ORIGIN_EXTENSION
;
521 load_one_module(module, origin
, 0);
527 do_modunload(struct Client
*source_p
, const char *module)
530 char *m_bn
= rb_basename(module);
532 if((modindex
= findmodule_byname(m_bn
)) == -1)
534 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
539 if(modlist
[modindex
]->core
== 1)
541 sendto_one_notice(source_p
, ":Module %s is a core module and may not be unloaded", m_bn
);
546 if(unload_one_module(m_bn
, 1) == -1)
548 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
555 do_modreload(struct Client
*source_p
, const char *module)
559 char *m_bn
= rb_basename(module);
561 if((modindex
= findmodule_byname(m_bn
)) == -1)
563 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
568 check_core
= modlist
[modindex
]->core
;
570 if(unload_one_module(m_bn
, 1) == -1)
572 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
577 if((load_one_module(m_bn
, modlist
[modindex
]->origin
, check_core
) == -1) && check_core
)
579 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
580 "Error reloading core module: %s: terminating ircd", m_bn
);
581 ilog(L_MAIN
, "Error loading core module %s: terminating ircd", m_bn
);
589 do_modrestart(struct Client
*source_p
)
593 sendto_one_notice(source_p
, ":Reloading all modules");
597 unload_one_module(modlist
[0]->name
, 0);
600 load_core_modules(0);
603 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
604 "Module Restart: %d modules unloaded, %d modules loaded",
606 ilog(L_MAIN
, "Module Restart: %d modules unloaded, %d modules loaded", modnum
, num_mods
);
610 do_modlist(struct Client
*source_p
, const char *pattern
)
614 for (i
= 0; i
< num_mods
; i
++)
617 switch (modlist
[i
]->origin
)
619 case MAPI_ORIGIN_EXTENSION
:
620 origin
= "extension";
622 case MAPI_ORIGIN_CORE
:
632 if(match(pattern
, modlist
[i
]->name
))
634 sendto_one(source_p
, form_str(RPL_MODLIST
),
635 me
.name
, source_p
->name
,
637 (unsigned long)(uintptr_t)modlist
[i
]->address
, origin
,
638 modlist
[i
]->core
? " (core)" : "", modlist
[i
]->version
, modlist
[i
]->description
);
643 sendto_one(source_p
, form_str(RPL_MODLIST
),
644 me
.name
, source_p
->name
, modlist
[i
]->name
,
645 (unsigned long)(uintptr_t)modlist
[i
]->address
, origin
,
646 modlist
[i
]->core
? " (core)" : "", modlist
[i
]->version
, modlist
[i
]->description
);
650 sendto_one(source_p
, form_str(RPL_ENDOFMODLIST
), me
.name
, source_p
->name
);
653 static void increase_modlist(void);
655 #define MODS_INCREMENT 10
657 static char unknown_ver
[] = "<unknown>";
658 static char unknown_description
[] = "<none>";
660 /* unload_one_module()
662 * inputs - name of module to unload
663 * - 1 to say modules unloaded, 0 to not
664 * output - 0 if successful, -1 if error
665 * side effects - module is unloaded
668 unload_one_module(const char *name
, int warn
)
672 if((modindex
= findmodule_byname(name
)) == -1)
676 ** XXX - The type system in C does not allow direct conversion between
677 ** data and function pointers, but as it happens, most C compilers will
678 ** safely do this, however it is a theoretical overlow to cast as we
679 ** must do here. I have library functions to take care of this, but
680 ** despite being more "correct" for the C language, this is more
681 ** practical. Removing the abuse of the ability to cast ANY pointer
682 ** to and from an integer value here will break some compilers.
685 /* Left the comment in but the code isn't here any more -larne */
686 switch (modlist
[modindex
]->mapi_version
)
690 struct mapi_mheader_av1
*mheader
= modlist
[modindex
]->mapi_header
;
691 if(mheader
->mapi_command_list
)
694 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
698 /* hook events are never removed, we simply lose the
699 * ability to call them --fl
701 if(mheader
->mapi_hfn_list
)
703 mapi_hfn_list_av1
*m
;
704 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
705 remove_hook(m
->hapi_name
, m
->fn
);
708 if(mheader
->mapi_unregister
)
709 mheader
->mapi_unregister();
714 struct mapi_mheader_av2
*mheader
= modlist
[modindex
]->mapi_header
;
716 /* XXX duplicate code :( */
717 if(mheader
->mapi_command_list
)
720 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
724 /* hook events are never removed, we simply lose the
725 * ability to call them --fl
727 if(mheader
->mapi_hfn_list
)
729 mapi_hfn_list_av1
*m
;
730 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
731 remove_hook(m
->hapi_name
, m
->fn
);
734 if(mheader
->mapi_unregister
)
735 mheader
->mapi_unregister();
737 if(mheader
->mapi_cap_list
)
739 mapi_cap_list_av2
*m
;
740 for (m
= mheader
->mapi_cap_list
; m
->cap_name
; ++m
)
742 struct CapabilityIndex
*idx
;
744 switch (m
->cap_index
)
746 case MAPI_CAP_CLIENT
:
749 case MAPI_CAP_SERVER
:
753 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
754 "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s",
755 m
->cap_index
, m
->cap_name
, modlist
[modindex
]->name
);
757 "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s",
758 m
->cap_index
, m
->cap_name
, modlist
[modindex
]->name
);
762 capability_orphan(idx
, m
->cap_name
);
767 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
768 "Unknown/unsupported MAPI version %d when unloading %s!",
769 modlist
[modindex
]->mapi_version
, modlist
[modindex
]->name
);
770 ilog(L_MAIN
, "Unknown/unsupported MAPI version %d when unloading %s!",
771 modlist
[modindex
]->mapi_version
, modlist
[modindex
]->name
);
775 lt_dlclose(modlist
[modindex
]->address
);
777 rb_free(modlist
[modindex
]->name
);
778 rb_free(modlist
[modindex
]);
779 memmove(&modlist
[modindex
], &modlist
[modindex
+ 1],
780 sizeof(struct module *) * ((num_mods
- 1) - modindex
));
787 ilog(L_MAIN
, "Module %s unloaded", name
);
788 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Module %s unloaded", name
);
797 * inputs - path name of module, int to notice, int of origin, int of core
798 * output - -1 if error 0 if success
799 * side effects - loads a module if successful
802 load_a_module(const char *path
, int warn
, int origin
, int core
)
806 const char *ver
, *description
= NULL
;
810 mod_basename
= rb_basename(path
);
812 tmpptr
= lt_dlopen(path
);
816 const char *err
= lt_dlerror();
818 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
819 "Error loading module %s: %s", mod_basename
, err
);
820 ilog(L_MAIN
, "Error loading module %s: %s", mod_basename
, err
);
821 rb_free(mod_basename
);
827 * _mheader is actually a struct mapi_mheader_*, but mapi_version
828 * is always the first member of this structure, so we treate it
829 * as a single int in order to determine the API version.
832 mapi_version
= (int *) (uintptr_t) lt_dlsym(tmpptr
, "_mheader");
833 if((mapi_version
== NULL
834 && (mapi_version
= (int *) (uintptr_t) lt_dlsym(tmpptr
, "__mheader")) == NULL
)
835 || MAPI_MAGIC(*mapi_version
) != MAPI_MAGIC_HDR
)
837 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
838 "Data format error: module %s has no MAPI header.",
840 ilog(L_MAIN
, "Data format error: module %s has no MAPI header.", mod_basename
);
841 (void) lt_dlclose(tmpptr
);
842 rb_free(mod_basename
);
846 switch (MAPI_VERSION(*mapi_version
))
850 struct mapi_mheader_av1
*mheader
= (struct mapi_mheader_av1
*)(void *)mapi_version
; /* see above */
851 if(mheader
->mapi_register
&& (mheader
->mapi_register() == -1))
853 ilog(L_MAIN
, "Module %s indicated failure during load.",
855 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
856 "Module %s indicated failure during load.",
859 rb_free(mod_basename
);
862 if(mheader
->mapi_command_list
)
865 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
869 if(mheader
->mapi_hook_list
)
872 for (m
= mheader
->mapi_hook_list
; m
->hapi_name
; ++m
)
873 *m
->hapi_id
= register_hook(m
->hapi_name
);
876 if(mheader
->mapi_hfn_list
)
878 mapi_hfn_list_av1
*m
;
879 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
880 add_hook(m
->hapi_name
, m
->fn
);
883 ver
= mheader
->mapi_module_version
;
888 struct mapi_mheader_av2
*mheader
= (struct mapi_mheader_av2
*)(void *)mapi_version
; /* see above */
890 /* XXX duplicated code :( */
891 if(mheader
->mapi_register
&& (mheader
->mapi_register() == -1))
893 ilog(L_MAIN
, "Module %s indicated failure during load.",
895 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
896 "Module %s indicated failure during load.",
899 rb_free(mod_basename
);
903 /* Basic date code checks
905 * Don't make them fatal, but do complain about differences within a certain time frame.
906 * Later on if there are major API changes we can add fatal checks.
909 if(mheader
->mapi_datecode
!= datecode
&& mheader
->mapi_datecode
> 0)
911 long int delta
= datecode
- mheader
->mapi_datecode
;
912 if (delta
> MOD_WARN_DELTA
)
915 iwarn("Module %s build date is out of sync with ircd build date by %ld days, expect problems",
916 mod_basename
, delta
);
917 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
918 "Module %s build date is out of sync with ircd build date by %ld days, expect problems",
919 mod_basename
, delta
);
923 if(mheader
->mapi_command_list
)
926 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
930 if(mheader
->mapi_hook_list
)
933 for (m
= mheader
->mapi_hook_list
; m
->hapi_name
; ++m
)
934 *m
->hapi_id
= register_hook(m
->hapi_name
);
937 if(mheader
->mapi_hfn_list
)
939 mapi_hfn_list_av1
*m
;
940 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
941 add_hook(m
->hapi_name
, m
->fn
);
944 /* New in MAPI v2 - version replacement */
945 ver
= mheader
->mapi_module_version
? mheader
->mapi_module_version
: ircd_version
;
946 description
= mheader
->mapi_module_description
;
948 if(mheader
->mapi_cap_list
)
950 mapi_cap_list_av2
*m
;
951 for (m
= mheader
->mapi_cap_list
; m
->cap_name
; ++m
)
953 struct CapabilityIndex
*idx
;
956 switch (m
->cap_index
)
958 case MAPI_CAP_CLIENT
:
961 case MAPI_CAP_SERVER
:
965 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
966 "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
967 m
->cap_index
, m
->cap_name
, mod_basename
);
969 "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
970 m
->cap_index
, m
->cap_name
, mod_basename
);
974 result
= capability_put(idx
, m
->cap_name
, m
->cap_ownerdata
);
975 if (m
->cap_id
!= NULL
)
976 *(m
->cap_id
) = result
;
983 ilog(L_MAIN
, "Module %s has unknown/unsupported MAPI version %d.",
984 mod_basename
, MAPI_VERSION(*mapi_version
));
985 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
986 "Module %s has unknown/unsupported MAPI version %d.",
987 mod_basename
, *mapi_version
);
989 rb_free(mod_basename
);
996 if(description
== NULL
)
997 description
= unknown_description
;
1001 modlist
[num_mods
] = rb_malloc(sizeof(struct module));
1002 modlist
[num_mods
]->address
= tmpptr
;
1003 modlist
[num_mods
]->version
= ver
;
1004 modlist
[num_mods
]->description
= description
;
1005 modlist
[num_mods
]->core
= core
;
1006 modlist
[num_mods
]->name
= rb_strdup(mod_basename
);
1007 modlist
[num_mods
]->mapi_header
= mapi_version
;
1008 modlist
[num_mods
]->mapi_version
= MAPI_VERSION(*mapi_version
);
1009 modlist
[num_mods
]->origin
= origin
;
1018 case MAPI_ORIGIN_EXTENSION
:
1021 case MAPI_ORIGIN_CORE
:
1029 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1030 "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at 0x%lx",
1031 mod_basename
, ver
, MAPI_VERSION(*mapi_version
), o
, description
,
1032 (unsigned long) tmpptr
);
1033 ilog(L_MAIN
, "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at 0x%lx",
1034 mod_basename
, ver
, MAPI_VERSION(*mapi_version
), o
, description
, (unsigned long) tmpptr
);
1036 rb_free(mod_basename
);
1045 * side effects - expand the size of modlist if necessary
1048 increase_modlist(void)
1050 struct module **new_modlist
= NULL
;
1052 if((num_mods
+ 1) < max_mods
)
1055 new_modlist
= (struct module **) rb_malloc(sizeof(struct module *) *
1056 (max_mods
+ MODS_INCREMENT
));
1057 memcpy((void *) new_modlist
, (void *) modlist
, sizeof(struct module *) * num_mods
);
1060 modlist
= new_modlist
;
1061 max_mods
+= MODS_INCREMENT
;