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