]> jfr.im git - solanum.git/blob - modules/m_alias.c
Merge pull request #345 from edk0/alias
[solanum.git] / modules / m_alias.c
1 /* modules/m_alias.c - main module for aliases
2 * Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
7 *
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 */
20
21 #include "stdinc.h"
22 #include "client.h"
23 #include "parse.h"
24 #include "msg.h"
25 #include "modules.h"
26 #include "s_conf.h"
27 #include "s_serv.h"
28 #include "hash.h"
29 #include "ircd.h"
30 #include "match.h"
31 #include "numeric.h"
32 #include "send.h"
33 #include "packet.h"
34 #include "s_assert.h"
35
36 static const char alias_desc[] = "Provides the system for services aliases";
37
38 static int _modinit(void);
39 static void _moddeinit(void);
40 static int reload_aliases(hook_data *);
41 static void m_alias(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
42
43 mapi_hfn_list_av1 alias_hfnlist[] = {
44 { "rehash", (hookfn)reload_aliases },
45 { NULL, NULL },
46 };
47
48 DECLARE_MODULE_AV2(alias, _modinit, _moddeinit, NULL, NULL, alias_hfnlist, NULL, NULL, alias_desc);
49
50 static rb_dlink_list alias_messages;
51 static const struct MessageEntry alias_msgtab[] =
52 {{m_alias, 2}, {m_alias, 2}, mg_ignore, mg_ignore, mg_ignore, {m_alias, 2}};
53
54 static inline void
55 create_aliases(void)
56 {
57 rb_dictionary_iter iter;
58 struct alias_entry *alias;
59
60 s_assert(rb_dlink_list_length(&alias_messages) == 0);
61
62 RB_DICTIONARY_FOREACH(alias, &iter, alias_dict)
63 {
64 struct Message *message = rb_malloc(sizeof(*message) + strlen(alias->name) + 1);
65 char *cmd = (char*)message + sizeof(*message);
66
67 /* copy the alias name as it will be freed early on a rehash */
68 strcpy(cmd, alias->name);
69 message->cmd = cmd;
70 memcpy(message->handlers, alias_msgtab, sizeof(alias_msgtab));
71
72 mod_add_cmd(message);
73 rb_dlinkAddAlloc(message, &alias_messages);
74 }
75 }
76
77 static inline void
78 destroy_aliases(void)
79 {
80 rb_dlink_node *ptr, *nptr;
81
82 RB_DLINK_FOREACH_SAFE(ptr, nptr, alias_messages.head)
83 {
84 mod_del_cmd((struct Message *)ptr->data);
85 rb_free(ptr->data);
86 rb_dlinkDestroy(ptr, &alias_messages);
87 }
88 }
89
90 static int
91 _modinit(void)
92 {
93 create_aliases();
94 return 0;
95 }
96
97 static void
98 _moddeinit(void)
99 {
100 destroy_aliases();
101 }
102
103 static int
104 reload_aliases(hook_data *data)
105 {
106 destroy_aliases(); /* Clear old aliases */
107 create_aliases();
108 return 0;
109 }
110
111 /* The below was mostly taken from the old do_alias */
112 static void
113 m_alias(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
114 {
115 struct Client *target_p;
116 struct alias_entry *aptr = rb_dictionary_retrieve(alias_dict, msgbuf->cmd);
117 char *p;
118
119 if(aptr == NULL)
120 {
121 /* This shouldn't happen... */
122 if(IsPerson(client_p))
123 sendto_one(client_p, form_str(ERR_UNKNOWNCOMMAND),
124 me.name, client_p->name, msgbuf->cmd);
125
126 return;
127 }
128
129 if(!IsFloodDone(client_p) && client_p->localClient->receiveM > 20)
130 flood_endgrace(client_p);
131
132 p = strchr(aptr->target, '@');
133 if(p != NULL)
134 {
135 /* user@server */
136 target_p = find_server(NULL, p + 1);
137 if(target_p != NULL && IsMe(target_p))
138 target_p = NULL;
139 }
140 else
141 {
142 /* nick, must be +S */
143 target_p = find_named_person(aptr->target);
144 if(target_p != NULL && !IsService(target_p))
145 target_p = NULL;
146 }
147
148 if(target_p == NULL)
149 {
150 sendto_one_numeric(client_p, ERR_SERVICESDOWN, form_str(ERR_SERVICESDOWN), aptr->target);
151 return;
152 }
153
154 msgbuf_reconstruct_tail(msgbuf, 1);
155 if(EmptyString(parv[1]))
156 {
157 sendto_one(client_p, form_str(ERR_NOTEXTTOSEND), me.name, target_p->name);
158 return;
159 }
160
161 sendto_one(target_p, ":%s PRIVMSG %s :%s",
162 get_id(client_p, target_p),
163 p != NULL ? aptr->target : get_id(target_p, target_p),
164 parv[1]);
165 }