ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_watch.c
Revision: 879
Committed: Thu Oct 25 08:03:01 2007 UTC (18 years, 9 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/m_watch.c
File size: 7441 byte(s)
Log Message:
svn propset svn:keywords

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

Properties

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