]> jfr.im git - solanum.git/blob - modules/m_alias.c
m_alias: fix an assert
[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
35 static const char alias_desc[] = "Provides the system for services aliases";
36
37 static int _modinit(void);
38 static void _moddeinit(void);
39 static int reload_aliases(hook_data *);
40 static void m_alias(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
41
42 mapi_hfn_list_av1 alias_hfnlist[] = {
43 { "rehash", (hookfn)reload_aliases },
44 { NULL, NULL },
45 };
46
47 DECLARE_MODULE_AV2(alias, _modinit, _moddeinit, NULL, NULL, alias_hfnlist, NULL, NULL, alias_desc);
48
49 static rb_dlink_list alias_messages;
50 static const struct MessageEntry alias_msgtab[] =
51 {{m_alias, 2}, {m_alias, 2}, mg_ignore, mg_ignore, mg_ignore, {m_alias, 2}};
52
53 static inline void
54 create_aliases(void)
55 {
56 rb_dictionary_iter iter;
57 struct alias_entry *alias;
58
59 s_assert(rb_dlink_list_length(&alias_messages) == 0);
60
61 RB_DICTIONARY_FOREACH(alias, &iter, alias_dict)
62 {
63 struct Message *message = rb_malloc(sizeof(struct Message));
64
65 message->cmd = alias->name;
66 memcpy(message->handlers, alias_msgtab, sizeof(alias_msgtab));
67
68 mod_add_cmd(message);
69 rb_dlinkAddAlloc(message, &alias_messages);
70 }
71 }
72
73 static inline void
74 destroy_aliases(void)
75 {
76 rb_dlink_node *ptr, *nptr;
77
78 RB_DLINK_FOREACH_SAFE(ptr, nptr, alias_messages.head)
79 {
80 mod_del_cmd((struct Message *)ptr->data);
81 rb_free(ptr->data);
82 rb_dlinkDestroy(ptr, &alias_messages);
83 }
84 }
85
86 static int
87 _modinit(void)
88 {
89 create_aliases();
90 return 0;
91 }
92
93 static void
94 _moddeinit(void)
95 {
96 destroy_aliases();
97 }
98
99 static int
100 reload_aliases(hook_data *data)
101 {
102 destroy_aliases(); /* Clear old aliases */
103 create_aliases();
104 return 0;
105 }
106
107 /* The below was mostly taken from the old do_alias */
108 static void
109 m_alias(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
110 {
111 struct Client *target_p;
112 struct alias_entry *aptr = rb_dictionary_retrieve(alias_dict, msgbuf->cmd);
113 char *p;
114
115 if(aptr == NULL)
116 {
117 /* This shouldn't happen... */
118 if(IsPerson(client_p))
119 sendto_one(client_p, form_str(ERR_UNKNOWNCOMMAND),
120 me.name, client_p->name, msgbuf->cmd);
121
122 return;
123 }
124 else if(parc < 2)
125 {
126 sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
127 me.name,
128 EmptyString(client_p->name) ? "*" : client_p->name,
129 msgbuf->cmd);
130 return;
131 }
132
133 if(!IsFloodDone(client_p) && client_p->localClient->receiveM > 20)
134 flood_endgrace(client_p);
135
136 p = strchr(aptr->target, '@');
137 if(p != NULL)
138 {
139 /* user@server */
140 target_p = find_server(NULL, p + 1);
141 if(target_p != NULL && IsMe(target_p))
142 target_p = NULL;
143 }
144 else
145 {
146 /* nick, must be +S */
147 target_p = find_named_person(aptr->target);
148 if(target_p != NULL && !IsService(target_p))
149 target_p = NULL;
150 }
151
152 if(target_p == NULL)
153 {
154 sendto_one_numeric(client_p, ERR_SERVICESDOWN, form_str(ERR_SERVICESDOWN), aptr->target);
155 return;
156 }
157
158 if(EmptyString(parv[1]))
159 {
160 sendto_one(client_p, form_str(ERR_NOTEXTTOSEND), me.name, target_p->name);
161 return;
162 }
163
164 /* increment the hitcounter on this alias */
165 aptr->hits++;
166
167 sendto_one(target_p, ":%s PRIVMSG %s :%s",
168 get_id(client_p, target_p),
169 p != NULL ? aptr->target : get_id(target_p, target_p),
170 parv[1]);
171 }