]> jfr.im git - solanum.git/blame - modules/m_monitor.c
Add .travis.yml
[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.
29 *
30 * $Id: m_monitor.c 312 2005-11-07 10:47:33Z jilles $
31 */
32
33#include "stdinc.h"
34#include "client.h"
35#include "msg.h"
36#include "parse.h"
37#include "modules.h"
38#include "monitor.h"
39#include "numeric.h"
40#include "s_conf.h"
41#include "send.h"
439bf4db 42#include "supported.h"
5f8fb56d 43
439bf4db
JT
44static int monitor_init(void);
45static void monitor_deinit(void);
5f8fb56d
AW
46static int m_monitor(struct Client *, struct Client *, int, const char **);
47
48struct Message monitor_msgtab = {
49 "MONITOR", 0, 0, 0, MFLG_SLOW,
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 };
439bf4db
JT
54DECLARE_MODULE_AV1(monitor, monitor_init, monitor_deinit, monitor_clist, NULL, NULL, "$Revision: 312 $");
55
56static int monitor_init(void)
57{
58 add_isupport("MONITOR", isupport_intptr, &ConfigFileEntry.max_monitor);
59 return 0;
60}
61
62static void monitor_deinit(void)
63{
64 delete_isupport("MONITOR");
65}
5f8fb56d
AW
66
67static void
68add_monitor(struct Client *client_p, const char *nicks)
69{
70 char onbuf[BUFSIZE], offbuf[BUFSIZE];
71 struct Client *target_p;
72 struct monitor *monptr;
73 const char *name;
74 char *tmp;
75 char *p;
76 char *onptr, *offptr;
77 int mlen, arglen;
78 int cur_onlen, cur_offlen;
79
80 /* these two are same length, just diff numeric */
81 cur_offlen = cur_onlen = mlen = sprintf(onbuf, form_str(RPL_MONONLINE),
82 me.name, client_p->name, "");
83 sprintf(offbuf, form_str(RPL_MONOFFLINE),
84 me.name, client_p->name, "");
85
86 onptr = onbuf + mlen;
87 offptr = offbuf + mlen;
88
89 tmp = LOCAL_COPY(nicks);
90
91 for(name = rb_strtok_r(tmp, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
92 {
93 if(EmptyString(name) || strlen(name) > NICKLEN-1)
94 continue;
95
96 if(rb_dlink_list_length(&client_p->localClient->monitor_list) >=
97 (unsigned long)ConfigFileEntry.max_monitor)
98 {
99 char buf[100];
100
101 if(cur_onlen != mlen)
102 sendto_one(client_p, "%s", onbuf);
103 if(cur_offlen != mlen)
104 sendto_one(client_p, "%s", offbuf);
105
106 if(p)
107 rb_snprintf(buf, sizeof(buf), "%s,%s", name, p);
108 else
109 rb_snprintf(buf, sizeof(buf), "%s", name);
110
111 sendto_one(client_p, form_str(ERR_MONLISTFULL),
112 me.name, client_p->name,
113 ConfigFileEntry.max_monitor, buf);
114 return;
115 }
116
2d28539c 117 if (!clean_nick(name, 0))
413c61aa
AC
118 continue;
119
5f8fb56d
AW
120 monptr = find_monitor(name, 1);
121
122 /* already monitoring this nick */
123 if(rb_dlinkFind(client_p, &monptr->users))
124 continue;
125
126 rb_dlinkAddAlloc(client_p, &monptr->users);
127 rb_dlinkAddAlloc(monptr, &client_p->localClient->monitor_list);
128
129 if((target_p = find_named_person(name)) != NULL)
130 {
131 if(cur_onlen + strlen(target_p->name) +
132 strlen(target_p->username) + strlen(target_p->host) + 3 >= BUFSIZE-3)
133 {
134 sendto_one(client_p, "%s", onbuf);
135 cur_onlen = mlen;
136 onptr = onbuf + mlen;
137 }
138
139 if(cur_onlen != mlen)
140 {
141 *onptr++ = ',';
142 cur_onlen++;
143 }
144
145 arglen = sprintf(onptr, "%s!%s@%s",
146 target_p->name, target_p->username,
147 target_p->host);
148 onptr += arglen;
149 cur_onlen += arglen;
150 }
151 else
152 {
153 if(cur_offlen + strlen(name) + 1 >= BUFSIZE-3)
154 {
155 sendto_one(client_p, "%s", offbuf);
156 cur_offlen = mlen;
157 offptr = offbuf + mlen;
158 }
159
160 if(cur_offlen != mlen)
161 {
162 *offptr++ = ',';
163 cur_offlen++;
164 }
165
166 arglen = sprintf(offptr, "%s", name);
167 offptr += arglen;
168 cur_offlen += arglen;
169 }
170 }
171
172 if(cur_onlen != mlen)
173 sendto_one(client_p, "%s", onbuf);
174 if(cur_offlen != mlen)
175 sendto_one(client_p, "%s", offbuf);
176}
177
178static void
179del_monitor(struct Client *client_p, const char *nicks)
180{
181 struct monitor *monptr;
182 const char *name;
183 char *tmp;
184 char *p;
185
186 if(!rb_dlink_list_length(&client_p->localClient->monitor_list))
187 return;
188
189 tmp = LOCAL_COPY(nicks);
190
191 for(name = rb_strtok_r(tmp, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
192 {
193 if(EmptyString(name))
194 continue;
195
196 /* not monitored */
197 if((monptr = find_monitor(name, 0)) == NULL)
198 continue;
199
200 rb_dlinkFindDestroy(client_p, &monptr->users);
201 rb_dlinkFindDestroy(monptr, &client_p->localClient->monitor_list);
202
203 free_monitor(monptr);
204 }
205}
206
207static void
208list_monitor(struct Client *client_p)
209{
210 char buf[BUFSIZE];
211 struct monitor *monptr;
212 char *nbuf;
213 rb_dlink_node *ptr;
214 int mlen, arglen, cur_len;
215
216 if(!rb_dlink_list_length(&client_p->localClient->monitor_list))
217 {
218 sendto_one(client_p, form_str(RPL_ENDOFMONLIST),
219 me.name, client_p->name);
220 return;
221 }
222
223 cur_len = mlen = sprintf(buf, form_str(RPL_MONLIST),
224 me.name, client_p->name, "");
225 nbuf = buf + mlen;
226
227 RB_DLINK_FOREACH(ptr, client_p->localClient->monitor_list.head)
228 {
229 monptr = ptr->data;
230
231 if(cur_len + strlen(monptr->name) + 1 >= BUFSIZE-3)
232 {
233 sendto_one(client_p, "%s", buf);
234 nbuf = buf + mlen;
235 cur_len = mlen;
236 }
237
238 if(cur_len != mlen)
239 {
240 *nbuf++ = ',';
241 cur_len++;
242 }
243
244 arglen = sprintf(nbuf, "%s", monptr->name);
245 cur_len += arglen;
246 nbuf += arglen;
247 }
248
249 sendto_one(client_p, "%s", buf);
250 sendto_one(client_p, form_str(RPL_ENDOFMONLIST),
251 me.name, client_p->name);
252}
253
254static void
255show_monitor_status(struct Client *client_p)
256{
257 char onbuf[BUFSIZE], offbuf[BUFSIZE];
258 struct Client *target_p;
259 struct monitor *monptr;
260 char *onptr, *offptr;
261 int cur_onlen, cur_offlen;
262 int mlen, arglen;
263 rb_dlink_node *ptr;
264
265 mlen = cur_onlen = sprintf(onbuf, form_str(RPL_MONONLINE),
266 me.name, client_p->name, "");
267 cur_offlen = sprintf(offbuf, form_str(RPL_MONOFFLINE),
268 me.name, client_p->name, "");
269
270 onptr = onbuf + mlen;
271 offptr = offbuf + mlen;
272
273 RB_DLINK_FOREACH(ptr, client_p->localClient->monitor_list.head)
274 {
275 monptr = ptr->data;
276
277 if((target_p = find_named_person(monptr->name)) != NULL)
278 {
279 if(cur_onlen + strlen(target_p->name) +
280 strlen(target_p->username) + strlen(target_p->host) + 3 >= BUFSIZE-3)
281 {
282 sendto_one(client_p, "%s", onbuf);
283 cur_onlen = mlen;
284 onptr = onbuf + mlen;
285 }
286
287 if(cur_onlen != mlen)
288 {
289 *onptr++ = ',';
290 cur_onlen++;
291 }
292
293 arglen = sprintf(onptr, "%s!%s@%s",
294 target_p->name, target_p->username,
295 target_p->host);
296 onptr += arglen;
297 cur_onlen += arglen;
298 }
299 else
300 {
301 if(cur_offlen + strlen(monptr->name) + 1 >= BUFSIZE-3)
302 {
303 sendto_one(client_p, "%s", offbuf);
304 cur_offlen = mlen;
305 offptr = offbuf + mlen;
306 }
307
308 if(cur_offlen != mlen)
309 {
310 *offptr++ = ',';
311 cur_offlen++;
312 }
313
314 arglen = sprintf(offptr, "%s", monptr->name);
315 offptr += arglen;
316 cur_offlen += arglen;
317 }
318 }
319
320 if(cur_onlen != mlen)
321 sendto_one(client_p, "%s", onbuf);
322 if(cur_offlen != mlen)
323 sendto_one(client_p, "%s", offbuf);
324}
325
326static int
327m_monitor(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
328{
329 switch(parv[1][0])
330 {
331 case '+':
332 if(parc < 3 || EmptyString(parv[2]))
333 {
334 sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
335 me.name, source_p->name, "MONITOR");
336 return 0;
337 }
338
339 add_monitor(source_p, parv[2]);
340 break;
341 case '-':
342 if(parc < 3 || EmptyString(parv[2]))
343 {
344 sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
345 me.name, source_p->name, "MONITOR");
346 return 0;
347 }
348
349 del_monitor(source_p, parv[2]);
350 break;
351
352 case 'C':
353 case 'c':
354 clear_monitor(source_p);
355 break;
356
357 case 'L':
358 case 'l':
359 list_monitor(source_p);
360 break;
361
362 case 'S':
363 case 's':
364 show_monitor_status(source_p);
365 break;
366
367 default:
368 break;
369 }
370
371 return 0;
372}
373