]> jfr.im git - solanum.git/blame - modules/m_monitor.c
Kill Travis
[solanum.git] / modules / m_monitor.c
CommitLineData
5f8fb56d
AW
1/* modules/m_monitor.c
2 *
3 * Copyright (C) 2005 Lee Hardy <lee@leeh.co.uk>
4 * Copyright (C) 2005 ircd-ratbox development team
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * 1.Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2.Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3.The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
5f8fb56d
AW
29 */
30
31#include "stdinc.h"
32#include "client.h"
33#include "msg.h"
34#include "parse.h"
35#include "modules.h"
36#include "monitor.h"
37#include "numeric.h"
38#include "s_conf.h"
39#include "send.h"
439bf4db 40#include "supported.h"
5f8fb56d 41
eeabf33a
EM
42static const char monitor_desc[] = "Provides the MONITOR facility for tracking user signon and signoff";
43
439bf4db
JT
44static int monitor_init(void);
45static void monitor_deinit(void);
3c7d6fcc 46static void m_monitor(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
5f8fb56d
AW
47
48struct Message monitor_msgtab = {
7baa37a9 49 "MONITOR", 0, 0, 0, 0,
5f8fb56d
AW
50 {mg_unreg, {m_monitor, 2}, mg_ignore, mg_ignore, mg_ignore, {m_monitor, 2}}
51};
52
53mapi_clist_av1 monitor_clist[] = { &monitor_msgtab, NULL };
f5ebe640 54
f5ebe640 55DECLARE_MODULE_AV2(monitor, monitor_init, monitor_deinit, monitor_clist, NULL, NULL, NULL, NULL, monitor_desc);
439bf4db
JT
56
57static int monitor_init(void)
58{
59 add_isupport("MONITOR", isupport_intptr, &ConfigFileEntry.max_monitor);
60 return 0;
61}
62
63static void monitor_deinit(void)
64{
65 delete_isupport("MONITOR");
66}
5f8fb56d
AW
67
68static void
69add_monitor(struct Client *client_p, const char *nicks)
70{
aacd07a2 71 rb_dlink_node *prev_head, *ptr;
5f8fb56d
AW
72 struct Client *target_p;
73 struct monitor *monptr;
74 const char *name;
75 char *tmp;
76 char *p;
5f8fb56d 77
aacd07a2 78 prev_head = client_p->localClient->monitor_list.head;
5f8fb56d
AW
79 tmp = LOCAL_COPY(nicks);
80
81 for(name = rb_strtok_r(tmp, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
82 {
83 if(EmptyString(name) || strlen(name) > NICKLEN-1)
84 continue;
85
86 if(rb_dlink_list_length(&client_p->localClient->monitor_list) >=
87 (unsigned long)ConfigFileEntry.max_monitor)
88 {
aacd07a2 89 break;
5f8fb56d
AW
90 }
91
2d28539c 92 if (!clean_nick(name, 0))
413c61aa
AC
93 continue;
94
5f8fb56d
AW
95 monptr = find_monitor(name, 1);
96
97 /* already monitoring this nick */
98 if(rb_dlinkFind(client_p, &monptr->users))
99 continue;
100
101 rb_dlinkAddAlloc(client_p, &monptr->users);
102 rb_dlinkAddAlloc(monptr, &client_p->localClient->monitor_list);
aacd07a2 103 }
5f8fb56d 104
aacd07a2
DF
105 send_multiline_init(client_p, ",", form_str(RPL_MONONLINE),
106 me.name,
107 client_p->name,
108 "");
5f8fb56d 109
aacd07a2
DF
110 if (prev_head != NULL)
111 prev_head = prev_head->prev;
112 else
113 prev_head = client_p->localClient->monitor_list.tail;
114
115 RB_DLINK_FOREACH_PREV(ptr, prev_head)
116 {
117 monptr = ptr->data;
118 target_p = find_named_person(monptr->name);
5f8fb56d 119
aacd07a2
DF
120 if (target_p != NULL)
121 {
122 send_multiline_item(client_p, "%s!%s@%s",
123 target_p->name,
124 target_p->username,
5f8fb56d 125 target_p->host);
5f8fb56d 126 }
aacd07a2 127 }
5f8fb56d 128
aacd07a2
DF
129 send_multiline_fini(client_p, NULL);
130
131 send_multiline_init(client_p, ",", form_str(RPL_MONOFFLINE),
132 me.name,
133 client_p->name,
134 "");
135
136 RB_DLINK_FOREACH_PREV(ptr, prev_head)
137 {
138 monptr = ptr->data;
5f8fb56d 139
aacd07a2
DF
140 if (find_named_person(monptr->name) == NULL)
141 {
142 send_multiline_item(client_p, "%s", monptr->name);
5f8fb56d
AW
143 }
144 }
145
aacd07a2
DF
146 send_multiline_fini(client_p, NULL);
147
148 if (name)
149 {
150 char buf[400];
151
152 if (p)
153 snprintf(buf, sizeof buf, "%s,%s", name, p);
154 else
155 snprintf(buf, sizeof buf, "%s", name);
156
157 sendto_one(client_p, form_str(ERR_MONLISTFULL),
158 me.name,
159 client_p->name,
160 ConfigFileEntry.max_monitor,
161 buf);
162 }
5f8fb56d
AW
163}
164
165static void
166del_monitor(struct Client *client_p, const char *nicks)
167{
168 struct monitor *monptr;
169 const char *name;
170 char *tmp;
171 char *p;
172
173 if(!rb_dlink_list_length(&client_p->localClient->monitor_list))
174 return;
175
176 tmp = LOCAL_COPY(nicks);
177
178 for(name = rb_strtok_r(tmp, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
179 {
180 if(EmptyString(name))
181 continue;
182
183 /* not monitored */
184 if((monptr = find_monitor(name, 0)) == NULL)
185 continue;
186
187 rb_dlinkFindDestroy(client_p, &monptr->users);
188 rb_dlinkFindDestroy(monptr, &client_p->localClient->monitor_list);
189
190 free_monitor(monptr);
191 }
192}
193
194static void
195list_monitor(struct Client *client_p)
196{
5f8fb56d 197 struct monitor *monptr;
5f8fb56d 198 rb_dlink_node *ptr;
5f8fb56d
AW
199
200 if(!rb_dlink_list_length(&client_p->localClient->monitor_list))
201 {
202 sendto_one(client_p, form_str(RPL_ENDOFMONLIST),
203 me.name, client_p->name);
204 return;
205 }
206
aacd07a2
DF
207 send_multiline_init(client_p, ",", form_str(RPL_MONLIST),
208 me.name,
209 client_p->name,
210 "");
5f8fb56d
AW
211
212 RB_DLINK_FOREACH(ptr, client_p->localClient->monitor_list.head)
213 {
214 monptr = ptr->data;
215
aacd07a2 216 send_multiline_item(client_p, "%s", monptr->name);
5f8fb56d
AW
217 }
218
aacd07a2 219 send_multiline_fini(client_p, NULL);
5f8fb56d
AW
220 sendto_one(client_p, form_str(RPL_ENDOFMONLIST),
221 me.name, client_p->name);
222}
223
224static void
225show_monitor_status(struct Client *client_p)
226{
5f8fb56d
AW
227 struct Client *target_p;
228 struct monitor *monptr;
5f8fb56d
AW
229 rb_dlink_node *ptr;
230
aacd07a2
DF
231 send_multiline_init(client_p, ",", form_str(RPL_MONONLINE),
232 me.name,
233 client_p->name,
234 "");
5f8fb56d
AW
235
236 RB_DLINK_FOREACH(ptr, client_p->localClient->monitor_list.head)
237 {
238 monptr = ptr->data;
aacd07a2 239 target_p = find_named_person(monptr->name);
5f8fb56d 240
aacd07a2 241 if (target_p != NULL)
5f8fb56d 242 {
aacd07a2
DF
243 send_multiline_item(client_p, "%s!%s@%s",
244 target_p->name,
245 target_p->username,
5f8fb56d 246 target_p->host);
5f8fb56d 247 }
aacd07a2 248 }
5f8fb56d 249
aacd07a2
DF
250 send_multiline_fini(client_p, NULL);
251
252 send_multiline_init(client_p, ",", form_str(RPL_MONOFFLINE),
253 me.name,
254 client_p->name,
255 "");
5f8fb56d 256
aacd07a2
DF
257 RB_DLINK_FOREACH(ptr, client_p->localClient->monitor_list.head)
258 {
259 monptr = ptr->data;
260
261 if (find_named_person(monptr->name) == NULL)
262 {
263 send_multiline_item(client_p, "%s", monptr->name);
5f8fb56d
AW
264 }
265 }
266
aacd07a2 267 send_multiline_fini(client_p, NULL);
5f8fb56d
AW
268}
269
3c7d6fcc 270static void
428ca87b 271m_monitor(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
5f8fb56d
AW
272{
273 switch(parv[1][0])
274 {
275 case '+':
276 if(parc < 3 || EmptyString(parv[2]))
277 {
278 sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
279 me.name, source_p->name, "MONITOR");
3c7d6fcc 280 return;
5f8fb56d
AW
281 }
282
283 add_monitor(source_p, parv[2]);
284 break;
285 case '-':
286 if(parc < 3 || EmptyString(parv[2]))
287 {
288 sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
289 me.name, source_p->name, "MONITOR");
3c7d6fcc 290 return;
5f8fb56d
AW
291 }
292
293 del_monitor(source_p, parv[2]);
294 break;
295
296 case 'C':
297 case 'c':
298 clear_monitor(source_p);
299 break;
300
301 case 'L':
302 case 'l':
303 list_monitor(source_p);
304 break;
305
306 case 'S':
307 case 's':
308 show_monitor_status(source_p);
309 break;
310
311 default:
312 break;
313 }
5f8fb56d 314}