]> jfr.im git - solanum.git/blob - modules/m_monitor.c
extensions/invite_notify: make the NOTICE optional, configurable
[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 rb_dlink_node *prev_head, *ptr;
72 struct Client *target_p;
73 struct monitor *monptr;
74 const char *name;
75 char *tmp;
76 char *p;
77
78 prev_head = client_p->localClient->monitor_list.head;
79 tmp = LOCAL_COPY(nicks);
80
81 for(name = rb_strtok_r(tmp, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
82 {
83 if(EmptyString(name) || strlen(name) > NICKLEN-1)
84 continue;
85
86 if(rb_dlink_list_length(&client_p->localClient->monitor_list) >=
87 (unsigned long)ConfigFileEntry.max_monitor)
88 {
89 break;
90 }
91
92 if (!clean_nick(name, 0))
93 continue;
94
95 monptr = find_monitor(name, 1);
96
97 /* already monitoring this nick */
98 if(rb_dlinkFind(client_p, &monptr->users))
99 continue;
100
101 rb_dlinkAddAlloc(client_p, &monptr->users);
102 rb_dlinkAddAlloc(monptr, &client_p->localClient->monitor_list);
103 }
104
105 send_multiline_init(client_p, ",", form_str(RPL_MONONLINE),
106 me.name,
107 client_p->name,
108 "");
109
110 if (prev_head != NULL)
111 prev_head = prev_head->prev;
112 else
113 prev_head = client_p->localClient->monitor_list.tail;
114
115 RB_DLINK_FOREACH_PREV(ptr, prev_head)
116 {
117 monptr = ptr->data;
118 target_p = find_named_person(monptr->name);
119
120 if (target_p != NULL)
121 {
122 send_multiline_item(client_p, "%s!%s@%s",
123 target_p->name,
124 target_p->username,
125 target_p->host);
126 }
127 }
128
129 send_multiline_fini(client_p, NULL);
130
131 send_multiline_init(client_p, ",", form_str(RPL_MONOFFLINE),
132 me.name,
133 client_p->name,
134 "");
135
136 RB_DLINK_FOREACH_PREV(ptr, prev_head)
137 {
138 monptr = ptr->data;
139
140 if (find_named_person(monptr->name) == NULL)
141 {
142 send_multiline_item(client_p, "%s", monptr->name);
143 }
144 }
145
146 send_multiline_fini(client_p, NULL);
147
148 if (name)
149 {
150 char buf[400];
151
152 if (p)
153 snprintf(buf, sizeof buf, "%s,%s", name, p);
154 else
155 snprintf(buf, sizeof buf, "%s", name);
156
157 sendto_one(client_p, form_str(ERR_MONLISTFULL),
158 me.name,
159 client_p->name,
160 ConfigFileEntry.max_monitor,
161 buf);
162 }
163 }
164
165 static void
166 del_monitor(struct Client *client_p, const char *nicks)
167 {
168 struct monitor *monptr;
169 const char *name;
170 char *tmp;
171 char *p;
172
173 if(!rb_dlink_list_length(&client_p->localClient->monitor_list))
174 return;
175
176 tmp = LOCAL_COPY(nicks);
177
178 for(name = rb_strtok_r(tmp, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
179 {
180 if(EmptyString(name))
181 continue;
182
183 /* not monitored */
184 if((monptr = find_monitor(name, 0)) == NULL)
185 continue;
186
187 rb_dlinkFindDestroy(client_p, &monptr->users);
188 rb_dlinkFindDestroy(monptr, &client_p->localClient->monitor_list);
189
190 free_monitor(monptr);
191 }
192 }
193
194 static void
195 list_monitor(struct Client *client_p)
196 {
197 struct monitor *monptr;
198 rb_dlink_node *ptr;
199
200 if(!rb_dlink_list_length(&client_p->localClient->monitor_list))
201 {
202 sendto_one(client_p, form_str(RPL_ENDOFMONLIST),
203 me.name, client_p->name);
204 return;
205 }
206
207 send_multiline_init(client_p, ",", form_str(RPL_MONLIST),
208 me.name,
209 client_p->name,
210 "");
211
212 RB_DLINK_FOREACH(ptr, client_p->localClient->monitor_list.head)
213 {
214 monptr = ptr->data;
215
216 send_multiline_item(client_p, "%s", monptr->name);
217 }
218
219 send_multiline_fini(client_p, NULL);
220 sendto_one(client_p, form_str(RPL_ENDOFMONLIST),
221 me.name, client_p->name);
222 }
223
224 static void
225 show_monitor_status(struct Client *client_p)
226 {
227 struct Client *target_p;
228 struct monitor *monptr;
229 rb_dlink_node *ptr;
230
231 send_multiline_init(client_p, ",", form_str(RPL_MONONLINE),
232 me.name,
233 client_p->name,
234 "");
235
236 RB_DLINK_FOREACH(ptr, client_p->localClient->monitor_list.head)
237 {
238 monptr = ptr->data;
239 target_p = find_named_person(monptr->name);
240
241 if (target_p != NULL)
242 {
243 send_multiline_item(client_p, "%s!%s@%s",
244 target_p->name,
245 target_p->username,
246 target_p->host);
247 }
248 }
249
250 send_multiline_fini(client_p, NULL);
251
252 send_multiline_init(client_p, ",", form_str(RPL_MONOFFLINE),
253 me.name,
254 client_p->name,
255 "");
256
257 RB_DLINK_FOREACH(ptr, client_p->localClient->monitor_list.head)
258 {
259 monptr = ptr->data;
260
261 if (find_named_person(monptr->name) == NULL)
262 {
263 send_multiline_item(client_p, "%s", monptr->name);
264 }
265 }
266
267 send_multiline_fini(client_p, NULL);
268 }
269
270 static void
271 m_monitor(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
272 {
273 switch(parv[1][0])
274 {
275 case '+':
276 if(parc < 3 || EmptyString(parv[2]))
277 {
278 sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
279 me.name, source_p->name, "MONITOR");
280 return;
281 }
282
283 add_monitor(source_p, parv[2]);
284 break;
285 case '-':
286 if(parc < 3 || EmptyString(parv[2]))
287 {
288 sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
289 me.name, source_p->name, "MONITOR");
290 return;
291 }
292
293 del_monitor(source_p, parv[2]);
294 break;
295
296 case 'C':
297 case 'c':
298 clear_monitor(source_p);
299 break;
300
301 case 'L':
302 case 'l':
303 list_monitor(source_p);
304 break;
305
306 case 'S':
307 case 's':
308 show_monitor_status(source_p);
309 break;
310
311 default:
312 break;
313 }
314 }