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