ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_watch.c
Revision: 4545
Committed: Fri Aug 22 08:46:13 2014 UTC (11 years ago) by michael
Content type: text/x-csrc
File size: 7548 byte(s)
Log Message:
- Implemented pseudo {} blocks (service aliases)
- Fixed compile warnings with -Wmissing-field-initializers

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

Properties

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