ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_who.c
Revision: 1832
Committed: Fri Apr 19 19:16:09 2013 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 10248 byte(s)
Log Message:
- Made all numeric defines use the actual string instead of the numeric value
  which allows to use gcc's printf format attribute
- Remove current message locale implementation

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

Properties

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