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