ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/commandtree.C
Revision: 1.6
Committed: Wed Aug 29 21:42:28 2007 UTC (16 years, 9 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.5: +2 -3 lines
Log Message:
fixed bug in user introduction

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