From b663a8070f37e4dc7a9577f7e5c176ac63ca88f1 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 6 Apr 2016 07:27:50 -0500 Subject: [PATCH] Move alias handling into a dedicated module. Not yet tested, caveat emptor! Closes #166 --- ircd/parse.c | 66 ----------------- modules/Makefile.am | 1 + modules/m_alias.c | 170 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 66 deletions(-) create mode 100644 modules/m_alias.c diff --git a/ircd/parse.c b/ircd/parse.c index 738bb753f..e09dbe38e 100644 --- a/ircd/parse.c +++ b/ircd/parse.c @@ -48,7 +48,6 @@ static void cancel_clients(struct Client *, struct Client *); static void remove_unknown(struct Client *, const char *, char *); static void do_numeric(int, struct Client *, struct Client *, int, const char **); -static void do_alias(struct alias_entry *, struct Client *, char *); static int handle_command(struct Message *, struct MsgBuf *, struct Client *, struct Client *); @@ -137,24 +136,6 @@ parse(struct Client *client_p, char *pbuffer, char *bufend) /* no command or its encap only, error */ if(!mptr || !mptr->cmd) { - if (IsPerson(client_p)) - { - struct alias_entry *aptr = rb_dictionary_retrieve(alias_dict, msgbuf.cmd); - if (aptr != NULL) - { - if (msgbuf.n_para < 2) - { - sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS), - me.name, - EmptyString(client_p->name) ? "*" : client_p->name, - msgbuf.cmd); - return; - } - - do_alias(aptr, client_p, reconstruct_parv(msgbuf.n_para - 1, msgbuf.para + 1)); - return; - } - } if(IsPerson(from)) { sendto_one(from, form_str(ERR_UNKNOWNCOMMAND), @@ -525,53 +506,6 @@ do_numeric(int numeric, struct Client *client_p, struct Client *source_p, int pa numeric, chptr->chname, buffer); } -static void do_alias(struct alias_entry *aptr, struct Client *source_p, char *text) -{ - char *p; - struct Client *target_p; - - if (!IsFloodDone(source_p) && source_p->localClient->receiveM > 20) - flood_endgrace(source_p); - - p = strchr(aptr->target, '@'); - if (p != NULL) - { - /* user@server */ - target_p = find_server(NULL, p + 1); - if (target_p != NULL && IsMe(target_p)) - target_p = NULL; - } - else - { - /* nick, must be +S */ - target_p = find_named_person(aptr->target); - if (target_p != NULL && !IsService(target_p)) - target_p = NULL; - } - - if (target_p == NULL) - { - sendto_one_numeric(source_p, ERR_SERVICESDOWN, form_str(ERR_SERVICESDOWN), aptr->target); - return; - } - - if (text != NULL && *text == ':') - text++; - if (text == NULL || *text == '\0') - { - sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name); - return; - } - - /* increment the hitcounter on this alias */ - aptr->hits++; - - sendto_one(target_p, ":%s PRIVMSG %s :%s", - get_id(source_p, target_p), - p != NULL ? aptr->target : get_id(target_p, target_p), - text); -} - void m_not_oper(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { diff --git a/modules/Makefile.am b/modules/Makefile.am index 21f7aa65d..ed975134e 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -14,6 +14,7 @@ auto_load_mod_LTLIBRARIES = \ chm_noctcp.la \ m_accept.la \ m_admin.la \ + m_alias.la \ m_away.la \ m_cap.la \ m_capab.la \ diff --git a/modules/m_alias.c b/modules/m_alias.c new file mode 100644 index 000000000..2a5d01f0b --- /dev/null +++ b/modules/m_alias.c @@ -0,0 +1,170 @@ +/* modules/m_alias.c - main module for aliases + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "client.h" +#include "parse.h" +#include "msg.h" +#include "modules.h" +#include "s_conf.h" +#include "s_serv.h" +#include "hash.h" +#include "ircd.h" +#include "match.h" +#include "numeric.h" +#include "send.h" +#include "packet.h" + +static const char alias_desc[] = "Provides the system for services aliases"; + +static int _modinit(void); +static void _moddeinit(void); +static int reload_aliases(hook_data *); +static void m_alias(struct MsgBuf *, struct Client *, struct Client *, int, const char **); + +mapi_hfn_list_av1 alias_hfnlist[] = { + { "rehash", (hookfn)reload_aliases }, + { NULL, NULL }, +}; + +DECLARE_MODULE_AV2(alias, _modinit, _moddeinit, NULL, NULL, alias_hfnlist, NULL, NULL, alias_desc); + +static rb_dlink_list alias_messages; +static const struct MessageEntry alias_msgtab[] = + {{m_alias, 2}, {m_alias, 2}, mg_ignore, mg_ignore, mg_ignore, {m_alias, 2}}; + +static inline void +create_aliases(void) +{ + rb_dictionary_iter iter; + struct alias_entry *alias; + + s_assert(rb_dlink_list_length(alias_messages) > 0); + + RB_DICTIONARY_FOREACH(alias, &iter, alias_dict) + { + struct Message *message = rb_malloc(sizeof(struct Message)); + + message->cmd = alias->name; + memcpy(message->handlers, alias_msgtab, sizeof(alias_msgtab)); + + mod_add_cmd(message); + rb_dlinkAddAlloc(message, &alias_messages); + } +} + +static inline void +destroy_aliases(void) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, alias_messages.head) + { + mod_del_cmd((struct Message *)ptr->data); + rb_free(ptr->data); + rb_dlinkDestroy(ptr, &alias_messages); + } +} + +static int +_modinit(void) +{ + create_aliases(); + return 0; +} + +static void +_moddeinit(void) +{ + destroy_aliases(); +} + +static int +reload_aliases(hook_data *data __unused) +{ + destroy_aliases(); /* Clear old aliases */ + create_aliases(); + return 0; +} + +/* The below was mostly taken from the old do_alias */ +static void +m_alias(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p, int parc, const char **parv) +{ + struct Client *target_p; + struct alias_entry *aptr = rb_dictionary_retrieve(alias_dict, msgbuf->cmd); + char *p; + + if(aptr == NULL) + { + if(IsPerson(source_p)) + sendto_one(source_p, form_str(ERR_UNKNOWNCOMMAND), + me.name, source_p->name, msgbuf->cmd); + + return; + } + else if(parc < 2) + { + sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS), + me.name, + EmptyString(client_p->name) ? "*" : client_p->name, + msgbuf->cmd); + return; + } + + if(!IsFloodDone(source_p) && source_p->localClient->receiveM > 20) + flood_endgrace(source_p); + + p = strchr(aptr->target, '@'); + if(p != NULL) + { + /* user@server */ + target_p = find_server(NULL, p + 1); + if(target_p != NULL && IsMe(target_p)) + target_p = NULL; + } + else + { + /* nick, must be +S */ + target_p = find_named_person(aptr->target); + if(target_p != NULL && !IsService(target_p)) + target_p = NULL; + } + + if(target_p == NULL) + { + sendto_one_numeric(source_p, ERR_SERVICESDOWN, form_str(ERR_SERVICESDOWN), aptr->target); + return; + } + + if(*parv[1] == '\0') + { + sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name); + return; + } + + /* increment the hitcounter on this alias */ + aptr->hits++; + + sendto_one(target_p, ":%s PRIVMSG %s :%s", + get_id(source_p, target_p), + p != NULL ? aptr->target : get_id(target_p, target_p), + parv[1]); +}