ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_watch.c
Revision: 6185
Committed: Wed Jun 24 17:46:27 2015 UTC (10 years, 2 months ago) by michael
Content type: text/x-csrc
File size: 7619 byte(s)
Log Message:
- Moved all ISUPPORT related code to isupport.c; renamed several functions to meet our coding convention

File Contents

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

Properties

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