Clean a bit - to be continued...
[seven-1.x.git] / modules / m_list_ratbox.c
blobf94a278e935527b17396c8e5475520b4fa0d8609
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_list.c: Shows what servers are currently connected.
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
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.
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.
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
25 #include "stdinc.h"
26 #include "tools.h"
27 #include "channel.h"
28 #include "client.h"
29 #include "hash.h"
30 #include "irc_string.h"
31 #include "ircd.h"
32 #include "numeric.h"
33 #include "s_conf.h"
34 #include "s_serv.h"
35 #include "send.h"
36 #include "msg.h"
37 #include "parse.h"
38 #include "modules.h"
39 #include "linebuf.h"
41 static int m_list(struct Client *, struct Client *, int, const char **);
42 static int mo_list(struct Client *, struct Client *, int, const char **);
44 struct Message list_msgtab = {
45 "LIST", 0, 0, 0, MFLG_SLOW,
46 {mg_unreg, {m_list, 0}, mg_ignore, mg_ignore, mg_ignore, {mo_list, 0}}
49 mapi_clist_av1 list_clist[] = { &list_msgtab, NULL };
50 DECLARE_MODULE_AV1(list, NULL, NULL, list_clist, NULL, NULL, "$Revision: 26 $");
52 static void list_all_channels(struct Client *source_p);
53 static void list_limit_channels(struct Client *source_p, const char *param);
54 static void list_named_channel(struct Client *source_p, const char *name);
56 /* m_list()
57 * parv[0] = sender prefix
58 * parv[1] = channel
60 static int
61 m_list(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
63 static time_t last_used = 0L;
65 /* pace this due to the sheer traffic involved */
66 if(((last_used + ConfigFileEntry.pace_wait) > CurrentTime))
68 sendto_one(source_p, form_str(RPL_LOAD2HI),
69 me.name, source_p->name, "LIST");
70 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
71 return 0;
73 else
74 last_used = CurrentTime;
76 /* If no arg, do all channels *whee*, else just one channel */
77 if(parc < 2 || EmptyString(parv[1]))
78 list_all_channels(source_p);
79 else if(IsChannelName(parv[1]))
80 list_named_channel(source_p, parv[1]);
81 else
82 list_limit_channels(source_p, parv[1]);
84 return 0;
87 /* mo_list()
88 * parv[0] = sender prefix
89 * parv[1] = channel
91 static int
92 mo_list(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
94 /* If no arg, do all channels *whee*, else just one channel */
95 if(parc < 2 || EmptyString(parv[1]))
96 list_all_channels(source_p);
97 else if(IsChannelName(parv[1]))
98 list_named_channel(source_p, parv[1]);
99 else
100 list_limit_channels(source_p, parv[1]);
102 return 0;
105 /* list_all_channels()
107 * inputs - pointer to client requesting list
108 * output -
109 * side effects - list all channels to source_p
111 static void
112 list_all_channels(struct Client *source_p)
114 struct Channel *chptr;
115 dlink_node *ptr;
116 int sendq_limit;
118 /* give them an output limit of 90% of their sendq. --fl */
119 sendq_limit = (int) get_sendq(source_p);
120 sendq_limit /= 10;
121 sendq_limit *= 9;
123 sendto_one(source_p, form_str(RPL_LISTSTART), me.name, source_p->name);
125 DLINK_FOREACH(ptr, global_channel_list.head)
127 chptr = ptr->data;
129 /* if theyre overflowing their sendq, stop. --fl */
130 if(linebuf_len(&source_p->localClient->buf_sendq) > sendq_limit)
132 sendto_one(source_p, form_str(ERR_TOOMANYMATCHES),
133 me.name, source_p->name, "LIST");
134 break;
137 if(SecretChannel(chptr) && !IsMember(source_p, chptr))
138 continue;
140 sendto_one(source_p, form_str(RPL_LIST),
141 me.name, source_p->name, chptr->chname,
142 dlink_list_length(&chptr->members),
143 chptr->topic == NULL ? "" : chptr->topic);
146 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
147 return;
150 static void
151 list_limit_channels(struct Client *source_p, const char *param)
153 struct Channel *chptr;
154 char *args;
155 char *p;
156 dlink_node *ptr;
157 unsigned int sendq_limit;
158 int max = INT_MAX;
159 int min = 0;
160 int i;
162 args = LOCAL_COPY(param);
164 for(i = 0; i < 2; i++)
166 if((p = strchr(args, ',')) != NULL)
167 *p++ = '\0';
169 if(*args == '<')
171 args++;
172 if((max = atoi(args)) <= 0)
173 max = INT_MAX;
175 else if(*args == '>')
177 args++;
178 if((min = atoi(args)) < 0)
179 min = 0;
182 if(EmptyString(p))
183 break;
184 else
185 args = p;
188 /* give them an output limit of 90% of their sendq. --fl */
189 sendq_limit = (unsigned int) get_sendq(source_p);
190 sendq_limit /= 10;
191 sendq_limit *= 9;
193 sendto_one(source_p, form_str(RPL_LISTSTART), me.name, source_p->name);
195 DLINK_FOREACH(ptr, global_channel_list.head)
197 chptr = ptr->data;
199 /* if theyre overflowing their sendq, stop. --fl */
200 if(linebuf_len(&source_p->localClient->buf_sendq) > sendq_limit)
202 sendto_one(source_p, form_str(ERR_TOOMANYMATCHES),
203 me.name, source_p->name, "LIST");
204 break;
207 if(dlink_list_length(&chptr->members) >= max ||
208 dlink_list_length(&chptr->members) <= min)
209 continue;
211 if(SecretChannel(chptr) && !IsMember(source_p, chptr))
212 continue;
214 sendto_one(source_p, form_str(RPL_LIST),
215 me.name, source_p->name, chptr->chname,
216 dlink_list_length(&chptr->members),
217 chptr->topic == NULL ? "" : chptr->topic);
220 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
221 return;
225 /* list_named_channel()
227 * inputs - pointer to client requesting list
228 * output -
229 * side effects - list single channel to source
231 static void
232 list_named_channel(struct Client *source_p, const char *name)
234 struct Channel *chptr;
235 char *p;
236 char *n = LOCAL_COPY(name);
238 sendto_one(source_p, form_str(RPL_LISTSTART), me.name, source_p->name);
240 if((p = strchr(n, ',')))
241 *p = '\0';
243 if(*n == '\0')
245 sendto_one_numeric(source_p, ERR_NOSUCHNICK,
246 form_str(ERR_NOSUCHNICK), name);
247 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
248 return;
251 chptr = find_channel(n);
253 if(chptr == NULL)
255 sendto_one_numeric(source_p, ERR_NOSUCHNICK,
256 form_str(ERR_NOSUCHNICK), n);
257 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
258 return;
261 if(ShowChannel(source_p, chptr))
262 sendto_one(source_p, form_str(RPL_LIST),
263 me.name, source_p->name, chptr->chname,
264 dlink_list_length(&chptr->members),
265 chptr->topic == NULL ? "" : chptr->topic);
267 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
268 return;