RageIRCd v2.0 (bluemoon): Command API
-------------------------------------

$Id: command-api.txt,v 1.3.2.1 2005/02/21 02:32:45 amcwilliam Exp $
(C) 2000-2005 the RageIRCd Development Team, all rights reserved.

RageIRCd v2.0 provides a dynamic framework for server admins and developers 
alike, to extend the functionality of ircd. (See doc/dynamic-modules.txt 
for more information.) This extended versatility of RageIRCd v2.0 allows 
custom module developers to create new IRC commands, using the Command 
APIs.

Modules should introduce new commands to ircd through the use of 
registering Module Objects. Please read module-objects.txt for more 
information.

This document explains 1 structure, and 2 functions. They are required in 
order to add a new command to ircd via modules.

NB. This document makes references to the MOD_HEADER macro. For more 
    information, please read module-api.txt

1. msg_ptr: the message pointer struct

Message pointers contain specific information a Command: it's name, it's 
token (if any), and it's flags (options). The structure is defined in 
include/msg.h.

typedef struct _msg_ptr msg_ptr;
struct _msg_ptr {
	char *msg_str;
	char *tok_str;
	unsigned int cmd_flags;
};

char* msg_str - this is the name of the command. This is mandatory, as it 
is used internally by ircd, as well as by users.

char* tok_str - this is the token of the command, if any, used for 
optimised server<->server communication. If links support the TOK1 and 
SUID capabilities, this will be used instead of msg_str when sending to 
remote servers. It eliminates the need for a string-based command lookup, 
as the token is used as an index into a table. Only needed if this is to 
be used by servers.

unsigned int cmd_flags - sets various options on the command, outlined 
below.

		 CMDFLAG_NONE:	no flags (self explanitory!)
	 CMDFLAG_UNREGUSE:	available to unregistered clients/connections
	CMDFLAG_RESETIDLE:	reset idle time when used
		CMDFLAG_ALIAS:	eliminates need for : prefix for /cs, /globops, etc.

Below are some exaples of now msg_ptr is used. The first is the user-only 
command OPER. It is not used server<->server, and thus does not have a 
token. The second example is PRIVMSG, which is used both client<->server 
and server<->server. It also has a command option.

msg_ptr CMD_OPER = { "OPER", NULL, CMDFLAG_NONE };
msg_ptr CMD_PRIVMSG = { "PRIVMSG", "P", CMDFLAG_RESETIDLE };

NB. You can set more than one CMDFLAG in msg_ptr. However, be careful! 
Both msg_str and tok_str MUST be unique. If another command already loaded 
into ircd uses either of these, the command will not be created. Token 
collisions are especially dangerous!

2. int m_cmd(): the command

Each command on IRC has it's own function associated with it. When a user 
(or server) performs a command, it's Command structure is looked up. 
After parsing, the associated function is then called to deal with the 
request.

These command functions have four generic parameters supplied by the 
internal parser.

a. aClient* cptr - pointer to the aClient structure of the _local_ client 
   from which the message originated. This client is guaranteed to have an 
   open socket. Can either be a local client, or a local server link. 
   However, the message can originate from a remote client/server, in 
   which case cptr would be the uplink.

b. aClient* sptr - pointer to the source aClient structure from which the 
message originates, determined by the message prefix (if any). If no 
prefix is defined, or the client to which the prefix represents is not 
found, then (sptr == cptr).

   Guaranteed: i. (sptr->from == cptr, cptr->from == cptr)
              ii. MyConnect(sptr) <=> (sptr == cptr) e.g., sptr cannot be 
		  a local connection, unless it's actuall cptr.

c. int parc - number of variable parameter strings supplied (if zero, parv 
   is allowed to be NULL)

d. char *parv[] - NULL-terminated list of parameter pointers, parv[0] is 
   the sender prefix, or empty string if not present.

   parv[parc - 1]: pointers to additional parameters supplied
   parv[parc]: _always_ NULL
   parv[0] to parv[parc - 1] are guaranteed to be non-NULL pointers.

Using the previous examples of OPER, an example of the OPER command 
function is below. The function type is an integer, and should return 0. 
If for any reason the function calls exit_client(), the return value of 
exit_client() should be returned.

int m_oper(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	/* Blah blah blah */
	return 0;
}

3. Command* register_command(Module*, msg_ptr*, int (*)())

This is the Command API call that will actually register the command 
within ircd, so it can be used. This should be called from within 
MOD_LOAD, and will return a pointer to the created Command structure on 
success, or NULL on failure. It requires three parameters:

a. pointer to the Module struct from which the command is originating.
b. pointer to the msg_ptr struct relating to the command.
c. the function to associate with the command, of 'int' type.

Again, using our trusty OPER examples from above, the following could be 
used to register the OPER command.

Command *c_oper = register_command(&MOD_HEADER(m_oper), &CMD_OPER, m_oper);

End of document.
