ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/m_who.c
Revision: 1028
Committed: Sun Nov 8 13:03:38 2009 UTC (15 years, 9 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/m_who.c
File size: 9676 byte(s)
Log Message:
- move ircd-hybrid-7.2 to trunk

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * m_who.c: Shows who is on a channel.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
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 knight 31 * $Id$
23 adx 30 */
24 michael 1011
25 adx 30 #include "stdinc.h"
26 michael 1011 #include "list.h"
27 adx 30 #include "common.h"
28     #include "handlers.h"
29     #include "client.h"
30     #include "channel.h"
31     #include "channel_mode.h"
32     #include "hash.h"
33     #include "ircd.h"
34     #include "numeric.h"
35     #include "s_serv.h"
36     #include "send.h"
37     #include "irc_string.h"
38     #include "sprintf_irc.h"
39     #include "s_conf.h"
40     #include "msg.h"
41     #include "parse.h"
42     #include "modules.h"
43    
44 adx 268 static time_t last_used = 0;
45    
46 michael 980 static void m_who(struct Client *, struct Client *, int, char *[]);
47 adx 30
48     struct Message who_msgtab = {
49     "WHO", 0, 0, 2, 0, MFLG_SLOW, 0,
50 michael 885 {m_unregistered, m_who, m_ignore, m_ignore, m_who, m_ignore}
51 adx 30 };
52    
53     #ifndef STATIC_MODULES
54     void
55     _modinit(void)
56     {
57     mod_add_cmd(&who_msgtab);
58     }
59    
60     void
61     _moddeinit(void)
62     {
63     mod_del_cmd(&who_msgtab);
64     }
65    
66 knight 31 const char *_version = "$Revision$";
67 adx 30 #endif
68    
69 michael 980 static void who_global(struct Client *, char *, int);
70     static void do_who(struct Client *, struct Client *,
71     const char *, const char *);
72     static void do_who_on_channel(struct Client *, struct Channel *,
73     const char *, int, int);
74 adx 30
75     /*
76     ** m_who
77     ** parv[0] = sender prefix
78     ** parv[1] = nickname mask list
79     ** parv[2] = additional selection flag, only 'o' for now.
80     */
81     static void
82     m_who(struct Client *client_p, struct Client *source_p,
83     int parc, char *parv[])
84     {
85     struct Client *target_p;
86     char *mask = parv[1];
87     dlink_node *lp;
88     int server_oper = parc > 2 ? (*parv[2] == 'o') : 0; /* Show OPERS only */
89     struct Channel *chptr;
90    
91     /* See if mask is there, collapse it or return if not there */
92 michael 980 if (EmptyString(mask))
93 adx 30 {
94     who_global(source_p, mask, server_oper);
95     sendto_one(source_p, form_str(RPL_ENDOFWHO),
96 michael 980 me.name, source_p->name, "*");
97 adx 30 return;
98     }
99    
100     /* mask isn't NULL at this point. repeat after me... -db */
101     collapse(mask);
102    
103     /* '/who *' */
104     if (mask[0] == '*' && !mask[1])
105     {
106     if ((lp = source_p->channel.head) != NULL)
107     {
108     struct Channel *mychannel = ((struct Membership *)lp->data)->chptr;
109     do_who_on_channel(source_p, mychannel, mychannel->chname, YES,
110     server_oper);
111     }
112    
113 michael 980 sendto_one(source_p, form_str(RPL_ENDOFWHO), me.name, source_p->name, "*");
114 adx 30 return;
115     }
116    
117     /* '/who #some_channel' */
118     if (IsChanPrefix(*mask))
119     {
120     /* List all users on a given channel */
121     if ((chptr = hash_find_channel(mask)) != NULL)
122     {
123     if (IsMember(source_p, chptr))
124     do_who_on_channel(source_p, chptr, chptr->chname, YES, server_oper);
125     else if (!SecretChannel(chptr))
126     do_who_on_channel(source_p, chptr, chptr->chname, NO, server_oper);
127     }
128    
129     sendto_one(source_p, form_str(RPL_ENDOFWHO),
130 michael 980 me.name, source_p->name, mask);
131 adx 30 return;
132     }
133    
134     /* '/who nick' */
135     if (((target_p = find_client(mask)) != NULL) &&
136     IsClient(target_p) && (!server_oper || IsOper(target_p)))
137     {
138     DLINK_FOREACH(lp, target_p->channel.head)
139     {
140     chptr = ((struct Membership *) lp->data)->chptr;
141     if (PubChannel(chptr) || IsMember(source_p, chptr))
142     break;
143     }
144    
145     if (lp != NULL)
146     do_who(source_p, target_p, chptr->chname,
147     get_member_status(lp->data, NO));
148     else
149     do_who(source_p, target_p, NULL, "");
150    
151     sendto_one(source_p, form_str(RPL_ENDOFWHO),
152 michael 980 me.name, source_p->name, mask);
153 adx 30 return;
154     }
155    
156     /* '/who 0' */
157     if (mask[0] == '0' && !mask[1])
158     who_global(source_p, NULL, server_oper);
159     else
160     who_global(source_p, mask, server_oper);
161    
162     /* Wasn't a nick, wasn't a channel, wasn't a '*' so ... */
163     sendto_one(source_p, form_str(RPL_ENDOFWHO),
164 michael 980 me.name, source_p->name, mask);
165 adx 30 }
166    
167     /* who_common_channel
168     * inputs - pointer to client requesting who
169     * - pointer to channel member chain.
170     * - char * mask to match
171     * - int if oper on a server or not
172     * - pointer to int maxmatches
173     * output - NONE
174     * side effects - lists matching clients on specified channel,
175     * marks matched clients.
176     *
177     */
178     static void
179     who_common_channel(struct Client *source_p, struct Channel *chptr,
180     char *mask, int server_oper, int *maxmatches)
181     {
182     dlink_node *ptr;
183     struct Client *target_p;
184    
185     DLINK_FOREACH(ptr, chptr->members.head)
186     {
187     target_p = ((struct Membership *)ptr->data)->client_p;
188    
189     if (!IsInvisible(target_p) || IsMarked(target_p))
190     continue;
191    
192     if (server_oper && !IsOper(target_p))
193     continue;
194    
195     SetMark(target_p);
196    
197     assert(target_p->servptr != NULL);
198    
199     if ((mask == NULL) ||
200 adx 268 match(mask, target_p->name) || match(mask, target_p->username) ||
201     match(mask, target_p->host) ||
202     ((!ConfigServerHide.hide_servers || IsOper(source_p)) &&
203     match(mask, target_p->servptr->name)) ||
204     match(mask, target_p->info))
205 adx 30 {
206     do_who(source_p, target_p, NULL, "");
207    
208     if (*maxmatches > 0)
209     {
210 adx 268 if (--(*maxmatches) == 0)
211     return;
212 adx 30 }
213     }
214     }
215     }
216    
217     /* who_global()
218     *
219     * inputs - pointer to client requesting who
220     * - char * mask to match
221     * - int if oper on a server or not
222     * output - NONE
223     * side effects - do a global scan of all clients looking for match
224     * this is slightly expensive on EFnet ...
225     */
226     static void
227     who_global(struct Client *source_p, char *mask, int server_oper)
228     {
229     struct Channel *chptr;
230     struct Client *target_p;
231     dlink_node *lp;
232     dlink_node *lp_next;
233     dlink_node *gcptr;
234     dlink_node *gcptr_next;
235     int maxmatches = 500;
236    
237 adx 268 if (!IsOper(source_p))
238     {
239     if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime)
240     {
241     /* safe enough to give this on a local connect only */
242 michael 980 sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, source_p->name);
243 adx 268 return;
244     }
245 michael 980
246     last_used = CurrentTime;
247 adx 268 }
248    
249 adx 30 /* first, list all matching invisible clients on common channels */
250     DLINK_FOREACH_SAFE(lp, lp_next, source_p->channel.head)
251     {
252     chptr = ((struct Membership *)lp->data)->chptr;
253     who_common_channel(source_p, chptr, mask, server_oper, &maxmatches);
254     }
255    
256     /* second, list all matching visible clients */
257     DLINK_FOREACH_SAFE(gcptr, gcptr_next, global_client_list.head)
258     {
259     target_p = gcptr->data;
260    
261     if (!IsClient(target_p))
262     continue;
263    
264     if (IsInvisible(target_p))
265     {
266     ClearMark(target_p);
267     continue;
268     }
269    
270     if (server_oper && !IsOper(target_p))
271     continue;
272    
273     assert(target_p->servptr != NULL);
274    
275     if (!mask ||
276     match(mask, target_p->name) || match(mask, target_p->username) ||
277 adx 268 match(mask, target_p->host) || match(mask, target_p->servptr->name) ||
278     match(mask, target_p->info))
279 adx 30 {
280     do_who(source_p, target_p, NULL, "");
281    
282     if (maxmatches > 0)
283     {
284     if (--maxmatches == 0)
285 adx 268 return;
286 adx 30 }
287     }
288     }
289     }
290    
291     /* do_who_on_channel()
292     *
293     * inputs - pointer to client requesting who
294     * - pointer to channel to do who on
295     * - The "real name" of this channel
296     * - int if source_p is a server oper or not
297     * - int if client is member or not
298     * - int server_op flag
299     * output - NONE
300     * side effects - do a who on given channel
301     */
302     static void
303     do_who_on_channel(struct Client *source_p, struct Channel *chptr,
304     const char *chname, int member, int server_oper)
305     {
306 michael 313 dlink_node *ptr = NULL, *ptr_next = NULL;
307 adx 30 struct Client *target_p;
308     struct Membership *ms;
309    
310     DLINK_FOREACH_SAFE(ptr, ptr_next, chptr->members.head)
311     {
312     ms = ptr->data;
313     target_p = ms->client_p;
314    
315     if (member || !IsInvisible(target_p))
316     {
317     if (server_oper && !IsOper(target_p))
318 adx 268 continue;
319 adx 30 do_who(source_p, target_p, chname, get_member_status(ms, NO));
320     }
321     }
322     }
323    
324     /* do_who()
325     *
326     * inputs - pointer to client requesting who
327     * - pointer to client to do who on
328     * - The reported name
329     * - channel flags
330     * output - NONE
331     * side effects - do a who on given person
332     */
333     static void
334     do_who(struct Client *source_p, struct Client *target_p,
335     const char *chname, const char *op_flags)
336     {
337     char status[6];
338    
339     if (IsOper(source_p))
340 michael 980 ircsprintf(status, "%c%s%s%s", target_p->away ? 'G' : 'H',
341 adx 30 IsOper(target_p) ? "*" : "", IsCaptured(target_p) ? "#" : "", op_flags);
342     else
343     ircsprintf(status, "%c%s%s", target_p->away ? 'G' : 'H',
344     IsOper(target_p) ? "*" : "", op_flags);
345    
346     if (ConfigServerHide.hide_servers)
347     {
348 michael 980 sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, source_p->name,
349 adx 30 (chname) ? (chname) : "*",
350 michael 980 target_p->username, target_p->host,
351 adx 30 IsOper(source_p) ? target_p->servptr->name : "*",
352     target_p->name, status, 0, target_p->info);
353     }
354     else
355     {
356 michael 980 sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, source_p->name,
357     (chname) ? (chname) : "*", target_p->username,
358 adx 30 target_p->host, target_p->servptr->name, target_p->name,
359     status, target_p->hopcount, target_p->info);
360     }
361     }

Properties

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