]> jfr.im git - irc/rqf/shadowircd.git/blob - modules/m_list_ratbox.c
[svn] - the new plan:
[irc/rqf/shadowircd.git] / modules / m_list_ratbox.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_list.c: Shows what servers are currently connected.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
24 * $Id: m_list_ratbox.c 722 2006-02-08 21:51:28Z nenolod $
25 */
26
27 #include "stdinc.h"
28 #include "tools.h"
29 #include "channel.h"
30 #include "client.h"
31 #include "hash.h"
32 #include "irc_string.h"
33 #include "ircd.h"
34 #include "numeric.h"
35 #include "s_conf.h"
36 #include "s_serv.h"
37 #include "send.h"
38 #include "msg.h"
39 #include "parse.h"
40 #include "modules.h"
41 #include "linebuf.h"
42
43 static int m_list(struct Client *, struct Client *, int, const char **);
44 static int mo_list(struct Client *, struct Client *, int, const char **);
45
46 struct Message list_msgtab = {
47 "LIST", 0, 0, 0, MFLG_SLOW,
48 {mg_unreg, {m_list, 0}, mg_ignore, mg_ignore, mg_ignore, {mo_list, 0}}
49 };
50
51 mapi_clist_av1 list_clist[] = { &list_msgtab, NULL };
52 DECLARE_MODULE_AV1(list, NULL, NULL, list_clist, NULL, NULL, "$Revision: 722 $");
53
54 static void list_all_channels(struct Client *source_p);
55 static void list_limit_channels(struct Client *source_p, const char *param);
56 static void list_named_channel(struct Client *source_p, const char *name);
57
58 /* m_list()
59 * parv[0] = sender prefix
60 * parv[1] = channel
61 */
62 static int
63 m_list(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
64 {
65 static time_t last_used = 0L;
66
67 /* pace this due to the sheer traffic involved */
68 if(((last_used + ConfigFileEntry.pace_wait) > CurrentTime))
69 {
70 sendto_one(source_p, form_str(RPL_LOAD2HI),
71 me.name, source_p->name, "LIST");
72 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
73 return 0;
74 }
75 else
76 last_used = CurrentTime;
77
78 /* If no arg, do all channels *whee*, else just one channel */
79 if(parc < 2 || EmptyString(parv[1]))
80 list_all_channels(source_p);
81 else if(IsChannelName(parv[1]))
82 list_named_channel(source_p, parv[1]);
83 else
84 list_limit_channels(source_p, parv[1]);
85
86 return 0;
87 }
88
89 /* mo_list()
90 * parv[0] = sender prefix
91 * parv[1] = channel
92 */
93 static int
94 mo_list(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
95 {
96 /* If no arg, do all channels *whee*, else just one channel */
97 if(parc < 2 || EmptyString(parv[1]))
98 list_all_channels(source_p);
99 else if(IsChannelName(parv[1]))
100 list_named_channel(source_p, parv[1]);
101 else
102 list_limit_channels(source_p, parv[1]);
103
104 return 0;
105 }
106
107 /* list_all_channels()
108 *
109 * inputs - pointer to client requesting list
110 * output -
111 * side effects - list all channels to source_p
112 */
113 static void
114 list_all_channels(struct Client *source_p)
115 {
116 struct Channel *chptr;
117 dlink_node *ptr;
118 int sendq_limit;
119
120 /* give them an output limit of 90% of their sendq. --fl */
121 sendq_limit = (int) get_sendq(source_p);
122 sendq_limit /= 10;
123 sendq_limit *= 9;
124
125 sendto_one(source_p, form_str(RPL_LISTSTART), me.name, source_p->name);
126
127 DLINK_FOREACH(ptr, global_channel_list.head)
128 {
129 chptr = ptr->data;
130
131 /* if theyre overflowing their sendq, stop. --fl */
132 if(linebuf_len(&source_p->localClient->buf_sendq) > sendq_limit)
133 {
134 sendto_one(source_p, form_str(ERR_TOOMANYMATCHES),
135 me.name, source_p->name, "LIST");
136 break;
137 }
138
139 if(SecretChannel(chptr) && !IsMember(source_p, chptr))
140 continue;
141
142 sendto_one(source_p, form_str(RPL_LIST),
143 me.name, source_p->name, chptr->chname,
144 dlink_list_length(&chptr->members),
145 chptr->topic == NULL ? "" : chptr->topic);
146 }
147
148 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
149 return;
150 }
151
152 static void
153 list_limit_channels(struct Client *source_p, const char *param)
154 {
155 struct Channel *chptr;
156 char *args;
157 char *p;
158 dlink_node *ptr;
159 unsigned int sendq_limit;
160 int max = INT_MAX;
161 int min = 0;
162 int i;
163
164 args = LOCAL_COPY(param);
165
166 for(i = 0; i < 2; i++)
167 {
168 if((p = strchr(args, ',')) != NULL)
169 *p++ = '\0';
170
171 if(*args == '<')
172 {
173 args++;
174 if((max = atoi(args)) <= 0)
175 max = INT_MAX;
176 }
177 else if(*args == '>')
178 {
179 args++;
180 if((min = atoi(args)) < 0)
181 min = 0;
182 }
183
184 if(EmptyString(p))
185 break;
186 else
187 args = p;
188 }
189
190 /* give them an output limit of 90% of their sendq. --fl */
191 sendq_limit = (unsigned int) get_sendq(source_p);
192 sendq_limit /= 10;
193 sendq_limit *= 9;
194
195 sendto_one(source_p, form_str(RPL_LISTSTART), me.name, source_p->name);
196
197 DLINK_FOREACH(ptr, global_channel_list.head)
198 {
199 chptr = ptr->data;
200
201 /* if theyre overflowing their sendq, stop. --fl */
202 if(linebuf_len(&source_p->localClient->buf_sendq) > sendq_limit)
203 {
204 sendto_one(source_p, form_str(ERR_TOOMANYMATCHES),
205 me.name, source_p->name, "LIST");
206 break;
207 }
208
209 if(dlink_list_length(&chptr->members) >= max ||
210 dlink_list_length(&chptr->members) <= min)
211 continue;
212
213 if(SecretChannel(chptr) && !IsMember(source_p, chptr))
214 continue;
215
216 sendto_one(source_p, form_str(RPL_LIST),
217 me.name, source_p->name, chptr->chname,
218 dlink_list_length(&chptr->members),
219 chptr->topic == NULL ? "" : chptr->topic);
220 }
221
222 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
223 return;
224 }
225
226
227 /* list_named_channel()
228 *
229 * inputs - pointer to client requesting list
230 * output -
231 * side effects - list single channel to source
232 */
233 static void
234 list_named_channel(struct Client *source_p, const char *name)
235 {
236 struct Channel *chptr;
237 char *p;
238 char *n = LOCAL_COPY(name);
239
240 sendto_one(source_p, form_str(RPL_LISTSTART), me.name, source_p->name);
241
242 if((p = strchr(n, ',')))
243 *p = '\0';
244
245 if(*n == '\0')
246 {
247 sendto_one_numeric(source_p, ERR_NOSUCHNICK,
248 form_str(ERR_NOSUCHNICK), name);
249 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
250 return;
251 }
252
253 chptr = find_channel(n);
254
255 if(chptr == NULL)
256 {
257 sendto_one_numeric(source_p, ERR_NOSUCHNICK,
258 form_str(ERR_NOSUCHNICK), n);
259 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
260 return;
261 }
262
263 if(ShowChannel(source_p, chptr))
264 sendto_one(source_p, form_str(RPL_LIST),
265 me.name, source_p->name, chptr->chname,
266 dlink_list_length(&chptr->members),
267 chptr->topic == NULL ? "" : chptr->topic);
268
269 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
270 return;
271 }