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

# User Rev Content
1 michael 876 /*
2 michael 2820 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 michael 876 *
4 michael 2820 * Copyright (c) 1997 Jukka Santala (Donwulff)
5 michael 5347 * Copyright (c) 2000-2015 ircd-hybrid development team
6 michael 876 *
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 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20 michael 876 * USA
21     */
22    
23 michael 2820 /*! \file m_watch.c
24     * \brief Includes required functions for processing the WATCH command.
25     * \version $Id$
26     */
27    
28 michael 876 #include "stdinc.h"
29     #include "client.h"
30     #include "irc_string.h"
31     #include "ircd.h"
32     #include "numeric.h"
33 michael 1309 #include "conf.h"
34 michael 876 #include "send.h"
35     #include "parse.h"
36     #include "modules.h"
37 michael 3347 #include "user.h"
38 michael 876 #include "watch.h"
39 michael 6185 #include "isupport.h"
40 michael 876
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 michael 3156 show_watch(struct Client *source_p, const char *name,
50 michael 3109 enum irc_numerics rpl1, enum irc_numerics rpl2)
51 michael 876 {
52     const struct Client *target_p = NULL;
53    
54 michael 3156 if ((target_p = find_person(source_p, name)))
55     sendto_one_numeric(source_p, &me, rpl1,
56 michael 3109 target_p->name, target_p->username,
57     target_p->host, target_p->tsinfo);
58 michael 876 else
59 michael 3156 sendto_one_numeric(source_p, &me, rpl2, name, "*", "*", 0);
60 michael 876 }
61    
62 michael 3294 /*! \brief WATCH command handler
63 michael 876 *
64 michael 3294 * \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 michael 876 */
73 michael 2820 static int
74 michael 3156 m_watch(struct Client *source_p, int parc, char *parv[])
75 michael 876 {
76 michael 4815 dlink_node *node = NULL;
77 michael 876 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 michael 3368 if (*(s + 1))
102 michael 876 {
103 michael 4588 if (dlink_list_length(&source_p->connection->watches) >=
104 michael 4340 ConfigGeneral.max_watch)
105 michael 876 {
106 michael 4340 sendto_one_numeric(source_p, &me, ERR_TOOMANYWATCH, s + 1, ConfigGeneral.max_watch);
107 michael 876 continue;
108     }
109    
110 michael 3424 if (valid_nickname(s + 1, 1))
111     watch_add_to_hash_table(s + 1, source_p);
112 michael 876 }
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 michael 3294 * their WATCH list. I imagine this could be CPU intensive if
142 michael 876 * it's done alot, perhaps an auto-lag on this?
143     */
144     if (*s == 'S' || *s == 's')
145     {
146 michael 3213 char buf[IRCD_BUFSIZE] = "";
147 michael 4815 const struct Watch *watch = NULL;
148 michael 876 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 michael 4815 if ((watch = watch_find_hash(source_p->name)))
160     count = dlink_list_length(&watch->watched_by);
161 michael 876
162 michael 3109 sendto_one_numeric(source_p, &me, RPL_WATCHSTAT,
163 michael 4588 dlink_list_length(&source_p->connection->watches), count);
164 michael 876
165     /*
166 michael 3294 * Send a list of everybody in their WATCH list. Be careful
167 michael 876 * not to buffer overflow.
168     */
169 michael 4815 if ((node = source_p->connection->watches.head) == NULL)
170 michael 876 {
171 michael 3109 sendto_one_numeric(source_p, &me, RPL_ENDOFWATCHLIST, *s);
172 michael 876 continue;
173     }
174    
175 michael 4815 watch = node->data;
176     strlcpy(buf, watch->nick, sizeof(buf));
177 michael 876
178     count = strlen(source_p->name) + strlen(me.name) + 10 +
179     strlen(buf);
180    
181 michael 4815 while ((node = node->next))
182 michael 876 {
183 michael 4815 watch = node->data;
184 michael 876
185 michael 4815 if (count + strlen(watch->nick) + 1 > IRCD_BUFSIZE - 2)
186 michael 876 {
187 michael 3109 sendto_one_numeric(source_p, &me, RPL_WATCHLIST, buf);
188 michael 876 buf[0] = '\0';
189     count = strlen(source_p->name) + strlen(me.name) + 10;
190     }
191    
192 michael 3213 strlcat(buf, " ", sizeof(buf));
193 michael 4815 strlcat(buf, watch->nick, sizeof(buf));
194     count += (strlen(watch->nick) + 1);
195 michael 876 }
196    
197 michael 3109 sendto_one_numeric(source_p, &me, RPL_WATCHLIST, buf);
198     sendto_one_numeric(source_p, &me, RPL_ENDOFWATCHLIST, *s);
199 michael 876 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 michael 4815 DLINK_FOREACH(node, source_p->connection->watches.head)
217 michael 876 {
218 michael 4815 const struct Watch *watch = node->data;
219 michael 876
220 michael 4815 if ((target_p = find_person(source_p, watch->nick)))
221 michael 3109 sendto_one_numeric(source_p, &me, RPL_NOWON,
222     target_p->name, target_p->username,
223     target_p->host, target_p->tsinfo);
224    
225 michael 876 /*
226     * But actually, only show them offline if it's a capital
227     * 'L' (full list wanted).
228     */
229     else if (*s == 'L')
230 michael 4815 sendto_one_numeric(source_p, &me, RPL_NOWOFF, watch->nick,
231     "*", "*", watch->lasttime);
232 michael 876 }
233    
234 michael 3109 sendto_one_numeric(source_p, &me, RPL_ENDOFWATCHLIST, *s);
235 michael 876 continue;
236     }
237    
238     /* Hmm.. unknown prefix character.. Ignore it. :-) */
239     }
240 michael 2820
241     return 0;
242 michael 876 }
243 michael 1230
244 michael 2820 static struct Message watch_msgtab =
245     {
246 michael 5881 .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 michael 1230 };
254    
255     static void
256     module_init(void)
257     {
258     mod_add_cmd(&watch_msgtab);
259 michael 6185 isupport_add("WATCH", NULL, ConfigGeneral.max_watch);
260 michael 1230 }
261    
262     static void
263     module_exit(void)
264     {
265     mod_del_cmd(&watch_msgtab);
266 michael 6185 isupport_delete("WATCH");
267 michael 1230 }
268    
269 michael 2820 struct module module_entry =
270     {
271 michael 1230 .version = "$Revision$",
272     .modinit = module_init,
273     .modexit = module_exit,
274     };

Properties

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