ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.3/modules/m_watch.c
Revision: 1029
Committed: Sun Nov 8 13:10:50 2009 UTC (14 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 7360 byte(s)
Log Message:
- branch off trunk to create 7.3 branch

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 static void m_watch(struct Client *, struct Client *, int, char *[]);
42
43 struct Message watch_msgtab = {
44 "WATCH", 0, 0, 0, 0, MFLG_SLOW, 0,
45 { m_unregistered, m_watch, m_ignore, m_ignore, m_watch, m_ignore }
46 };
47
48 #ifndef STATIC_MODULES
49 void
50 _modinit(void)
51 {
52 mod_add_cmd(&watch_msgtab);
53 add_isupport("WATCH", NULL, ConfigFileEntry.max_watch);
54 }
55
56 void
57 _moddeinit(void)
58 {
59 mod_del_cmd(&watch_msgtab);
60 delete_isupport("WATCH");
61 }
62
63 const char *_version = "$Revision$";
64 #endif
65
66 /*
67 * RPL_NOWON - Online at the moment (Succesfully added to WATCH-list)
68 * RPL_NOWOFF - Offline at the moment (Succesfully added to WATCH-list)
69 * RPL_WATCHOFF - Succesfully removed from WATCH-list.
70 * ERR_TOOMANYWATCH - Take a guess :> Too many WATCH entries.
71 */
72 static void
73 show_watch(struct Client *client_p, const char *name,
74 unsigned int rpl1, unsigned int rpl2)
75 {
76 const struct Client *target_p = NULL;
77
78 if ((target_p = find_person(client_p, name)))
79 sendto_one(client_p, form_str(rpl1), me.name, client_p->name,
80 target_p->name, target_p->username,
81 target_p->host, target_p->lasttime);
82 else
83 sendto_one(client_p, form_str(rpl2), me.name, client_p->name,
84 name, "*", "*", 0);
85 }
86
87 /*
88 * m_watch()
89 *
90 * parv[0] = sender prefix
91 * parv[1] = watch options
92 */
93 static void
94 m_watch(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
95 {
96 dlink_node *ptr = NULL;
97 char *s = NULL;
98 char *p = NULL;
99 char *user;
100 char def[2] = "l";
101 unsigned int list_requested = 0;
102
103 /*
104 * Default to 'l' - list who's currently online
105 */
106 if (parc < 2)
107 parv[1] = def;
108
109 for (s = strtoken(&p, parv[1], ", "); s;
110 s = strtoken(&p, NULL, ", "))
111 {
112 if ((user = strchr(s, '!')))
113 *user++ = '\0'; /* Not used */
114
115 /*
116 * Prefix of "+", they want to add a name to their WATCH
117 * list.
118 */
119 if (*s == '+')
120 {
121 if (*(s + 1) != '\0')
122 {
123 if (dlink_list_length(&source_p->localClient->watches) >=
124 ConfigFileEntry.max_watch)
125 {
126 sendto_one(source_p, form_str(ERR_TOOMANYWATCH), me.name,
127 source_p->name, s + 1, ConfigFileEntry.max_watch);
128 continue;
129 }
130
131 watch_add_to_hash_table(s + 1, source_p);
132 }
133
134 show_watch(source_p, s + 1, RPL_NOWON, RPL_NOWOFF);
135 continue;
136 }
137
138 /*
139 * Prefix of "-", coward wants to remove somebody from their
140 * WATCH list. So do it. :-)
141 */
142 if (*s == '-')
143 {
144 watch_del_from_hash_table(s + 1, source_p);
145 show_watch(source_p, s + 1, RPL_WATCHOFF, RPL_WATCHOFF);
146 continue;
147 }
148
149 /*
150 * Fancy "C" or "c", they want to nuke their WATCH list and start
151 * over, so be it.
152 */
153 if (*s == 'C' || *s == 'c')
154 {
155 watch_del_watch_list(source_p);
156 continue;
157 }
158
159 /*
160 * Now comes the fun stuff, "S" or "s" returns a status report of
161 * their WATCH list. I imagine this could be CPU intensive if
162 * it's done alot, perhaps an auto-lag on this?
163 */
164 if (*s == 'S' || *s == 's')
165 {
166 char buf[IRCD_BUFSIZE] = { '\0' };
167 const struct Watch *anptr = NULL;
168 unsigned int count = 0;
169
170 if (list_requested & 0x1)
171 continue;
172
173 list_requested |= 0x1;
174
175 /*
176 * Send a list of how many users they have on their WATCH list
177 * and how many WATCH lists they are on.
178 */
179 if ((anptr = watch_find_hash(source_p->name)))
180 count = dlink_list_length(&anptr->watched_by);
181
182 sendto_one(source_p, form_str(RPL_WATCHSTAT),
183 me.name, source_p->name,
184 dlink_list_length(&source_p->localClient->watches), count);
185
186 /*
187 * Send a list of everybody in their WATCH list. Be careful
188 * not to buffer overflow.
189 */
190 if ((ptr = source_p->localClient->watches.head) == NULL)
191 {
192 sendto_one(source_p, form_str(RPL_ENDOFWATCHLIST),
193 me.name, source_p->name, *s);
194 continue;
195 }
196
197 anptr = ptr->data;
198 strlcpy(buf, anptr->nick, sizeof(buf));
199
200 count = strlen(source_p->name) + strlen(me.name) + 10 +
201 strlen(buf);
202
203 while ((ptr = ptr->next))
204 {
205 anptr = ptr->data;
206
207 if (count + strlen(anptr->nick) + 1 > IRCD_BUFSIZE - 2)
208 {
209 sendto_one(source_p, form_str(RPL_WATCHLIST),
210 me.name, source_p->name, buf);
211 buf[0] = '\0';
212 count = strlen(source_p->name) + strlen(me.name) + 10;
213 }
214
215 strcat(buf, " ");
216 strcat(buf, anptr->nick);
217 count += (strlen(anptr->nick) + 1);
218 }
219
220 sendto_one(source_p, form_str(RPL_WATCHLIST),
221 me.name, source_p->name, buf);
222 sendto_one(source_p, form_str(RPL_ENDOFWATCHLIST),
223 me.name, source_p->name, *s);
224 continue;
225 }
226
227 /*
228 * Well that was fun, NOT. Now they want a list of everybody in
229 * their WATCH list AND if they are online or offline? Sheesh,
230 * greedy aren't we?
231 */
232 if (*s == 'L' || *s == 'l')
233 {
234 const struct Client *target_p = NULL;
235
236 if (list_requested & 0x2)
237 continue;
238
239 list_requested |= 0x2;
240
241 DLINK_FOREACH(ptr, source_p->localClient->watches.head)
242 {
243 const struct Watch *anptr = ptr->data;
244
245 if ((target_p = find_person(source_p, anptr->nick)))
246 sendto_one(source_p, form_str(RPL_NOWON), me.name, source_p->name,
247 target_p->name, target_p->username,
248 target_p->host, target_p->tsinfo);
249 /*
250 * But actually, only show them offline if it's a capital
251 * 'L' (full list wanted).
252 */
253 else if (*s == 'L')
254 sendto_one(source_p, form_str(RPL_NOWOFF), me.name,
255 source_p->name, anptr->nick,
256 "*", "*", anptr->lasttime);
257 }
258
259 sendto_one(source_p, form_str(RPL_ENDOFWATCHLIST),
260 me.name, source_p->name, *s);
261 continue;
262 }
263
264 /* Hmm.. unknown prefix character.. Ignore it. :-) */
265 }
266 }

Properties

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