1 /* {{{ irc-seven: Cows like it.
3 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center.
4 * Copyright (C) 1996-2002 Hybrid Development Team.
5 * Copyright (C) 2002-2005 ircd-ratbox development team.
6 * Copyright (C) 2006 Elfyn McBratney.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to:
21 * Free Software Foundation, Inc.
22 * 51 Franklin St - Fifth Floor
23 * Boston, MA 02110-1301
36 #include "s_newconf.h"
40 #include "ircd_defs.h"
41 #include "irc_string.h"
44 #include "sprintf_irc.h"
47 # define MODS_INCREMENT 10
49 struct module
**modlist
= NULL
;
51 /* {{{ static const char *core_module_table[] = { ... } */
53 # define M(n) _M(m_##n)
55 static const char *core_module_table
[] =
75 int max_mods
= MODS_INCREMENT
;
77 static dlink_list mod_paths
;
79 extern struct Message error_msgtab
;
82 static int mo_modload (struct Client
*, struct Client
*, int, const char **);
83 static int me_modload (struct Client
*, struct Client
*, int, const char **);
84 static int mo_modunload (struct Client
*, struct Client
*, int, const char **);
85 static int me_modunload (struct Client
*, struct Client
*, int, const char **);
86 static int mo_modreload (struct Client
*, struct Client
*, int, const char **);
87 static int me_modreload (struct Client
*, struct Client
*, int, const char **);
88 static int mo_modrestart (struct Client
*, struct Client
*, int, const char **);
89 static int me_modrestart (struct Client
*, struct Client
*, int, const char **);
90 static int mo_modlist (struct Client
*, struct Client
*, int, const char **);
91 static int me_modlist (struct Client
*, struct Client
*, int, const char **);
93 static int do_modload (struct Client
*, const char *);
94 static int do_modunload (struct Client
*, const char *);
95 static int do_modreload (struct Client
*, const char *);
96 static int do_modrestart (struct Client
*);
97 static int do_modlist (struct Client
*);
100 /* {{{ static struct Message modload_msgtab = { ... } */
101 struct Message modload_msgtab
= {
102 "MODLOAD", 0, 0, 0, MFLG_SLOW
,
104 mg_unreg
, mg_not_oper
, mg_ignore
,
105 mg_ignore
, {me_modload
, 1}, {mo_modload
, 0},
110 /* {{{ static struct Message modunload_msgtab = { ... } */
111 struct Message modunload_msgtab
=
113 "MODUNLOAD", 0, 0, 0, MFLG_SLOW
,
115 mg_unreg
, mg_not_oper
, mg_ignore
,
116 mg_ignore
, {me_modunload
, 1}, {mo_modunload
, 0},
121 /* {{{ static struct Message modreload_msgtab = { ... } */
122 struct Message modreload_msgtab
=
124 "MODRELOAD", 0, 0, 0, MFLG_SLOW
,
126 mg_unreg
, mg_not_oper
, mg_ignore
,
127 mg_ignore
, {me_modreload
, 1}, {mo_modreload
, 0},
132 /* {{{ static struct Message modrestart_msgtab = { ... } */
133 struct Message modrestart_msgtab
=
135 "MODRESTART", 0, 0, 0, MFLG_SLOW
,
137 mg_unreg
, mg_not_oper
, mg_ignore
,
138 mg_ignore
, {me_modrestart
, 0}, {mo_modrestart
, 0},
143 /* {{{ static struct Message modlist_msgtab = { ... } */
144 struct Message modlist_msgtab
=
146 "MODLIST", 0, 0, 0, MFLG_SLOW
,
148 mg_unreg
, mg_not_oper
, mg_ignore
,
149 mg_ignore
, {me_modlist
, 0}, {mo_modlist
, 0},
154 /* {{{ void modules_init() */
158 mod_add_cmd(&modload_msgtab
);
159 mod_add_cmd(&modunload_msgtab
);
160 mod_add_cmd(&modreload_msgtab
);
161 mod_add_cmd(&modlist_msgtab
);
162 mod_add_cmd(&modrestart_msgtab
);
164 /* Add the default paths we look in to the module system --nenolod */
165 mod_add_path(MODPATH
);
166 mod_add_path(AUTOMODPATH
);
170 /* {{{ static struct module_path *mod_find_path()
174 * side effects - returns a module path from path
176 static struct module_path
*
177 mod_find_path (const char *path
)
179 dlink_node
*cur
= NULL
;
180 struct module_path
*mpath
= NULL
;
182 DLINK_FOREACH (cur
, mod_paths
.head
)
185 if(!strcmp(path
, mpath
->path
))
193 /* {{{ void mod_add_path()
197 * side effects - adds path to list
200 mod_add_path (const char *path
)
202 struct module_path
*pathst
= NULL
;
204 if(mod_find_path(path
))
207 pathst
= MyMalloc(sizeof(*pathst
));
208 strcpy(pathst
->path
, path
);
209 dlinkAddAlloc(pathst
, &mod_paths
);
213 /* {{{ void mod_clear_paths()
217 * side effects - clear the lists of paths
220 mod_clear_paths (void)
222 dlink_node
*cur
= NULL
;
223 dlink_node
*next
= NULL
;
225 DLINK_FOREACH_SAFE (cur
, next
, mod_paths
.head
)
228 free_dlink_node(cur
);
231 mod_paths
.head
= mod_paths
.tail
= NULL
;
232 mod_paths
.length
= 0;
236 /* {{{ char *irc_basename()
243 irc_basename (const char *path
)
245 char *mod_basename
= MyMalloc(strlen(path
) + 1);
246 const char *s
= NULL
;
248 s
= strrchr(path
, '/');
254 strcpy(mod_basename
, s
);
259 /* {{{ int findmodule_byname()
266 findmodule_byname (const char *name
)
270 for (i
= 0; i
< num_mods
; ++i
)
272 if(!irccmp(modlist
[i
]->name
, name
))
280 /* {{{ void load_all_modules()
287 load_all_modules (int warn
)
289 DIR *system_module_dir
= NULL
;
290 struct dirent
*ldirent
= NULL
;
291 char module_fq_name
[PATH_MAX
+ 1];
296 modlist
= (struct module
**) MyMalloc(sizeof(struct module
) * (MODS_INCREMENT
));
297 max_mods
= MODS_INCREMENT
;
298 system_module_dir
= opendir(AUTOMODPATH
);
300 if(system_module_dir
== NULL
)
302 ilog(L_MAIN
, "Could not load modules from %s: %s", AUTOMODPATH
, strerror(errno
));
306 while ((ldirent
= readdir(system_module_dir
)) != NULL
)
308 len
= strlen(ldirent
->d_name
);
309 if((len
> 3) && !strcmp(ldirent
->d_name
+len
-3, SHARED_SUFFIX
))
311 (void) ircsnprintf(module_fq_name
, sizeof(module_fq_name
), "%s/%s", AUTOMODPATH
, ldirent
->d_name
);
312 (void) load_a_module(module_fq_name
, warn
, 0);
317 (void) closedir(system_module_dir
);
321 /* {{{ void load_core_modules()
325 * side effects - core modules are loaded, if any fail, kill ircd
328 load_core_modules (int warn
)
331 char module_name
[MAXPATHLEN
];
333 for (i
= 0; core_module_table
[i
]; ++i
)
335 ircsnprintf(module_name
, sizeof(module_name
), "%s/%s%s", MODPATH
,
336 core_module_table
[i
], SHARED_SUFFIX
);
338 if(load_a_module(module_name
, warn
, 1) == -1)
341 "Error loading core module %s%s: terminating ircd",
342 core_module_table
[i
], SHARED_SUFFIX
);
349 /* {{{ int load_one_module()
356 load_one_module (const char *path
, int coremodule
)
358 char modpath
[MAXPATHLEN
];
359 dlink_node
*cur
= NULL
;
360 struct module_path
*mpath
= NULL
;
363 if (server_state_foreground
== 1)
364 inotice("loading module %s ...", path
);
366 DLINK_FOREACH (cur
, mod_paths
.head
)
369 ircsnprintf(modpath
, sizeof(modpath
), "%s/%s", mpath
->path
, path
);
371 if ((strstr(modpath
, "../") == NULL
) && (strstr(modpath
, "/..") == NULL
))
373 if (stat(modpath
, &statbuf
) == 0)
375 if (S_ISREG(statbuf
.st_mode
))
377 /* Regular files only please */
379 return load_a_module(modpath
, 1, 1);
381 return load_a_module(modpath
, 1, 0);
388 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Cannot locate module %s", path
);
393 /* {{{ static int mo_modload()
395 * Load a module into the IRCd.
398 * MODLOAD <module> [ON <server>]
402 * parv[2] - "ON", or nothing
403 * parv[3] - server, or nothing
406 mo_modload (struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
408 if (!IsOperAdmin(source_p
))
410 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
411 me
.name
, source_p
->name
, "admin");
417 ":%s NOTICE %s :To many parameters to MODLOAD",
418 me
.name
, source_p
->name
);
421 else if ((parc
!= 2 && parc
!= 4) || EmptyString(parv
[1]))
423 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
), me
.name
,
424 source_p
->name
, "MODLOAD");
431 if (EmptyString(parv
[2]) | EmptyString(parv
[3]))
433 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
), me
.name
,
434 source_p
->name
, "MODLOAD");
437 else if (irccmp(parv
[2], "ON") != 0)
440 ":%s NOTICE %s :Second argument to MODLOAD "
441 "must be [ON] not [%s]",
442 me
.name
, source_p
->name
, parv
[2]);
446 sendto_match_servs(source_p
, parv
[3], CAP_ENCAP
, NOCAPS
,
447 "ENCAP %s MODLOAD :%s", parv
[3], parv
[1]);
449 if (!match(parv
[3], me
.name
))
453 return do_modload(source_p
, parv
[1]);
457 /* {{{ static int me_modload()
459 * MODLOAD ENCAP message handler.
468 me_modload (struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
470 if (!IsPerson(source_p
) || EmptyString(parv
[1]))
472 if (!find_client_shared_conf(source_p
, SHARED_MODULE
))
475 return do_modload(source_p
, parv
[1]);
479 /* {{{ static int do_modload()
481 * Perform actual loading of modules into the IRCd.
484 do_modload (struct Client
*source_p
, const char *path
)
488 base
= irc_basename(path
);
489 if (findmodule_byname(base
) != -1)
492 ":%s NOTICE %s :Module %s is already loaded",
493 me
.name
, source_p
->name
, base
);
499 load_one_module(path
, 0);
506 /* {{{ static int mo_modunload()
508 * Unload a module from the IRCd.
517 mo_modunload(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
519 if (!IsOperAdmin(source_p
))
521 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
522 me
.name
, source_p
->name
, "admin");
528 ":%s NOTICE %s :To many parameters to MODUNLOAD",
529 me
.name
, source_p
->name
);
532 else if ((parc
!= 2 && parc
!= 4) || EmptyString(parv
[1]))
534 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
), me
.name
,
535 source_p
->name
, "MODUNLOAD");
542 if (EmptyString(parv
[2]) | EmptyString(parv
[3]))
544 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
), me
.name
,
545 source_p
->name
, "MODUNLOAD");
548 else if (irccmp(parv
[2], "ON") != 0)
551 ":%s NOTICE %s :Second argument to MODUNLOAD "
552 "must be [ON] not [%s]",
553 me
.name
, source_p
->name
, parv
[2]);
557 sendto_match_servs(source_p
, parv
[3], CAP_ENCAP
, NOCAPS
,
558 "ENCAP %s MODUNLOAD :%s", parv
[3], parv
[1]);
560 if (!match(parv
[3], me
.name
))
564 return do_modunload(source_p
, parv
[1]);
568 /* {{{ static int me_modunload()
570 * MODUNLOAD ENCAP message handler.
579 me_modunload (struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
581 if (!IsPerson(source_p
) || EmptyString(parv
[1]))
583 if (!find_client_shared_conf(source_p
, SHARED_MODULE
))
586 return do_modunload(source_p
, parv
[1]);
590 /* {{{ static int do_modunload()
592 * Perform actual unloading of modules.
595 do_modunload (struct Client
*source_p
, const char *path
)
600 base
= irc_basename(path
);
601 if ((i
= findmodule_byname(base
)) < 0)
604 ":%s NOTICE %s :Module %s is not loaded",
605 me
.name
, source_p
->name
, base
);
611 if (modlist
[i
]->core
== 1)
614 ":%s NOTICE %s :Module %s is a core module and cannot be unloaded",
615 me
.name
, source_p
->name
, base
);
621 if (unload_one_module(base
, 1) < 0)
623 ":%s NOTICE %s :Module %s is not loaded",
624 me
.name
, source_p
->name
, base
);
631 /* {{{ static int mo_modreload()
633 * Reload (i.e., unload and then load) a module.
636 * MODRELOAD <module> [ON <server>]
640 * parv[2] - "ON", or nothing
641 * parv[3] - server, or nothing
644 mo_modreload (struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
646 if (!IsOperAdmin(source_p
))
648 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
649 me
.name
, source_p
->name
, "admin");
655 ":%s NOTICE %s :To many parameters to MODRELOAD",
656 me
.name
, source_p
->name
);
659 else if ((parc
!= 2 && parc
!= 4) || EmptyString(parv
[1]))
661 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
), me
.name
,
662 source_p
->name
, "MODRELOAD");
669 if (EmptyString(parv
[2]) | EmptyString(parv
[3]))
671 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
), me
.name
,
672 source_p
->name
, "MODRELOAD");
675 else if (irccmp(parv
[2], "ON") != 0)
678 ":%s NOTICE %s :Second argument to MODRELOAD "
679 "must be [ON] not [%s]",
680 me
.name
, source_p
->name
, parv
[2]);
684 sendto_match_servs(source_p
, parv
[3], CAP_ENCAP
, NOCAPS
,
685 "ENCAP %s MODRELOAD :%s", parv
[3], parv
[1]);
687 if (!match(parv
[3], me
.name
))
691 return do_modreload(source_p
, parv
[1]);
695 /* {{{ static int me_modreload()
697 * MODRELOAD ENCAP message handler.
706 me_modreload (struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
708 if (!IsPerson(source_p
) || EmptyString(parv
[1]))
710 if (!find_client_shared_conf(source_p
, SHARED_MODULE
))
713 return do_modreload(source_p
, parv
[1]);
717 /* {{{ static int do_modreload()
719 * Perform actual reloading of modules.
722 do_modreload (struct Client
*source_p
, const char *path
)
728 base
= irc_basename(path
);
729 if ((i
= findmodule_byname(base
)) < 0)
732 ":%s NOTICE %s :Module %s is not loaded",
733 me
.name
, source_p
->name
, base
);
739 is_core
= modlist
[i
]->core
;
740 if (unload_one_module(base
, 1) < 0)
743 ":%s NOTICE %s :Module %s is not loaded",
744 me
.name
, source_p
->name
, base
);
750 if (load_one_module(path
, is_core
) < 0 && is_core
)
752 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
753 "Error while reloading core module: %s; terminating ircd",
757 "Error while reloading core module: %s; terminating ircd",
767 /* {{{ static int mo_modrestart()
769 * Reload all modules.
772 * MODRESTART [ON <server>]
775 * parv[1] - "ON", or nothing
776 * parv[2] - server, or nothing
779 mo_modrestart (struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
781 if (!IsOperAdmin(source_p
))
783 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
784 me
.name
, source_p
->name
, "admin");
790 ":%s NOTICE %s :To many parameters to MODRESTART",
791 me
.name
, source_p
->name
);
794 else if (parc
== 2 || (parc
== 3 && (EmptyString(parv
[1]) || EmptyString(parv
[2]))))
796 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
), me
.name
,
797 source_p
->name
, "MODRESTART");
803 if (irccmp(parv
[1], "ON") != 0)
806 ":%s NOTICE %s :Second argument to MODRESTART "
807 "must be [ON] not [%s]",
808 me
.name
, source_p
->name
, parv
[1]);
812 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
813 "ENCAP %s MODRESTART", parv
[2]);
815 if (!match(parv
[2], me
.name
))
819 return do_modrestart(source_p
);
823 /* {{{ static int me_modrestart()
825 * MODRESTART ENCAP message handler.
833 me_modrestart (struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
835 if (!IsPerson(source_p
))
837 if (!find_client_shared_conf(source_p
, SHARED_MODULE
))
840 return do_modrestart(source_p
);
844 /* {{{ static int do_modrestart()
846 * Perform actual restart of all modules.
849 do_modrestart (struct Client
*source_p
)
853 sendto_one(source_p
, ":%s NOTICE %s :Reloading all modules",
854 me
.name
, source_p
->name
);
858 unload_one_module(modlist
[0]->name
, 0);
861 load_core_modules(0);
864 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
865 "Module Restart: %d modules unloaded, %d modules loaded",
867 ilog(L_MAIN
, "Module Restart: %d modules unloaded, %d modules loaded",
874 /* {{{ static int mo_modlist()
876 * List modules currently loaded into the IRCd.
879 * MODLIST [<module>] [ON <server>]
882 * parv[2] - "ON", or nothing
883 * parv[3] - server, or nothing
886 mo_modlist (struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
888 if (!IsOperAdmin(source_p
))
890 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
891 me
.name
, source_p
->name
, "admin");
897 ":%s NOTICE %s :To many parameters to MODLIST",
898 me
.name
, source_p
->name
);
901 else if (parc
== 2 || (parc
== 3 && (EmptyString(parv
[1]) || EmptyString(parv
[2]))))
903 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
), me
.name
,
904 source_p
->name
, "MODLIST");
910 if (irccmp(parv
[1], "ON") != 0)
913 ":%s NOTICE %s :Second argument to MODLIST "
914 "must be [ON] not [%s]",
915 me
.name
, source_p
->name
, parv
[1]);
919 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
920 "ENCAP %s MODLIST", parv
[2]);
922 if (!match(parv
[2], me
.name
))
926 return do_modlist(source_p
);
930 /* {{{ static int me_modlist()
932 * MODLIST ENCAP message handler.
940 me_modlist (struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
942 if (!IsPerson(source_p
))
944 if (!find_client_shared_conf(source_p
, SHARED_MODULE
))
947 return do_modlist(source_p
);
951 /* {{{ static int do_modlist()
953 * Perform actual listing of loaded in modules.
956 do_modlist (struct Client
*source_p
)
960 for (i
= 0; i
< num_mods
; ++i
)
962 sendto_one(source_p
, form_str(RPL_MODLIST
), me
.name
,
963 source_p
->name
, modlist
[i
]->name
,
964 modlist
[i
]->address
, modlist
[i
]->version
,
965 modlist
[i
]->core
? "(core)" : "");
968 sendto_one(source_p
, form_str(RPL_ENDOFMODLIST
), me
.name
,
976 # define RTLD_NOW RTLD_LAZY /* openbsd deficiency */
979 # ifdef SEVEN_PROFILE
980 # ifndef RTLD_PROFILE
981 # warning libdl may not support profiling, sucks. :(
982 # define RTLD_PROFILE 0
986 static void increase_modlist(void);
988 static char unknown_ver
[] = "<unknown>";
990 /* {{{ int unload_one_module()
992 * inputs - name of module to unload
993 * - 1 to say modules unloaded, 0 to not
994 * output - 0 if successful, -1 if error
995 * side effects - module is unloaded
998 unload_one_module(const char *name
, int warn
)
1002 if((modindex
= findmodule_byname(name
)) == -1)
1006 ** XXX - The type system in C does not allow direct conversion between
1007 ** data and function pointers, but as it happens, most C compilers will
1008 ** safely do this, however it is a theoretical overlow to cast as we
1009 ** must do here. I have library functions to take care of this, but
1010 ** despite being more "correct" for the C language, this is more
1011 ** practical. Removing the abuse of the ability to cast ANY pointer
1012 ** to and from an integer value here will break some compilers.
1015 /* Left the comment in but the code isn't here any more -larne */
1016 switch (modlist
[modindex
]->mapi_version
)
1020 struct mapi_mheader_av1
*mheader
= modlist
[modindex
]->mapi_header
;
1021 if(mheader
->mapi_command_list
)
1024 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
1028 /* hook events are never removed, we simply lose the
1029 * ability to call them --fl
1031 if(mheader
->mapi_hfn_list
)
1033 mapi_hfn_list_av1
*m
;
1034 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
1035 remove_hook(m
->hapi_name
, m
->fn
);
1038 if(mheader
->mapi_unregister
)
1039 mheader
->mapi_unregister();
1043 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1044 "Unknown/unsupported MAPI version %d when unloading %s!",
1045 modlist
[modindex
]->mapi_version
, modlist
[modindex
]->name
);
1046 ilog(L_MAIN
, "Unknown/unsupported MAPI version %d when unloading %s!",
1047 modlist
[modindex
]->mapi_version
, modlist
[modindex
]->name
);
1051 dlclose(modlist
[modindex
]->address
);
1053 MyFree(modlist
[modindex
]->name
);
1054 memcpy(&modlist
[modindex
], &modlist
[modindex
+ 1],
1055 sizeof(struct module
) * ((num_mods
- 1) - modindex
));
1062 ilog(L_MAIN
, "Module %s unloaded", name
);
1063 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Module %s unloaded", name
);
1070 /* {{{ int load_a_module()
1072 * inputs - path name of module, int to notice, int of core
1073 * output - -1 if error 0 if success
1074 * side effects - loads a module if successful
1077 load_a_module(const char *path
, int warn
, int core
)
1079 void *tmpptr
= NULL
;
1086 mod_basename
= irc_basename(path
);
1088 #ifdef SEVEN_PROFILE
1089 tmpptr
= dlopen(path
, RTLD_NOW
| RTLD_PROFILE
);
1091 tmpptr
= dlopen(path
, RTLD_NOW
);
1096 const char *err
= dlerror();
1098 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1099 "Error loading module %s: %s", mod_basename
, err
);
1100 ilog(L_MAIN
, "Error loading module %s: %s", mod_basename
, err
);
1101 MyFree(mod_basename
);
1107 * _mheader is actually a struct mapi_mheader_*, but mapi_version
1108 * is always the first member of this structure, so we treate it
1109 * as a single int in order to determine the API version.
1112 mapi_version
= (int *) (uintptr_t) dlsym(tmpptr
, "_mheader");
1113 if((mapi_version
== NULL
1114 && (mapi_version
= (int *) (uintptr_t) dlsym(tmpptr
, "__mheader")) == NULL
)
1115 || MAPI_MAGIC(*mapi_version
) != MAPI_MAGIC_HDR
)
1117 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1118 "Data format error: module %s has no MAPI header.",
1120 ilog(L_MAIN
, "Data format error: module %s has no MAPI header.", mod_basename
);
1121 (void) dlclose(tmpptr
);
1122 MyFree(mod_basename
);
1126 switch (MAPI_VERSION(*mapi_version
))
1130 struct mapi_mheader_av1
*mheader
= (struct mapi_mheader_av1
*) mapi_version
; /* see above */
1131 if(mheader
->mapi_register
&& (mheader
->mapi_register() == -1))
1133 ilog(L_MAIN
, "Module %s indicated failure during load.",
1135 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1136 "Module %s indicated failure during load.",
1139 MyFree(mod_basename
);
1142 if(mheader
->mapi_command_list
)
1145 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
1149 if(mheader
->mapi_hook_list
)
1152 for (m
= mheader
->mapi_hook_list
; m
->hapi_name
; ++m
)
1153 *m
->hapi_id
= register_hook(m
->hapi_name
);
1156 if(mheader
->mapi_hfn_list
)
1158 mapi_hfn_list_av1
*m
;
1159 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
1160 add_hook(m
->hapi_name
, m
->fn
);
1163 ver
= mheader
->mapi_module_version
;
1168 ilog(L_MAIN
, "Module %s has unknown/unsupported MAPI version %d.",
1169 mod_basename
, MAPI_VERSION(*mapi_version
));
1170 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1171 "Module %s has unknown/unsupported MAPI version %d.",
1172 mod_basename
, *mapi_version
);
1174 MyFree(mod_basename
);
1183 modlist
[num_mods
] = MyMalloc(sizeof(struct module
));
1184 modlist
[num_mods
]->address
= tmpptr
;
1185 modlist
[num_mods
]->version
= ver
;
1186 modlist
[num_mods
]->core
= core
;
1187 DupString(modlist
[num_mods
]->name
, mod_basename
);
1188 modlist
[num_mods
]->mapi_header
= mapi_version
;
1189 modlist
[num_mods
]->mapi_version
= MAPI_VERSION(*mapi_version
);
1194 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1195 "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx",
1196 mod_basename
, ver
, MAPI_VERSION(*mapi_version
),
1197 (unsigned long) tmpptr
);
1198 ilog(L_MAIN
, "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx",
1199 mod_basename
, ver
, MAPI_VERSION(*mapi_version
), (unsigned long) tmpptr
);
1201 MyFree(mod_basename
);
1206 /* {{{ static void increase_modlist()
1210 * side effects - expand the size of modlist if necessary
1213 increase_modlist(void)
1215 struct module
**new_modlist
= NULL
;
1217 if((num_mods
+ 1) < max_mods
)
1220 new_modlist
= (struct module
**) MyMalloc(sizeof(struct module
) *
1221 (max_mods
+ MODS_INCREMENT
));
1222 memcpy((void *) new_modlist
, (void *) modlist
, sizeof(struct module
) * num_mods
);
1225 modlist
= new_modlist
;
1226 max_mods
+= MODS_INCREMENT
;
1231 * vim: ts=8 sw=8 noet fdm=marker tw=80