ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_who.c
Revision: 32
Committed: Sun Oct 2 20:41:23 2005 UTC (21 years ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/m_who.c
File size: 10371 byte(s)
Log Message:
- svn:keywords

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

Properties

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