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

# Content
1 /*
2 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
3 * Rights to this code are as documented in doc/pod/gplicense.pod.
4 *
5 * Commandtree manipulation routines.
6 *
7 * $Id: commandtree.C,v 1.6 2007-08-29 21:42:28 pippijn Exp $
8 */
9
10 #include <algorithm>
11
12 #include "atheme.h"
13 #include <common/dynbuf.h>
14 #include "users.h"
15 #include "privs.h"
16
17 static char const rcsid[] = "$Id: commandtree.C,v 1.6 2007-08-29 21:42:28 pippijn Exp $";
18
19 cmdvec null_cmdvec;
20
21 struct cmd_eq
22 {
23 cmd_eq () : cmd (0) { }
24 cmd_eq (char const * const command) : cmd (command) { }
25 cmd_eq (command_t const &command) : cmd (command.name) { }
26
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 char const * const cmd;
51 } 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 operator << (cmdvec &commandlist, command_t const &cmd)
68 {
69 if (std::find_if (commandlist.begin (), commandlist.end (), cmd_eq (cmd)) != commandlist.end ())
70 {
71 slog (LG_INFO, "command_add(): command %s already in the list", cmd.name);
72 return;
73 }
74
75 commandlist.push_back (&cmd);
76 }
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 commandlist << *cmd[i];
85 }
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 operator >> (cmdvec &commandlist, command_t const &cmd)
102 {
103 commandlist.erase (std::find_if (commandlist.begin (), commandlist.end (), cmd_eq (cmd)));
104 }
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 commandlist >> *cmd[i];
113 }
114
115 command_t const *
116 cmdvec::find (char const *command)
117 {
118 cmdvec::iterator et = end ();
119 cmdvec::iterator it = std::find_if (begin (), et, cmd_eq (command));
120
121 if (it != et)
122 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 command_fail (si, fault::noprivs, _("You do not have %s privilege."), access);
138 else
139 command_fail (si, fault::noprivs, _("You are not authorized to perform this operation."));
140 /*snoop(_("DENIED CMD: \2%s\2 used %s %s"), origin, svs->name, cmd); */
141 }
142
143 void
144 command_exec_split (service_t *svs, sourceinfo_t *si, char const * const cmd, char const * const text, cmdvec &commandlist)
145 {
146 char *parv[20] = { 0 };
147 command_t const *c;
148
149 if ((c = commandlist.find (cmd)))
150 {
151 unsigned const parc = sjtoken (text, ' ', parv, c->maxparc);
152 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 render_help (sourceinfo_t *info)
172 : si (info)
173 {
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 command_help (sourceinfo_t *si, cmdvec &commandlist)
190 {
191 if (si->service == NULL || si->service->cmdtree == &commandlist)
192 command_success_nodata (si, _("The following commands are available:"));
193 else
194 command_success_nodata (si, _("The following subcommands are available:"));
195
196 std::for_each (commandlist.begin (), commandlist.end (), render_help (si));
197 }
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 render_help_short (sourceinfo_t *info, char const * const cmdlist)
239 : si (info), maincmds (cmdlist)
240 {
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 char const * const maincmds;
255 };
256
257 struct render_list
258 {
259 render_list (sourceinfo_t *info, dynstr &str, char const * const cmdlist, size_t length)
260 : si (info), buf (str), maincmds (cmdlist), indent (length)
261 {
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 if (buf.size () > l)
273 buf.add (", ", 2);
274 if (buf.size () > 55)
275 {
276 command_success_nodata (si, "%s", buf.c_str ());
277 buf.clear ();
278 while (--l > 0)
279 buf.add (' ');
280 buf.add (' ');
281 l = indent;
282 }
283 buf.add (c->name, strlen (c->name));
284 }
285 }
286
287 private:
288 sourceinfo_t *si;
289 dynstr &buf;
290 char const * const maincmds;
291 size_t indent;
292 };
293
294 void
295 command_help_short (sourceinfo_t *si, cmdvec &commandlist, char const * const maincmds)
296 {
297 size_t l;
298 char *lbuf;
299 dynstr buf (256);
300
301 if (si->service == NULL || si->service->cmdtree == &commandlist)
302 command_success_nodata (si, _("The following commands are available:"));
303 else
304 command_success_nodata (si, _("The following subcommands are available:"));
305
306 std::for_each (commandlist.begin (), commandlist.end (), render_help_short (si, maincmds));
307
308 command_success_nodata (si, " ");
309 lbuf = _("Other commands: ");
310 buf.add (lbuf, l = strlen (lbuf));
311
312 std::for_each (commandlist.begin (), commandlist.end (), render_list (si, buf, maincmds, l));
313
314 if (buf.size () > l)
315 command_success_nodata (si, "%s", buf.c_str ());
316 }