ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_who.c
Revision: 1406
Committed: Thu May 10 21:01:57 2012 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/m_who.c
File size: 10386 byte(s)
Log Message:
- m_who(): replace two irccmp with strcmp

File Contents

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

Properties

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