ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/commandtree.C
Revision: 1.11
Committed: Sat Sep 22 14:27:30 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.10: +1 -2 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

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