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