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