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

File Contents

# Content
1 /**
2 * commandtree.C: Commandtree manipulation routines.
3 *
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 * Rights to this code are as documented in doc/pod/license.pod.
10 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
11 */
12
13 static char const rcsid[] = "$Id: commandtree.C,v 1.9 2007-09-09 20:05:52 pippijn Exp $";
14
15 #include <algorithm>
16
17 #include "atheme.h"
18 #include <common/string.h>
19 #include "users.h"
20 #include "privs.h"
21
22 cmdvec null_cmdvec;
23
24 struct cmd_eq
25 {
26 cmd_eq () : cmd (0) { }
27 cmd_eq (char const * const command) : cmd (command) { }
28 cmd_eq (command_t const &command) : cmd (command.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 char const * const 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 et = end ();
122 cmdvec::iterator it = std::find_if (begin (), et, cmd_eq (command));
123
124 if (it != et)
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 const * const cmd, char const * const text, cmdvec &commandlist)
148 {
149 char *parv[20] = { 0 };
150 command_t const *c;
151
152 if ((c = commandlist.find (cmd)))
153 {
154 unsigned const parc = sjtoken (text, ' ', parv, c->maxparc);
155 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 render_help (sourceinfo_t *info)
175 : si (info)
176 {
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 command_help (sourceinfo_t *si, cmdvec &commandlist)
193 {
194 if (si->service == NULL || si->service->cmdtree == &commandlist)
195 command_success_nodata (si, _("The following commands are available:"));
196 else
197 command_success_nodata (si, _("The following subcommands are available:"));
198
199 std::for_each (commandlist.begin (), commandlist.end (), render_help (si));
200 }
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 render_help_short (sourceinfo_t *info, char const * const cmdlist)
242 : si (info), maincmds (cmdlist)
243 {
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 char const * const maincmds;
258 };
259
260 struct render_list
261 {
262 render_list (sourceinfo_t *info, dynstr &str, char const * const cmdlist, size_t length)
263 : si (info), buf (str), maincmds (cmdlist), indent (length)
264 {
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 if (buf.size () > l)
276 buf.add (", ", 2);
277 if (buf.size () > 55)
278 {
279 command_success_nodata (si, "%s", buf.c_str ());
280 buf.clear ();
281 while (--l > 0)
282 buf.add (' ');
283 buf.add (' ');
284 l = indent;
285 }
286 buf.add (c->name, strlen (c->name));
287 }
288 }
289
290 private:
291 sourceinfo_t *si;
292 dynstr &buf;
293 char const * const maincmds;
294 size_t indent;
295 };
296
297 void
298 command_help_short (sourceinfo_t *si, cmdvec &commandlist, char const * const maincmds)
299 {
300 size_t l;
301 char *lbuf;
302 dynstr buf (256);
303
304 if (si->service == NULL || si->service->cmdtree == &commandlist)
305 command_success_nodata (si, _("The following commands are available:"));
306 else
307 command_success_nodata (si, _("The following subcommands are available:"));
308
309 std::for_each (commandlist.begin (), commandlist.end (), render_help_short (si, maincmds));
310
311 command_success_nodata (si, " ");
312 lbuf = _("Other commands: ");
313 buf.add (lbuf, l = strlen (lbuf));
314
315 std::for_each (commandlist.begin (), commandlist.end (), render_list (si, buf, maincmds, l));
316
317 if (buf.size () > l)
318 command_success_nodata (si, "%s", buf.c_str ());
319 }