ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_who.c
Revision: 32
Committed: Sun Oct 2 20:41:23 2005 UTC (19 years, 10 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/m_who.c
File size: 10371 byte(s)
Log Message:
- svn:keywords

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

Properties

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