ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/contrib/ircd_alis.C
Revision: 1.2
Committed: Sat Jul 21 01:29:08 2007 UTC (19 years, 2 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +3 -3 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * Copyright © 2005-2007 William Pitcock, et al.
3 pippijn 1.2 * The rights to this code are as documented under doc/pod/license.pod.
4 pippijn 1.1 *
5     * Copyright © 2003-2007 Lee Hardy <leeh@leeh.co.uk>
6     * Copyright © 2003-2007 ircd-ratbox development team
7     *
8     * Redistribution and use in source and binary forms, with or without
9     * modification, are permitted provided that the following conditions are
10     * met:
11     *
12     * 1.Redistributions of source code must retain the above copyright notice,
13     * this list of conditions and the following disclaimer.
14     * 2.Redistributions in binary form must reproduce the above copyright
15     * notice, this list of conditions and the following disclaimer in the
16     * documentation and/or other materials provided with the distribution.
17     * 3.The name of the author may not be used to endorse or promote products
18     * derived from this software without specific prior written permission.
19     *
20     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23     * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
24     * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26     * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28     * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29     * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30     * POSSIBILITY OF SUCH DAMAGE.
31     *
32     * ALIS, based on the ratbox-services implementation.
33     *
34 pippijn 1.2 * $Id: ircd_alis.C,v 1.1 2007-07-19 08:24:53 pippijn Exp $
35 pippijn 1.1 */
36    
37     #include "atheme.h"
38    
39 pippijn 1.2 DECLARE_MODULE_V1 ("alis", false, _modinit, _moddeinit, "$Revision: 1.1 $", "William Pitcock <nenolod -at- nenolod.net>");
40 pippijn 1.1
41     #define ALIS_MAX_PARC 10
42     #define ALIS_MAX_MATCH 60
43    
44     #define DIR_UNSET 0
45     #define DIR_SET 1
46     #define DIR_EQUAL 2
47    
48     service_t *alis;
49     cmdvec alis_cmdtree;
50    
51     static void alis_cmd_list (sourceinfo_t *si, int parc, char *parv[]);
52     static void alis_cmd_help (sourceinfo_t *si, int parc, char *parv[]);
53     static void alis_handler (sourceinfo_t *si, int parc, char *parv[]);
54    
55     command_t alis_list = { "LIST", "Lists channels matching given parameters.",
56     AC_NONE, ALIS_MAX_PARC, alis_cmd_list
57     };
58     command_t alis_help = { "HELP", "Displays contextual help information.",
59     AC_NONE, 1, alis_cmd_help
60     };
61    
62     struct alis_query
63     {
64     char const *mask;
65     char *topic;
66     int min;
67     int max;
68     int show_mode;
69     int show_topicwho;
70     unsigned int mode;
71     int mode_dir;
72     int mode_key;
73     int mode_limit;
74     int skip;
75     };
76    
77     void
78     _modinit (module_t *m)
79     {
80     alis = add_service ("ALIS", "alis", me.name, "Channel Directory", alis_handler, alis_cmdtree);
81    
82     &alis_cmdtree << alis_list;
83     &alis_cmdtree << alis_help;
84     }
85    
86     void
87     _moddeinit ()
88     {
89     &alis_cmdtree >> alis_list;
90     &alis_cmdtree >> alis_help;
91    
92     del_service (alis);
93     }
94    
95     static int
96     alis_parse_mode (const char *text, int *key, int *limit)
97     {
98     int mode = 0;
99    
100     if (!text)
101     return 0;
102    
103     while (*text)
104     {
105     switch (*text)
106     {
107     case 'l':
108     *limit = 1;
109     break;
110     case 'k':
111     *key = 1;
112     break;
113     default:
114     mode |= mode_to_flag (*text);
115     break;
116     }
117    
118     text++;
119     }
120    
121     return mode;
122     }
123    
124     static int
125     parse_alis (sourceinfo_t *si, int parc, char *parv[], struct alis_query *query)
126     {
127     int i = 0;
128     char *opt = NULL, *arg = NULL;
129    
130     while ((opt = parv[i++]))
131     {
132     if (!strcasecmp (opt, "-min"))
133     {
134     if ((arg = parv[i++]) == NULL || (query->min = atoi (arg)) < 1)
135     {
136     command_fail (si, fault_badparams, "Invalid -min option");
137     return 0;
138     }
139     }
140     else if (!strcasecmp (opt, "-max"))
141     {
142     if ((arg = parv[i++]) == NULL || (query->max = atoi (arg)) < 1)
143     {
144     command_fail (si, fault_badparams, "Invalid -max option");
145     return 0;
146     }
147     }
148     else if (!strcasecmp (opt, "-skip"))
149     {
150     if ((arg = parv[i++]) == NULL || (query->skip = atoi (arg)) < 1)
151     {
152     command_fail (si, fault_badparams, "Invalid -skip option");
153     return 0;
154     }
155     }
156     else if (!strcasecmp (opt, "-topic"))
157     {
158     query->topic = strtok (NULL, " ");
159     }
160     else if (!strcasecmp (opt, "-show"))
161     {
162     arg = parv[i++];
163    
164     if (arg == NULL)
165     {
166     command_fail (si, fault_badparams, "Invalid -show option");
167     return 0;
168     }
169    
170     if (arg[0] == 'm')
171     {
172     query->show_mode = 1;
173    
174     if (arg[1] == 't')
175     query->show_topicwho = 1;
176     }
177     else if (arg[0] == 't')
178     {
179     query->show_topicwho = 1;
180    
181     if (arg[1] == 'm')
182     query->show_mode = 1;
183     }
184     }
185     else if (!strcasecmp (opt, "-mode"))
186     {
187     arg = parv[i++];
188    
189     if (arg == NULL)
190     {
191     command_fail (si, fault_badparams, "Invalid -mode option");
192     return 0;
193     }
194    
195     switch (*arg)
196     {
197     case '+':
198     query->mode_dir = DIR_SET;
199     break;
200     case '-':
201     query->mode_dir = DIR_UNSET;
202     break;
203     case '=':
204     query->mode_dir = DIR_EQUAL;
205     break;
206     default:
207     command_fail (si, fault_badparams, "Invalid -mode option");
208     return 0;
209     }
210    
211     query->mode = alis_parse_mode (arg + 1, &query->mode_key, &query->mode_limit);
212    
213     if (query->mode == 0)
214     {
215     command_fail (si, fault_badparams, "Invalid -mode option");
216     return 0;
217     }
218     }
219     else
220     {
221     command_fail (si, fault_badparams, "Invalid option %s", opt);
222     return 0;
223     }
224     }
225    
226     return 1;
227     }
228    
229     static void
230     print_channel (sourceinfo_t *si, channel_t *c, struct alis_query *query)
231     {
232     int show_topicwho = query->show_topicwho;
233     int show_topic = 1;
234     char modestr[MAXEXTMODES + 60];
235     int i, j;
236    
237     /* cant show a topicwho, when a channel has no topic. */
238     if (!c->topic)
239     {
240     show_topicwho = 0;
241     show_topic = 0;
242     }
243     if (query->show_mode)
244     {
245     j = 0;
246     modestr[j++] = '+';
247     for (i = 0; i < MAXEXTMODES; i++)
248     if (c->extmodes[i] != NULL)
249     modestr[j++] = ignore_mode_list[i].mode;
250     if (c->limit != 0)
251     modestr[j++] = 'l';
252     if (c->key != NULL)
253     modestr[j++] = 'k';
254     modestr[j] = '\0';
255     strlcat (modestr, flags_to_string (c->modes), sizeof modestr);
256     }
257    
258     if (query->show_mode && show_topicwho && show_topic)
259     command_success_nodata (si, "%-50s %-8s %3ld :%s (%s)", c->name, modestr, LIST_LENGTH (&c->members), c->topic, c->topic_setter);
260     else if (query->show_mode)
261     command_success_nodata (si, "%-50s %-8s %3ld :%s", c->name, modestr, LIST_LENGTH (&c->members), c->topic);
262     else if (show_topicwho && show_topic)
263     command_success_nodata (si, "%-50s %3ld :%s (%s)", c->name, LIST_LENGTH (&c->members), c->topic, c->topic_setter);
264     else if (show_topic)
265     command_success_nodata (si, "%-50s %3ld :%s", c->name, LIST_LENGTH (&c->members), c->topic);
266     else
267     command_success_nodata (si, "%-50s %3ld", c->name, LIST_LENGTH (&c->members));
268     }
269    
270     static int
271     show_channel (channel_t *c, struct alis_query *query)
272     {
273     /* skip +s channels */
274     if (c->modes & CMODE_SEC)
275     return 0;
276    
277     if ((int) LIST_LENGTH (&c->members) < query->min || (query->max && (int) LIST_LENGTH (&c->members) > query->max))
278     return 0;
279    
280     if (query->mode)
281     {
282     if (query->mode_dir == DIR_SET)
283     {
284     if (((c->modes & query->mode) == 0) || (query->mode_key && c->key[0] == '\0') || (query->mode_limit && !c->limit))
285     return 0;
286     }
287     else if (query->mode_dir == DIR_UNSET)
288     {
289     if ((c->modes & query->mode) || (query->mode_key && c->key[0] != '\0') || (query->mode_limit && c->limit))
290     return 0;
291     }
292     else if (query->mode_dir == DIR_EQUAL)
293     {
294     if ((c->modes != query->mode) || (query->mode_key && c->key[0] == '\0') || (query->mode_limit && !c->limit))
295     return 0;
296     }
297     }
298    
299     if (match (query->mask, c->name))
300     return 0;
301    
302     if (query->topic != NULL && match (query->topic, c->topic))
303     return 0;
304    
305     if (query->skip)
306     {
307     query->skip--;
308     return 0;
309     }
310    
311     return 1;
312     }
313    
314     static void
315     alis_cmd_list (sourceinfo_t *si, int parc, char *parv[])
316     {
317     channel_t *c;
318     struct alis_query query;
319     dictionary_iteration_state_t state;
320     int maxmatch = ALIS_MAX_MATCH;
321    
322     memset (&query, 0, sizeof (struct alis_query));
323    
324     query.mask = parc >= 1 ? parv[0] : "*";
325     if (!parse_alis (si, parc - 1, parv + 1, &query))
326     return;
327    
328     logcommand (si, CMDLOG_GET, "LIST %s", query.mask);
329    
330     command_success_nodata (si, "Returning maximum of %d channel names matching '\2%s\2'", ALIS_MAX_MATCH, query.mask);
331    
332     /* hunting for one channel.. */
333     if (strchr (query.mask, '*') == NULL && strchr (query.mask, '?') == NULL)
334     {
335     if ((c = channel_find (query.mask)) != NULL)
336     {
337     if (!(c->modes & CMODE_SEC))
338     print_channel (si, c, &query);
339     }
340    
341     command_success_nodata (si, "End of output");
342     return;
343     }
344    
345     DICTIONARY_FOREACH (c, channel_t, &state, chanlist)
346     {
347     /* matches, so show it */
348     if (show_channel (c, &query))
349     {
350     print_channel (si, c, &query);
351    
352     if (--maxmatch == 0)
353     {
354     command_success_nodata (si, "Maximum channel output reached");
355     break;
356     }
357     }
358     }
359    
360     command_success_nodata (si, "End of output");
361     return;
362     }
363    
364     static void
365     alis_cmd_help (sourceinfo_t *si, int parc, char *parv[])
366     {
367     command_help (si, &alis_cmdtree);
368     }
369    
370     static void
371     alis_handler (sourceinfo_t *si, int parc, char *parv[])
372     {
373     char orig[BUFSIZE];
374     char *cmd;
375     char *text;
376    
377     /* this should never happen */
378     if (parv[0][0] == '&')
379     {
380     slog (LG_ERROR, "services(): got parv with local channel: %s", parv[0]);
381     return;
382     }
383    
384     /* make a copy of the original for debugging */
385     strlcpy (orig, parv[parc - 1], BUFSIZE);
386    
387     /* lets go through this to get the command */
388     cmd = strtok (parv[parc - 1], " ");
389     text = strtok (NULL, "");
390    
391     if (!cmd)
392     return;
393     if (*cmd == '\001')
394     {
395     handle_ctcp_common (si, cmd, text);
396     return;
397     }
398    
399     /* take the command through the hash table */
400     command_exec_split (alis, si, cmd, text, &alis_cmdtree);
401     }