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, 7 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

# 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.10 2007-09-16 18:54:44 pippijn Exp $";
14
15 #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 cmd_eq () : cmd (0) { }
26 cmd_eq (char const * const command) : cmd (command) { }
27 cmd_eq (command_t const &command) : cmd (command.name) { }
28
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 char const * const cmd;
53 } 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 operator << (cmdvec &commandlist, command_t const &cmd)
70 {
71 if (std::find_if (commandlist.begin (), commandlist.end (), cmd_eq (cmd)) != commandlist.end ())
72 {
73 slog (LG_INFO, "command_add(): command %s already in the list", cmd.name);
74 return;
75 }
76
77 commandlist.push_back (&cmd);
78 }
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 commandlist << *cmd[i];
87 }
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 operator >> (cmdvec &commandlist, command_t const &cmd)
104 {
105 commandlist.erase (std::find_if (commandlist.begin (), commandlist.end (), cmd_eq (cmd)));
106 }
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 commandlist >> *cmd[i];
115 }
116
117 command_t const *
118 cmdvec::find (char const *command)
119 {
120 cmdvec::iterator et = end ();
121 cmdvec::iterator it = std::find_if (begin (), et, cmd_eq (command));
122
123 if (it != et)
124 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 command_fail (si, fault::noprivs, _("You do not have %s privilege."), access);
140 else
141 command_fail (si, fault::noprivs, _("You are not authorized to perform this operation."));
142 /*snoop(_("DENIED CMD: \2%s\2 used %s %s"), origin, svs->name, cmd); */
143 }
144
145 void
146 command_exec_split (service_t *svs, sourceinfo_t *si, char const * const cmd, char const * const text, cmdvec &commandlist)
147 {
148 char *parv[20] = { 0 };
149 command_t const *c;
150
151 if ((c = commandlist.find (cmd)))
152 {
153 unsigned const parc = sjtoken (text, ' ', parv, c->maxparc);
154 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 render_help (sourceinfo_t *info)
174 : si (info)
175 {
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 command_help (sourceinfo_t *si, cmdvec &commandlist)
192 {
193 if (si->service == NULL || si->service->cmdtree == &commandlist)
194 command_success_nodata (si, _("The following commands are available:"));
195 else
196 command_success_nodata (si, _("The following subcommands are available:"));
197
198 std::for_each (commandlist.begin (), commandlist.end (), render_help (si));
199 }
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 render_help_short (sourceinfo_t *info, char const * const cmdlist)
241 : si (info), maincmds (cmdlist)
242 {
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 char const * const maincmds;
257 };
258
259 struct render_list
260 {
261 render_list (sourceinfo_t *info, dynstr &str, char const * const cmdlist, size_t length)
262 : si (info), buf (str), maincmds (cmdlist), indent (length)
263 {
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 if (buf.size () > l)
275 buf.add (", ", 2);
276 if (buf.size () > 55)
277 {
278 command_success_nodata (si, "%s", buf.c_str ());
279 buf.clear ();
280 while (--l > 0)
281 buf.add (' ');
282 buf.add (' ');
283 l = indent;
284 }
285 buf.add (c->name, strlen (c->name));
286 }
287 }
288
289 private:
290 sourceinfo_t *si;
291 dynstr &buf;
292 char const * const maincmds;
293 size_t indent;
294 };
295
296 void
297 command_help_short (sourceinfo_t *si, cmdvec &commandlist, char const * const maincmds)
298 {
299 size_t l;
300 char *lbuf;
301 dynstr buf (256);
302
303 if (si->service == NULL || si->service->cmdtree == &commandlist)
304 command_success_nodata (si, _("The following commands are available:"));
305 else
306 command_success_nodata (si, _("The following subcommands are available:"));
307
308 std::for_each (commandlist.begin (), commandlist.end (), render_help_short (si, maincmds));
309
310 command_success_nodata (si, " ");
311 lbuf = _("Other commands: ");
312 buf.add (lbuf, l = strlen (lbuf));
313
314 std::for_each (commandlist.begin (), commandlist.end (), render_list (si, buf, maincmds, l));
315
316 if (buf.size () > l)
317 command_success_nodata (si, "%s", buf.c_str ());
318 }