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

File Contents

# User Rev Content
1 michael 876 /*
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 michael 953 * $Id$
24 michael 876 */
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 michael 972 { m_unregistered, m_watch, m_ignore, m_ignore, m_watch, m_ignore }
46 michael 876 };
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 michael 879 const char *_version = "$Revision$";
64 michael 876 #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