ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/commandtree.C
Revision: 1.7
Committed: Thu Aug 30 19:56:24 2007 UTC (16 years, 9 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.6: +14 -13 lines
Log Message:
- put faultcodes into their own namespace
- removed old files
- limited header garbage in atheme.h
- macros to inline bools for connection_t::is_*
- put some connection_t functions into the connection_t class

File Contents

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