]> jfr.im git - solanum.git/blob - modules/m_alias.c
Replace RPL_WHOISTEXT(337) with RPL_WHOISSPECIAL(320) (#419)
[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 void reload_aliases(void *);
41 static void m_alias(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
42
43 mapi_hfn_list_av1 alias_hfnlist[] = {
44 { "rehash", 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 void
104 reload_aliases(void *data)
105 {
106 destroy_aliases(); /* Clear old aliases */
107 create_aliases();
108 }
109
110 /* The below was mostly taken from the old do_alias */
111 static void
112 m_alias(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
113 {
114 struct Client *target_p;
115 struct alias_entry *aptr = rb_dictionary_retrieve(alias_dict, msgbuf->cmd);
116 char *p;
117
118 if(aptr == NULL)
119 {
120 /* This shouldn't happen... */
121 if(IsPerson(client_p))
122 sendto_one(client_p, form_str(ERR_UNKNOWNCOMMAND),
123 me.name, client_p->name, msgbuf->cmd);
124
125 return;
126 }
127
128 if(!IsFloodDone(client_p) && client_p->localClient->receiveM > 20)
129 flood_endgrace(client_p);
130
131 p = strchr(aptr->target, '@');
132 if(p != NULL)
133 {
134 /* user@server */
135 target_p = find_server(NULL, p + 1);
136 if(target_p != NULL && IsMe(target_p))
137 target_p = NULL;
138 }
139 else
140 {
141 /* nick, must be +S */
142 target_p = find_named_person(aptr->target);
143 if(target_p != NULL && !IsService(target_p))
144 target_p = NULL;
145 }
146
147 if(target_p == NULL)
148 {
149 sendto_one_numeric(client_p, ERR_SERVICESDOWN, form_str(ERR_SERVICESDOWN), aptr->target);
150 return;
151 }
152
153 msgbuf_reconstruct_tail(msgbuf, 1);
154 if(EmptyString(parv[1]))
155 {
156 sendto_one(client_p, form_str(ERR_NOTEXTTOSEND), me.name, target_p->name);
157 return;
158 }
159
160 sendto_one(target_p, ":%s PRIVMSG %s :%s",
161 get_id(client_p, target_p),
162 p != NULL ? aptr->target : get_id(target_p, target_p),
163 parv[1]);
164 }