ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/commandtree.C
Revision: 1.2
Committed: Sat Jul 21 01:29:10 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +3 -3 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

# Content
1 /*
2 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
3 * Copyright © 2005-2006 Atheme Development Group
4 * Rights to this code are as documented in doc/pod/license.pod.
5 *
6 * Commandtree manipulation routines.
7 *
8 * $Id: commandtree.C,v 1.1 2007-07-19 08:24:56 pippijn Exp $
9 */
10
11 #include <algorithm>
12
13 #include "atheme.h"
14 #include "users.h"
15 #include "privs.h"
16
17 static char const rcsid[] = "$Id: commandtree.C,v 1.1 2007-07-19 08:24:56 pippijn Exp $";
18
19 static int text_to_parv (char *text, int maxparc, char **parv);
20
21 command_t null_cmd = { NULL, NULL, NULL, 0, NULL };
22 cmdvec null_cmdvec;
23
24 struct cmd_eq
25 {
26 cmd_eq () { }
27 cmd_eq (char const *cmd) : cmd (cmd) { }
28 cmd_eq (command_t const &cmd) : cmd (cmd.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 const char *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 it_end = this->end ();
122 cmdvec::iterator it = std::find_if (this->begin (), it_end, cmd_eq (command));
123
124 if (it != it_end)
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 *cmd, char *text, cmdvec *commandlist)
148 {
149 int parc, i;
150 char *parv[20];
151 command_t const *c;
152
153 if ((c = commandlist->find (cmd)))
154 {
155 parc = text_to_parv (text, c->maxparc, parv);
156 for (i = parc; i < (int) (sizeof (parv) / sizeof (parv[0])); i++)
157 parv[i] = NULL;
158 c->exec (svs, si, parc, parv);
159 }
160 else
161 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);
162 }
163
164 /*
165 * command_help
166 * Iterates the command tree and lists available commands.
167 *
168 * inputs -
169 * si: The origin of the request.
170 * commandtree: The command tree being listed.
171 *
172 * outputs -
173 * A list of available commands.
174 */
175 struct render_help
176 {
177 render_help (sourceinfo_t *si)
178 : si (si)
179 {
180 }
181
182 void operator () (command_t const *c)
183 {
184 /* show only the commands we have access to
185 * (taken from command_exec())
186 */
187 if (has_priv (si, c->access))
188 command_success_nodata (si, "\2%-15s\2 %s", c->name, c->desc);
189 }
190
191 sourceinfo_t *si;
192 };
193
194 void
195 command_help (sourceinfo_t *si, cmdvec *commandlist)
196 {
197 if (si->service == NULL || si->service->cmdtree == commandlist)
198 command_success_nodata (si, _("The following commands are available:"));
199 else
200 command_success_nodata (si, _("The following subcommands are available:"));
201
202 std::for_each (commandlist->begin (), commandlist->end (), render_help (si));
203 }
204
205 /* name1 name2 name3... */
206 static bool
207 string_in_list (char const *str, char const *name)
208 {
209 char *p;
210 int l;
211
212 if (str == NULL)
213 return false;
214 l = strlen (name);
215 while (*str != '\0')
216 {
217 p = strchr (str, ' ');
218 if (p != NULL ? p - str == l && !strncasecmp (str, name, p - str) : !strcasecmp (str, name))
219 return true;
220 if (p == NULL)
221 return false;
222 str = p;
223 while (*str == ' ')
224 str++;
225 }
226 return false;
227 }
228
229 /*
230 * command_help_short
231 * Iterates over the command tree and lists available commands.
232 *
233 * inputs -
234 * mynick: The nick of the services bot sending out the notices.
235 * origin: The origin of the request.
236 * commandtree: The command tree being listed.
237 * maincmds: The commands to list verbosely.
238 *
239 * outputs -
240 * A list of available commands.
241 */
242 struct render_help_short
243 {
244 render_help_short (sourceinfo_t *si, char *maincmds)
245 : si (si), maincmds (maincmds)
246 {
247 }
248
249 void operator () (command_t const *c)
250 {
251 /* show only the commands we have access to
252 * (taken from command_exec())
253 */
254 if (string_in_list (maincmds, c->name) && has_priv (si, c->access))
255 command_success_nodata (si, "\2%-15s\2 %s", c->name, c->desc);
256 }
257
258 private:
259 sourceinfo_t *si;
260 char *maincmds;
261 };
262
263 struct render_list
264 {
265 render_list (sourceinfo_t *si, string *buf, char *maincmds, size_t length)
266 : si (si), buf (buf), maincmds (maincmds), indent (length)
267 {
268 }
269
270 void operator () (command_t const *c)
271 {
272 /* show only the commands we have access to
273 * (taken from command_exec())
274 */
275 size_t l = indent;
276 if (!string_in_list (maincmds, c->name) && has_priv (si, c->access))
277 {
278 if (buf->length () > l)
279 buf->append (", ", 2);
280 if (buf->length () > 55)
281 {
282 command_success_nodata (si, "%s", buf->c_str ());
283 buf->reset ();
284 while (--l > 0)
285 buf->append (' ');
286 buf->append (' ');
287 l = indent;
288 }
289 buf->append (c->name, strlen (c->name));
290 }
291 }
292
293 private:
294 sourceinfo_t *si;
295 string *buf;
296 char *maincmds;
297 size_t indent;
298 };
299
300 void
301 command_help_short (sourceinfo_t *si, cmdvec *commandlist, char *maincmds)
302 {
303 size_t l;
304 char *lbuf;
305 string buf (256);
306
307 if (si->service == NULL || si->service->cmdtree == commandlist)
308 command_success_nodata (si, _("The following commands are available:"));
309 else
310 command_success_nodata (si, _("The following subcommands are available:"));
311
312 std::for_each (commandlist->begin (), commandlist->end (), render_help_short (si, maincmds));
313
314 command_success_nodata (si, " ");
315 lbuf = _("Other commands: ");
316 buf.append (lbuf, l = strlen (lbuf));
317
318 std::for_each (commandlist->begin (), commandlist->end (), render_list (si, &buf, maincmds, l));
319
320 if (buf.length () > l)
321 command_success_nodata (si, "%s", buf.c_str ());
322 }
323
324 static int
325 text_to_parv (char *text, int maxparc, char **parv)
326 {
327 int count = 0;
328 char *p;
329
330 if (maxparc == 0)
331 return 0;
332
333 if (!text)
334 return 0;
335
336 p = text;
337 while (count < maxparc - 1 && (parv[count] = strtok (p, " ")) != NULL)
338 count++, p = NULL;
339
340 if ((parv[count] = strtok (p, "")) != NULL)
341 {
342 p = parv[count];
343 if (*p != '\0')
344 {
345 p += strlen (p) - 1;
346 while (*p == ' ' && p > parv[count])
347 p--;
348 p[1] = '\0';
349 }
350 count++;
351 }
352 return count;
353 }