=head1 Modules Ermyth has an easy to use module framework. It is rather strict when it comes to module initialisation but apart from that, you are free to put in anything you like. It is not recommended to create module dependencies but if you must, you can use the C macro to force the system to unload your module if the module yours depends on is unloaded. =head2 Writing a module First, you need the module header #include "atheme.h" #include And the mandatory rcsid line static char const rcsid[] = "$Id: module.pod,v 1.2 2007/08/30 19:56:18 pippijn Exp $"; Then, you register your module with REGISTER_MODULE. REGISTER_MODULE ("avada/kedavra", false, "Lord Voldemort"); =over =item "avada/kedavra" This is the module name, it is arbitrary and used by the C configuration directive to load it. =item false A boolean declaring whether or not this module needs to be protected from unloading. Giving this a true value prohibits unloading. =item "Lord Voldemort" The module vendor. This may be a person or a group of programmers. Most modules in Ermyth have been written by The Ermyth Team and the Atheme Development Group. =back Next, you can put in any other program code you like. void kill_harry_potter (void *) { puts ("Avada kedavra!"); } Last, you will need to define the initialisation and deinitialisation routines. _modinit returns C if the module was loaded successfully and C if it was not. If it was not, its state will be "not loaded" which means, it cannot be unloaded. Be aware that if your module fails, you will need to manually clean up and revert changes that _modinit did up to the exit point, as _moddeinit does not get called on failure. bool _modinit (module *m) { puts ("I am going to kill Harry Potter!"); // Kill harry potter every five minutes event_add ("kill potter", kill_harry_potter, NULL, 300); // Module loaded successfully return true; } void _moddeinit () { puts ("Whahaha, I win!"); } =head2 Using the module That's it. Now you have a working module. You can load it in the configuration with the C directive: loadmodule "avada/kedavra"; =head2 The module API The modules class provides an interface to the module API. =over =item bool modules::provides (char const * const name) This returns true if the module called C has been registered. Returns false otherwise. =item fault::code modules::enable (char const * const name) Enables a module. Returns C if the named module was not registered. Returns C if the module was already loaded. Returns C if the module's C<_modinit ()> failed. Returns C if the module was enabled successfully. =item fault::code modules::disable (char const * const name) Disables a module. Returns C if the named module was not registered. Returns C if the module was not loaded. Returns C if the module is protected. Returns C if the module was disabled successfully. =item module *modules::find (char const * const name) Returns a pointer to a module struct if the named module was registered. Returns C otherwise. =item void modules::cleanup () Unload all modules and delete their access structures. After this, the module API will be completely defunct. It is and should only be done on shutdown. =item REGISTER_MODULE (char const * const name, bool protected, char const * const vendor) This macro should come after the rcsid line and before the definition of _modinit and _moddeinit, as it declares these two functions. =item REGISTER_DEPENDENCY (char const * const thismod, char const * const othermod) Records a module dependency of thismod => othermod. If othermod gets unloaded, thismod gets unloaded as well. =item modules::list_type This is a typedef of std::vector that is used for the module list. =item modules::list_type const &modules::list () Returns the vector containing all module access objects. You can iterate over them like operserv/modlist does but you can not change its contents. =back