ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/m_who.c
Revision: 69
Committed: Tue Oct 4 16:09:51 2005 UTC (20 years, 10 months ago) by adx
Content type: text/x-csrc
File size: 10285 byte(s)
Log Message:
- splitted ircd/libio, all headers connected with libio sources have been
  moved for internal use only. To use libio interface, include "libio.h"
  (which is already done in "stdinc.h")


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

Properties

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