ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/src/commandtree.C
Revision: 1.1
Committed: Thu Jul 19 08:24:56 2007 UTC (19 years, 2 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Log Message:
initial import. the most important changes since Atheme are:
- fixed many memory leaks
- fixed many bugs
- converted to C++ and use more STL containers
- added a (not very enhanced yet) perl module
- greatly improved XML-RPC speed
- added a JSON-RPC module with code from json-cpp
- added a valgrind memcheck module to operserv
- added a more object oriented base64 implementation
- added a specialised unit test framework
- improved stability
- use gettimeofday() if available
- reworked adding/removing commands
- MemoServ IGNORE DEL can now remove indices

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
3     * Copyright © 2005-2006 Atheme Development Group
4     * Rights to this code are as documented in doc/LICENSE.
5     *
6     * Commandtree manipulation routines.
7     *
8     * $Id: commandtree.C,v 1.1 2007-07-11 11:04:47 pippijn Exp $
9     */
10    
11     #include <algorithm>
12    
13     #include "atheme.h"
14     #include "users.h"
15     #include "privs.h"
16    
17     static char const rcsid[] = "$Id: commandtree.C,v 1.1 2007-07-11 11:04:47 pippijn Exp $";
18    
19     static int text_to_parv (char *text, int maxparc, char **parv);
20    
21     command_t null_cmd = { NULL, NULL, NULL, 0, NULL };
22     cmdvec null_cmdvec;
23    
24     struct cmd_eq
25     {
26     cmd_eq () { }
27     cmd_eq (char const *cmd) : cmd (cmd) { }
28     cmd_eq (command_t const &cmd) : cmd (cmd.name) { }
29    
30     bool operator () (command_t const *c)
31     {
32     return !strcasecmp (c->name, cmd);
33     }
34    
35     /******/
36    
37     bool operator () (char const *c1, command_t const *c2)
38     {
39     return !strcasecmp (c1, c2->name);
40     }
41    
42     bool operator () (command_t const *c1, char const *c2)
43     {
44     return !strcasecmp (c1->name, c2);
45     }
46    
47     bool operator () (command_t const *c1, command_t const *c2)
48     {
49     return !strcasecmp (c1->name, c2->name);
50     }
51    
52     private:
53     const char *cmd;
54     } cmd_compare;
55    
56     /*
57     * command_add_many()
58     *
59     * Inputs:
60     * array of commands to add, list to add them to.
61     *
62     * Output:
63     * none
64     *
65     * Side Effects:
66     * adds an array of commands to a command list,
67     * via command_add().
68     */
69     void
70     operator << (cmdvec *commandlist, command_t const &cmd)
71     {
72     if (std::find_if (commandlist->begin (), commandlist->end (), cmd_eq (cmd)) != commandlist->end ())
73     {
74     slog (LG_INFO, "command_add(): command %s already in the list", cmd.name);
75     return;
76     }
77    
78     commandlist->push_back (&cmd);
79     }
80    
81     void
82     operator << (cmdvec &commandlist, command_t const *cmd[])
83     {
84     unsigned int i;
85    
86     for (i = 0; cmd[i] != NULL; i++)
87     &commandlist << *cmd[i];
88     }
89    
90     /*
91     * command_delete_many()
92     *
93     * Inputs:
94     * array of commands to delete, list to delete them from.
95     *
96     * Output:
97     * none
98     *
99     * Side Effects:
100     * deletes an array of commands from a command list,
101     * via command_delete().
102     */
103     void
104     operator >> (cmdvec *commandlist, command_t const &cmd)
105     {
106     commandlist->erase (std::find_if (commandlist->begin (), commandlist->end (), cmd_eq (cmd)));
107     }
108    
109     void
110     operator >> (cmdvec &commandlist, command_t const *cmd[])
111     {
112     unsigned int i;
113    
114     for (i = 0; cmd[i] != NULL; i++)
115     &commandlist >> *cmd[i];
116     }
117    
118     command_t const *
119     cmdvec::find (char const *command)
120     {
121     cmdvec::iterator it_end = this->end ();
122     cmdvec::iterator it = std::find_if (this->begin (), it_end, cmd_eq (command));
123    
124     if (it != it_end)
125     return *it;
126    
127     return NULL;
128     }
129    
130     void
131     command_t::exec (service_t *svs, sourceinfo_t *si, int parc, char *parv[]) const
132     {
133     if (has_priv (si, access))
134     {
135     cmd (si, parc, parv);
136     return;
137     }
138    
139     if (has_any_privs (si))
140     command_fail (si, fault_noprivs, _("You do not have %s privilege."), access);
141     else
142     command_fail (si, fault_noprivs, _("You are not authorized to perform this operation."));
143     /*snoop(_("DENIED CMD: \2%s\2 used %s %s"), origin, svs->name, cmd); */
144     }
145    
146     void
147     command_exec_split (service_t *svs, sourceinfo_t *si, char *cmd, char *text, cmdvec *commandlist)
148     {
149     int parc, i;
150     char *parv[20];
151     command_t const *c;
152    
153     if ((c = commandlist->find (cmd)))
154     {
155     parc = text_to_parv (text, c->maxparc, parv);
156     for (i = parc; i < (int) (sizeof (parv) / sizeof (parv[0])); i++)
157     parv[i] = NULL;
158     c->exec (svs, si, parc, parv);
159     }
160     else
161     notice (svs->name, si->su->nick, _("Invalid command. Use \2/%s%s help\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", svs->disp);
162     }
163    
164     /*
165     * command_help
166     * Iterates the command tree and lists available commands.
167     *
168     * inputs -
169     * si: The origin of the request.
170     * commandtree: The command tree being listed.
171     *
172     * outputs -
173     * A list of available commands.
174     */
175     struct render_help
176     {
177     render_help (sourceinfo_t *si)
178     : si (si)
179     {
180     }
181    
182     void operator () (command_t const *c)
183     {
184     /* show only the commands we have access to
185     * (taken from command_exec())
186     */
187     if (has_priv (si, c->access))
188     command_success_nodata (si, "\2%-15s\2 %s", c->name, c->desc);
189     }
190    
191     sourceinfo_t *si;
192     };
193    
194     void
195     command_help (sourceinfo_t *si, cmdvec *commandlist)
196     {
197     if (si->service == NULL || si->service->cmdtree == commandlist)
198     command_success_nodata (si, _("The following commands are available:"));
199     else
200     command_success_nodata (si, _("The following subcommands are available:"));
201    
202     std::for_each (commandlist->begin (), commandlist->end (), render_help (si));
203     }
204    
205     /* name1 name2 name3... */
206     static bool
207     string_in_list (char const *str, char const *name)
208     {
209     char *p;
210     int l;
211    
212     if (str == NULL)
213     return false;
214     l = strlen (name);
215     while (*str != '\0')
216     {
217     p = strchr (str, ' ');
218     if (p != NULL ? p - str == l && !strncasecmp (str, name, p - str) : !strcasecmp (str, name))
219     return true;
220     if (p == NULL)
221     return false;
222     str = p;
223     while (*str == ' ')
224     str++;
225     }
226     return false;
227     }
228    
229     /*
230     * command_help_short
231     * Iterates over the command tree and lists available commands.
232     *
233     * inputs -
234     * mynick: The nick of the services bot sending out the notices.
235     * origin: The origin of the request.
236     * commandtree: The command tree being listed.
237     * maincmds: The commands to list verbosely.
238     *
239     * outputs -
240     * A list of available commands.
241     */
242     struct render_help_short
243     {
244     render_help_short (sourceinfo_t *si, char *maincmds)
245     : si (si), maincmds (maincmds)
246     {
247     }
248    
249     void operator () (command_t const *c)
250     {
251     /* show only the commands we have access to
252     * (taken from command_exec())
253     */
254     if (string_in_list (maincmds, c->name) && has_priv (si, c->access))
255     command_success_nodata (si, "\2%-15s\2 %s", c->name, c->desc);
256     }
257    
258     private:
259     sourceinfo_t *si;
260     char *maincmds;
261     };
262    
263     struct render_list
264     {
265     render_list (sourceinfo_t *si, string *buf, char *maincmds, size_t length)
266     : si (si), buf (buf), maincmds (maincmds), indent (length)
267     {
268     }
269    
270     void operator () (command_t const *c)
271     {
272     /* show only the commands we have access to
273     * (taken from command_exec())
274     */
275     size_t l = indent;
276     if (!string_in_list (maincmds, c->name) && has_priv (si, c->access))
277     {
278     if (buf->length () > l)
279     buf->append (", ", 2);
280     if (buf->length () > 55)
281     {
282     command_success_nodata (si, "%s", buf->c_str ());
283     buf->reset ();
284     while (--l > 0)
285     buf->append (' ');
286     buf->append (' ');
287     l = indent;
288     }
289     buf->append (c->name, strlen (c->name));
290     }
291     }
292    
293     private:
294     sourceinfo_t *si;
295     string *buf;
296     char *maincmds;
297     size_t indent;
298     };
299    
300     void
301     command_help_short (sourceinfo_t *si, cmdvec *commandlist, char *maincmds)
302     {
303     size_t l;
304     char *lbuf;
305     string buf (256);
306    
307     if (si->service == NULL || si->service->cmdtree == commandlist)
308     command_success_nodata (si, _("The following commands are available:"));
309     else
310     command_success_nodata (si, _("The following subcommands are available:"));
311    
312     std::for_each (commandlist->begin (), commandlist->end (), render_help_short (si, maincmds));
313    
314     command_success_nodata (si, " ");
315     lbuf = _("Other commands: ");
316     buf.append (lbuf, l = strlen (lbuf));
317    
318     std::for_each (commandlist->begin (), commandlist->end (), render_list (si, &buf, maincmds, l));
319    
320     if (buf.length () > l)
321     command_success_nodata (si, "%s", buf.c_str ());
322     }
323    
324     static int
325     text_to_parv (char *text, int maxparc, char **parv)
326     {
327     int count = 0;
328     char *p;
329    
330     if (maxparc == 0)
331     return 0;
332    
333     if (!text)
334     return 0;
335    
336     p = text;
337     while (count < maxparc - 1 && (parv[count] = strtok (p, " ")) != NULL)
338     count++, p = NULL;
339    
340     if ((parv[count] = strtok (p, "")) != NULL)
341     {
342     p = parv[count];
343     if (*p != '\0')
344     {
345     p += strlen (p) - 1;
346     while (*p == ' ' && p > parv[count])
347     p--;
348     p[1] = '\0';
349     }
350     count++;
351     }
352     return count;
353     }