ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/branches/newio/modules/m_who.c
Revision: 1243
Committed: Fri Sep 30 10:47:53 2011 UTC (12 years, 6 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/m_who.c
File size: 10061 byte(s)
Log Message:
- move content of msg.h, ircd_handler.h and handlers.h into parse.h and
  remove headers accordingly
- killed common.h
- remove m_killhost.c and m_flags.c from contrib/
- sort out unused header includes here and there

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

Properties

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