ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/commandtree.C
Revision: 1.10
Committed: Sun Sep 16 18:54:44 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.9: +8 -3 lines
Log Message:
#defines to enum

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.10 static char const rcsid[] = "$Id: commandtree.C,v 1.9 2007-09-09 20:05:52 pippijn Exp $";
14 pippijn 1.9
15 pippijn 1.1 #include <algorithm>
16    
17     #include "atheme.h"
18 pippijn 1.8 #include <common/string.h>
19 pippijn 1.1 #include "users.h"
20     #include "privs.h"
21    
22     cmdvec null_cmdvec;
23    
24     struct cmd_eq
25     {
26 pippijn 1.3 cmd_eq () : cmd (0) { }
27     cmd_eq (char const * const command) : cmd (command) { }
28     cmd_eq (command_t const &command) : cmd (command.name) { }
29 pippijn 1.1
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 pippijn 1.3 char const * const cmd;
54 pippijn 1.1 } 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 pippijn 1.3 operator << (cmdvec &commandlist, command_t const &cmd)
71 pippijn 1.1 {
72 pippijn 1.3 if (std::find_if (commandlist.begin (), commandlist.end (), cmd_eq (cmd)) != commandlist.end ())
73 pippijn 1.1 {
74     slog (LG_INFO, "command_add(): command %s already in the list", cmd.name);
75     return;
76     }
77    
78 pippijn 1.3 commandlist.push_back (&cmd);
79 pippijn 1.1 }
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 pippijn 1.3 commandlist << *cmd[i];
88 pippijn 1.1 }
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 pippijn 1.3 operator >> (cmdvec &commandlist, command_t const &cmd)
105 pippijn 1.1 {
106 pippijn 1.3 commandlist.erase (std::find_if (commandlist.begin (), commandlist.end (), cmd_eq (cmd)));
107 pippijn 1.1 }
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 pippijn 1.3 commandlist >> *cmd[i];
116 pippijn 1.1 }
117    
118     command_t const *
119     cmdvec::find (char const *command)
120     {
121 pippijn 1.3 cmdvec::iterator et = end ();
122     cmdvec::iterator it = std::find_if (begin (), et, cmd_eq (command));
123 pippijn 1.1
124 pippijn 1.3 if (it != et)
125 pippijn 1.1 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 pippijn 1.7 command_fail (si, fault::noprivs, _("You do not have %s privilege."), access);
141 pippijn 1.1 else
142 pippijn 1.7 command_fail (si, fault::noprivs, _("You are not authorized to perform this operation."));
143 pippijn 1.1 /*snoop(_("DENIED CMD: \2%s\2 used %s %s"), origin, svs->name, cmd); */
144     }
145    
146     void
147 pippijn 1.3 command_exec_split (service_t *svs, sourceinfo_t *si, char const * const cmd, char const * const text, cmdvec &commandlist)
148 pippijn 1.1 {
149 pippijn 1.5 char *parv[20] = { 0 };
150 pippijn 1.1 command_t const *c;
151    
152 pippijn 1.3 if ((c = commandlist.find (cmd)))
153 pippijn 1.1 {
154 pippijn 1.4 unsigned const parc = sjtoken (text, ' ', parv, c->maxparc);
155 pippijn 1.1 c->exec (svs, si, parc, parv);
156     }
157     else
158     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);
159     }
160    
161     /*
162     * command_help
163     * Iterates the command tree and lists available commands.
164     *
165     * inputs -
166     * si: The origin of the request.
167     * commandtree: The command tree being listed.
168     *
169     * outputs -
170     * A list of available commands.
171     */
172     struct render_help
173     {
174 pippijn 1.3 render_help (sourceinfo_t *info)
175     : si (info)
176 pippijn 1.1 {
177     }
178    
179     void operator () (command_t const *c)
180     {
181     /* show only the commands we have access to
182     * (taken from command_exec())
183     */
184     if (has_priv (si, c->access))
185     command_success_nodata (si, "\2%-15s\2 %s", c->name, c->desc);
186     }
187    
188     sourceinfo_t *si;
189     };
190    
191     void
192 pippijn 1.3 command_help (sourceinfo_t *si, cmdvec &commandlist)
193 pippijn 1.1 {
194 pippijn 1.3 if (si->service == NULL || si->service->cmdtree == &commandlist)
195 pippijn 1.1 command_success_nodata (si, _("The following commands are available:"));
196     else
197     command_success_nodata (si, _("The following subcommands are available:"));
198    
199 pippijn 1.3 std::for_each (commandlist.begin (), commandlist.end (), render_help (si));
200 pippijn 1.1 }
201    
202     /* name1 name2 name3... */
203     static bool
204     string_in_list (char const *str, char const *name)
205     {
206     char *p;
207     int l;
208    
209     if (str == NULL)
210     return false;
211     l = strlen (name);
212     while (*str != '\0')
213     {
214     p = strchr (str, ' ');
215     if (p != NULL ? p - str == l && !strncasecmp (str, name, p - str) : !strcasecmp (str, name))
216     return true;
217     if (p == NULL)
218     return false;
219     str = p;
220     while (*str == ' ')
221     str++;
222     }
223     return false;
224     }
225    
226     /*
227     * command_help_short
228     * Iterates over the command tree and lists available commands.
229     *
230     * inputs -
231     * mynick: The nick of the services bot sending out the notices.
232     * origin: The origin of the request.
233     * commandtree: The command tree being listed.
234     * maincmds: The commands to list verbosely.
235     *
236     * outputs -
237     * A list of available commands.
238     */
239     struct render_help_short
240     {
241 pippijn 1.3 render_help_short (sourceinfo_t *info, char const * const cmdlist)
242     : si (info), maincmds (cmdlist)
243 pippijn 1.1 {
244     }
245    
246     void operator () (command_t const *c)
247     {
248     /* show only the commands we have access to
249     * (taken from command_exec())
250     */
251     if (string_in_list (maincmds, c->name) && has_priv (si, c->access))
252     command_success_nodata (si, "\2%-15s\2 %s", c->name, c->desc);
253     }
254    
255     private:
256     sourceinfo_t *si;
257 pippijn 1.3 char const * const maincmds;
258 pippijn 1.1 };
259    
260     struct render_list
261     {
262 pippijn 1.3 render_list (sourceinfo_t *info, dynstr &str, char const * const cmdlist, size_t length)
263     : si (info), buf (str), maincmds (cmdlist), indent (length)
264 pippijn 1.1 {
265     }
266    
267     void operator () (command_t const *c)
268     {
269     /* show only the commands we have access to
270     * (taken from command_exec())
271     */
272     size_t l = indent;
273     if (!string_in_list (maincmds, c->name) && has_priv (si, c->access))
274     {
275 pippijn 1.7 if (buf.size () > l)
276     buf.add (", ", 2);
277     if (buf.size () > 55)
278 pippijn 1.1 {
279 pippijn 1.3 command_success_nodata (si, "%s", buf.c_str ());
280 pippijn 1.7 buf.clear ();
281 pippijn 1.1 while (--l > 0)
282 pippijn 1.7 buf.add (' ');
283     buf.add (' ');
284 pippijn 1.1 l = indent;
285     }
286 pippijn 1.7 buf.add (c->name, strlen (c->name));
287 pippijn 1.1 }
288     }
289    
290     private:
291     sourceinfo_t *si;
292 pippijn 1.3 dynstr &buf;
293     char const * const maincmds;
294 pippijn 1.1 size_t indent;
295     };
296    
297     void
298 pippijn 1.3 command_help_short (sourceinfo_t *si, cmdvec &commandlist, char const * const maincmds)
299 pippijn 1.1 {
300     size_t l;
301     char *lbuf;
302 pippijn 1.3 dynstr buf (256);
303 pippijn 1.1
304 pippijn 1.3 if (si->service == NULL || si->service->cmdtree == &commandlist)
305 pippijn 1.1 command_success_nodata (si, _("The following commands are available:"));
306     else
307     command_success_nodata (si, _("The following subcommands are available:"));
308    
309 pippijn 1.3 std::for_each (commandlist.begin (), commandlist.end (), render_help_short (si, maincmds));
310 pippijn 1.1
311     command_success_nodata (si, " ");
312     lbuf = _("Other commands: ");
313 pippijn 1.7 buf.add (lbuf, l = strlen (lbuf));
314 pippijn 1.1
315 pippijn 1.3 std::for_each (commandlist.begin (), commandlist.end (), render_list (si, buf, maincmds, l));
316 pippijn 1.1
317 pippijn 1.7 if (buf.size () > l)
318 pippijn 1.1 command_success_nodata (si, "%s", buf.c_str ());
319     }