ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_who.c
Revision: 1178
Committed: Mon Aug 15 08:11:31 2011 UTC (12 years, 7 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/m_who.c
File size: 9769 byte(s)
Log Message:
- Cleanup and restore older parts of the irc-command parser.
  Gives back ability to specify maximum amount of parameters
  that are processed within a command.

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 michael 1178 "WHO", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
50 michael 885 {m_unregistered, m_who, m_ignore, m_ignore, m_who, m_ignore}
51 adx 30 };
52    
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
67 michael 980 static void who_global(struct Client *, char *, int);
68     static void do_who(struct Client *, struct Client *,
69     const char *, const char *);
70     static void do_who_on_channel(struct Client *, struct Channel *,
71     const char *, int, int);
72 adx 30
73     /*
74     ** m_who
75     ** parv[0] = sender prefix
76     ** parv[1] = nickname mask list
77     ** parv[2] = additional selection flag, only 'o' for now.
78     */
79     static void
80     m_who(struct Client *client_p, struct Client *source_p,
81     int parc, char *parv[])
82     {
83     struct Client *target_p;
84     char *mask = parv[1];
85     dlink_node *lp;
86     int server_oper = parc > 2 ? (*parv[2] == 'o') : 0; /* Show OPERS only */
87     struct Channel *chptr;
88    
89     /* See if mask is there, collapse it or return if not there */
90 michael 980 if (EmptyString(mask))
91 adx 30 {
92     who_global(source_p, mask, server_oper);
93     sendto_one(source_p, form_str(RPL_ENDOFWHO),
94 michael 980 me.name, source_p->name, "*");
95 adx 30 return;
96     }
97    
98     /* mask isn't NULL at this point. repeat after me... -db */
99     collapse(mask);
100    
101     /* '/who *' */
102     if (mask[0] == '*' && !mask[1])
103     {
104     if ((lp = source_p->channel.head) != NULL)
105     {
106     struct Channel *mychannel = ((struct Membership *)lp->data)->chptr;
107     do_who_on_channel(source_p, mychannel, mychannel->chname, YES,
108     server_oper);
109     }
110    
111 michael 980 sendto_one(source_p, form_str(RPL_ENDOFWHO), me.name, source_p->name, "*");
112 adx 30 return;
113     }
114    
115     /* '/who #some_channel' */
116     if (IsChanPrefix(*mask))
117     {
118     /* List all users on a given channel */
119     if ((chptr = hash_find_channel(mask)) != NULL)
120     {
121     if (IsMember(source_p, chptr))
122     do_who_on_channel(source_p, chptr, chptr->chname, YES, server_oper);
123     else if (!SecretChannel(chptr))
124     do_who_on_channel(source_p, chptr, chptr->chname, NO, server_oper);
125     }
126    
127     sendto_one(source_p, form_str(RPL_ENDOFWHO),
128 michael 980 me.name, source_p->name, mask);
129 adx 30 return;
130     }
131    
132     /* '/who nick' */
133 michael 1169 if (((target_p = hash_find_client(mask)) != NULL) &&
134 adx 30 IsClient(target_p) && (!server_oper || IsOper(target_p)))
135     {
136     DLINK_FOREACH(lp, target_p->channel.head)
137     {
138     chptr = ((struct Membership *) lp->data)->chptr;
139     if (PubChannel(chptr) || IsMember(source_p, chptr))
140     break;
141     }
142    
143     if (lp != NULL)
144     do_who(source_p, target_p, chptr->chname,
145 michael 1146 get_member_status(lp->data, !!HasCap(source_p, CAP_MULTI_PREFIX)));
146 adx 30 else
147     do_who(source_p, target_p, NULL, "");
148    
149     sendto_one(source_p, form_str(RPL_ENDOFWHO),
150 michael 980 me.name, source_p->name, mask);
151 adx 30 return;
152     }
153    
154     /* '/who 0' */
155     if (mask[0] == '0' && !mask[1])
156     who_global(source_p, NULL, server_oper);
157     else
158     who_global(source_p, mask, server_oper);
159    
160 michael 1146 /* Wasn't a nick, wasn't a channel, wasn't a '*' so ... */
161 adx 30 sendto_one(source_p, form_str(RPL_ENDOFWHO),
162 michael 980 me.name, source_p->name, mask);
163 adx 30 }
164    
165     /* who_common_channel
166     * inputs - pointer to client requesting who
167     * - pointer to channel member chain.
168     * - char * mask to match
169     * - int if oper on a server or not
170     * - pointer to int maxmatches
171     * output - NONE
172     * side effects - lists matching clients on specified channel,
173     * marks matched clients.
174     *
175     */
176     static void
177     who_common_channel(struct Client *source_p, struct Channel *chptr,
178     char *mask, int server_oper, int *maxmatches)
179     {
180     dlink_node *ptr;
181     struct Client *target_p;
182    
183     DLINK_FOREACH(ptr, chptr->members.head)
184     {
185     target_p = ((struct Membership *)ptr->data)->client_p;
186    
187     if (!IsInvisible(target_p) || IsMarked(target_p))
188     continue;
189    
190     if (server_oper && !IsOper(target_p))
191     continue;
192    
193     SetMark(target_p);
194    
195     assert(target_p->servptr != NULL);
196    
197     if ((mask == NULL) ||
198 adx 268 match(mask, target_p->name) || match(mask, target_p->username) ||
199     match(mask, target_p->host) ||
200     ((!ConfigServerHide.hide_servers || IsOper(source_p)) &&
201     match(mask, target_p->servptr->name)) ||
202     match(mask, target_p->info))
203 adx 30 {
204     do_who(source_p, target_p, NULL, "");
205    
206     if (*maxmatches > 0)
207     {
208 adx 268 if (--(*maxmatches) == 0)
209     return;
210 adx 30 }
211     }
212     }
213     }
214    
215     /* who_global()
216     *
217     * inputs - pointer to client requesting who
218     * - char * mask to match
219     * - int if oper on a server or not
220     * output - NONE
221     * side effects - do a global scan of all clients looking for match
222     * this is slightly expensive on EFnet ...
223     */
224     static void
225     who_global(struct Client *source_p, char *mask, int server_oper)
226     {
227     struct Channel *chptr;
228     struct Client *target_p;
229     dlink_node *lp;
230     dlink_node *lp_next;
231     dlink_node *gcptr;
232     dlink_node *gcptr_next;
233     int maxmatches = 500;
234    
235 adx 268 if (!IsOper(source_p))
236     {
237     if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime)
238     {
239     /* safe enough to give this on a local connect only */
240 michael 980 sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, source_p->name);
241 adx 268 return;
242     }
243 michael 980
244     last_used = CurrentTime;
245 adx 268 }
246    
247 adx 30 /* 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 adx 268 match(mask, target_p->host) || match(mask, target_p->servptr->name) ||
276     match(mask, target_p->info))
277 adx 30 {
278     do_who(source_p, target_p, NULL, "");
279    
280     if (maxmatches > 0)
281     {
282     if (--maxmatches == 0)
283 adx 268 return;
284 adx 30 }
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 michael 313 dlink_node *ptr = NULL, *ptr_next = NULL;
305 adx 30 struct Client *target_p;
306     struct Membership *ms;
307    
308     DLINK_FOREACH_SAFE(ptr, ptr_next, chptr->members.head)
309     {
310     ms = ptr->data;
311     target_p = ms->client_p;
312    
313     if (member || !IsInvisible(target_p))
314     {
315     if (server_oper && !IsOper(target_p))
316 adx 268 continue;
317 michael 1146 do_who(source_p, target_p, chname, get_member_status(ms, !!HasCap(source_p, CAP_MULTI_PREFIX)));
318 adx 30 }
319     }
320     }
321    
322     /* do_who()
323     *
324     * inputs - pointer to client requesting who
325     * - pointer to client to do who on
326     * - The reported name
327     * - channel flags
328     * output - NONE
329     * side effects - do a who on given person
330     */
331     static void
332     do_who(struct Client *source_p, struct Client *target_p,
333     const char *chname, const char *op_flags)
334     {
335 michael 1146 char status[8]; /* G*#@%+\0 */
336 adx 30
337     if (IsOper(source_p))
338 michael 1146 snprintf(status, sizeof(status), "%c%s%s%s", target_p->away ? 'G' : 'H',
339 adx 30 IsOper(target_p) ? "*" : "", IsCaptured(target_p) ? "#" : "", op_flags);
340     else
341 michael 1146 snprintf(status, sizeof(status), "%c%s%s", target_p->away ? 'G' : 'H',
342 adx 30 IsOper(target_p) ? "*" : "", op_flags);
343    
344     if (ConfigServerHide.hide_servers)
345     {
346 michael 980 sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, source_p->name,
347 adx 30 (chname) ? (chname) : "*",
348 michael 980 target_p->username, target_p->host,
349 adx 30 IsOper(source_p) ? target_p->servptr->name : "*",
350     target_p->name, status, 0, target_p->info);
351     }
352     else
353     {
354 michael 980 sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, source_p->name,
355     (chname) ? (chname) : "*", target_p->username,
356 adx 30 target_p->host, target_p->servptr->name, target_p->name,
357     status, target_p->hopcount, target_p->info);
358     }
359     }

Properties

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