ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_watch.c
Revision: 1230
Committed: Thu Sep 22 19:41:19 2011 UTC (15 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/m_watch.c
File size: 7449 byte(s)
Error occurred while calculating annotation data.
Log Message:
- cleanup module loader. Make module api more flexible

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * m_watch.c: Maintains notify list
4 *
5 * Copyright (C) 1997 Jukka Santala (Donwulff)
6 * Copyright (C) 2005 by the Hybrid Development Team.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 *
23 * $Id$
24 */
25
26 #include "stdinc.h"
27 #include "handlers.h"
28 #include "client.h"
29 #include "irc_string.h"
30 #include "sprintf_irc.h"
31 #include "ircd.h"
32 #include "numeric.h"
33 #include "s_conf.h"
34 #include "send.h"
35 #include "msg.h"
36 #include "parse.h"
37 #include "modules.h"
38 #include "s_user.h"
39 #include "watch.h"
40
41
42 /*
43 * RPL_NOWON - Online at the moment (Succesfully added to WATCH-list)
44 * RPL_NOWOFF - Offline at the moment (Succesfully added to WATCH-list)
45 * RPL_WATCHOFF - Succesfully removed from WATCH-list.
46 * ERR_TOOMANYWATCH - Take a guess :> Too many WATCH entries.
47 */
48 static void
49 show_watch(struct Client *client_p, const char *name,
50 unsigned int rpl1, unsigned int rpl2)
51 {
52 const struct Client *target_p = NULL;
53
54 if ((target_p = find_person(client_p, name)))
55 sendto_one(client_p, form_str(rpl1), me.name, client_p->name,
56 target_p->name, target_p->username,
57 target_p->host, target_p->lasttime);
58 else
59 sendto_one(client_p, form_str(rpl2), me.name, client_p->name,
60 name, "*", "*", 0);
61 }
62
63 /*
64 * m_watch()
65 *
66 * parv[0] = sender prefix
67 * parv[1] = watch options
68 */
69 static void
70 m_watch(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
71 {
72 dlink_node *ptr = NULL;
73 char *s = NULL;
74 char *p = NULL;
75 char *user;
76 char def[2] = "l";
77 unsigned int list_requested = 0;
78
79 /*
80 * Default to 'l' - list who's currently online
81 */
82 if (parc < 2)
83 parv[1] = def;
84
85 for (s = strtoken(&p, parv[1], ", "); s;
86 s = strtoken(&p, NULL, ", "))
87 {
88 if ((user = strchr(s, '!')))
89 *user++ = '\0'; /* Not used */
90
91 /*
92 * Prefix of "+", they want to add a name to their WATCH
93 * list.
94 */
95 if (*s == '+')
96 {
97 if (*(s + 1) != '\0')
98 {
99 if (dlink_list_length(&source_p->localClient->watches) >=
100 ConfigFileEntry.max_watch)
101 {
102 sendto_one(source_p, form_str(ERR_TOOMANYWATCH), me.name,
103 source_p->name, s + 1, ConfigFileEntry.max_watch);
104 continue;
105 }
106
107 watch_add_to_hash_table(s + 1, source_p);
108 }
109
110 show_watch(source_p, s + 1, RPL_NOWON, RPL_NOWOFF);
111 continue;
112 }
113
114 /*
115 * Prefix of "-", coward wants to remove somebody from their
116 * WATCH list. So do it. :-)
117 */
118 if (*s == '-')
119 {
120 watch_del_from_hash_table(s + 1, source_p);
121 show_watch(source_p, s + 1, RPL_WATCHOFF, RPL_WATCHOFF);
122 continue;
123 }
124
125 /*
126 * Fancy "C" or "c", they want to nuke their WATCH list and start
127 * over, so be it.
128 */
129 if (*s == 'C' || *s == 'c')
130 {
131 watch_del_watch_list(source_p);
132 continue;
133 }
134
135 /*
136 * Now comes the fun stuff, "S" or "s" returns a status report of
137 * their WATCH list. I imagine this could be CPU intensive if
138 * it's done alot, perhaps an auto-lag on this?
139 */
140 if (*s == 'S' || *s == 's')
141 {
142 char buf[IRCD_BUFSIZE] = { '\0' };
143 const struct Watch *anptr = NULL;
144 unsigned int count = 0;
145
146 if (list_requested & 0x1)
147 continue;
148
149 list_requested |= 0x1;
150
151 /*
152 * Send a list of how many users they have on their WATCH list
153 * and how many WATCH lists they are on.
154 */
155 if ((anptr = watch_find_hash(source_p->name)))
156 count = dlink_list_length(&anptr->watched_by);
157
158 sendto_one(source_p, form_str(RPL_WATCHSTAT),
159 me.name, source_p->name,
160 dlink_list_length(&source_p->localClient->watches), count);
161
162 /*
163 * Send a list of everybody in their WATCH list. Be careful
164 * not to buffer overflow.
165 */
166 if ((ptr = source_p->localClient->watches.head) == NULL)
167 {
168 sendto_one(source_p, form_str(RPL_ENDOFWATCHLIST),
169 me.name, source_p->name, *s);
170 continue;
171 }
172
173 anptr = ptr->data;
174 strlcpy(buf, anptr->nick, sizeof(buf));
175
176 count = strlen(source_p->name) + strlen(me.name) + 10 +
177 strlen(buf);
178
179 while ((ptr = ptr->next))
180 {
181 anptr = ptr->data;
182
183 if (count + strlen(anptr->nick) + 1 > IRCD_BUFSIZE - 2)
184 {
185 sendto_one(source_p, form_str(RPL_WATCHLIST),
186 me.name, source_p->name, buf);
187 buf[0] = '\0';
188 count = strlen(source_p->name) + strlen(me.name) + 10;
189 }
190
191 strcat(buf, " ");
192 strcat(buf, anptr->nick);
193 count += (strlen(anptr->nick) + 1);
194 }
195
196 sendto_one(source_p, form_str(RPL_WATCHLIST),
197 me.name, source_p->name, buf);
198 sendto_one(source_p, form_str(RPL_ENDOFWATCHLIST),
199 me.name, source_p->name, *s);
200 continue;
201 }
202
203 /*
204 * Well that was fun, NOT. Now they want a list of everybody in
205 * their WATCH list AND if they are online or offline? Sheesh,
206 * greedy aren't we?
207 */
208 if (*s == 'L' || *s == 'l')
209 {
210 const struct Client *target_p = NULL;
211
212 if (list_requested & 0x2)
213 continue;
214
215 list_requested |= 0x2;
216
217 DLINK_FOREACH(ptr, source_p->localClient->watches.head)
218 {
219 const struct Watch *anptr = ptr->data;
220
221 if ((target_p = find_person(source_p, anptr->nick)))
222 sendto_one(source_p, form_str(RPL_NOWON), me.name, source_p->name,
223 target_p->name, target_p->username,
224 target_p->host, target_p->tsinfo);
225 /*
226 * But actually, only show them offline if it's a capital
227 * 'L' (full list wanted).
228 */
229 else if (*s == 'L')
230 sendto_one(source_p, form_str(RPL_NOWOFF), me.name,
231 source_p->name, anptr->nick,
232 "*", "*", anptr->lasttime);
233 }
234
235 sendto_one(source_p, form_str(RPL_ENDOFWATCHLIST),
236 me.name, source_p->name, *s);
237 continue;
238 }
239
240 /* Hmm.. unknown prefix character.. Ignore it. :-) */
241 }
242 }
243
244 static struct Message watch_msgtab = {
245 "WATCH", 0, 0, 0, 1, MFLG_SLOW, 0,
246 { m_unregistered, m_watch, m_ignore, m_ignore, m_watch, m_ignore }
247 };
248
249 static void
250 module_init(void)
251 {
252 mod_add_cmd(&watch_msgtab);
253 add_isupport("WATCH", NULL, ConfigFileEntry.max_watch);
254 }
255
256 static void
257 module_exit(void)
258 {
259 mod_del_cmd(&watch_msgtab);
260 delete_isupport("WATCH");
261 }
262
263 struct module module_entry = {
264 .node = { NULL, NULL, NULL },
265 .name = NULL,
266 .version = "$Revision$",
267 .handle = NULL,
268 .modinit = module_init,
269 .modexit = module_exit,
270 .flags = 0
271 };

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision