ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/commands.c
Revision: 3389
Committed: Fri Apr 25 14:12:15 2014 UTC (9 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 6785 byte(s)
Log Message:
- Imported ircservices-5.1.24

File Contents

# Content
1 /* Routines for looking up commands in a *Serv command list.
2 *
3 * IRC Services is copyright (c) 1996-2009 Andrew Church.
4 * E-mail: <achurch@achurch.org>
5 * Parts written by Andrew Kempe and others.
6 * This program is free but copyrighted software; see the file GPL.txt for
7 * details.
8 */
9
10 #include "services.h"
11 #include "modules.h"
12 #include "commands.h"
13 #include "language.h"
14
15 /*************************************************************************/
16
17 typedef struct commandlist_ CommandList;
18 typedef struct commandarray_ CommandArray;
19
20 struct commandlist_ {
21 CommandList *next, *prev;
22 Module *id;
23 CommandArray *first_array;
24 };
25
26 struct commandarray_ {
27 CommandArray *next, *prev;
28 Command *commands;
29 };
30
31 /*************************************************************************/
32
33 /* List of all commands registered. */
34 static CommandList *cmdlist;
35
36 /*************************************************************************/
37 /*************************************************************************/
38
39 /* Set up a new command list using the given module pointer as an ID value.
40 * Fails if a command list associated with `id' already exists.
41 */
42
43 int new_commandlist(Module *id)
44 {
45 CommandList *cl;
46
47 LIST_SEARCH_SCALAR(cmdlist, id, id, cl);
48 if (cl)
49 return 0;
50 cl = smalloc(sizeof(*cl));
51 cl->id = id;
52 cl->first_array = NULL;
53 LIST_INSERT(cl, cmdlist);
54 return 1;
55 }
56
57 /*************************************************************************/
58
59 /* Register a command array under the given ID. Fails if there is no
60 * command list associated with `id', `array' is NULL, `array' has already
61 * been added to the list, or there are multiple command entries in `array'
62 * with the same name (case-insensitive). If an entry in `array' has the
63 * same name as a previously-registered entry, the entry in `array' will
64 * take precendence, and a pointer to the previous entry will be stored in
65 * the `next' field of the entry.
66 */
67
68 int register_commands(Module *id, Command *array)
69 {
70 CommandList *cl;
71 CommandArray *ca;
72 Command *c, *c2;
73
74 /* Basic sanity checking */
75 if (!array)
76 return 0;
77 LIST_SEARCH_SCALAR(cmdlist, id, id, cl);
78 if (!cl)
79 return 0;
80 LIST_SEARCH_SCALAR(cl->first_array, commands, array, ca);
81 if (ca)
82 return 0;
83 /* Check for duplicate commands and set `next' pointers */
84 for (c = array; c->name; c++) {
85 for (c2 = c+1; c2->name; c2++) {
86 if (stricmp(c->name, c2->name) == 0)
87 return 0;
88 }
89 c->next = lookup_cmd(id, c->name);
90 }
91 /* All's well, insert it in the list and return success */
92 ca = smalloc(sizeof(*ca));
93 ca->commands = array;
94 LIST_INSERT(ca, cl->first_array);
95 return 1;
96 }
97
98 /*************************************************************************/
99
100 /* Unregister a command array from the given ID. Fails if there is no
101 * command list associated with `id' or `array' was not in the list in the
102 * first place.
103 */
104
105 int unregister_commands(Module *id, Command *array)
106 {
107 CommandList *cl;
108 CommandArray *ca;
109
110 LIST_SEARCH_SCALAR(cmdlist, id, id, cl);
111 if (!cl)
112 return 0;
113 LIST_SEARCH_SCALAR(cl->first_array, commands, array, ca);
114 if (!ca)
115 return 0;
116 LIST_REMOVE(ca, cl->first_array);
117 free(ca);
118 return 1;
119 }
120
121 /*************************************************************************/
122
123 /* Delete the command list associated with the given ID. Fails if there is
124 * no command list associated with `id' or the command list is not empty.
125 */
126
127 int del_commandlist(Module *id)
128 {
129 CommandList *cl;
130
131 LIST_SEARCH_SCALAR(cmdlist, id, id, cl);
132 if (!cl || cl->first_array)
133 return 0;
134 LIST_REMOVE(cl, cmdlist);
135 free(cl);
136 return 1;
137 }
138
139 /*************************************************************************/
140 /*************************************************************************/
141
142 /* Returns the Command structure associated with the given command for the
143 * given command list (`id'), or NULL if no such command exists.
144 */
145
146 Command *lookup_cmd(Module *id, const char *name)
147 {
148 CommandList *cl;
149 CommandArray *ca;
150 Command *c;
151
152 LIST_SEARCH_SCALAR(cmdlist, id, id, cl);
153 if (!cl)
154 return NULL;
155 LIST_FOREACH (ca, cl->first_array) {
156 for (c = ca->commands; c->name; c++) {
157 if (stricmp(c->name, name) == 0)
158 return c;
159 }
160 }
161 return NULL;
162 }
163
164 /*************************************************************************/
165
166 /* Run the routine for the given command, if it exists and the user has
167 * privilege to do so; if not, print an appropriate error message.
168 */
169
170 void run_cmd(const char *service, User *u, Module *id, const char *cmd)
171 {
172 Command *c = lookup_cmd(id, cmd);
173
174 if (c && c->routine) {
175 if ((c->has_priv == NULL) || c->has_priv(u))
176 c->routine(u);
177 else
178 notice_lang(service, u, ACCESS_DENIED);
179 } else {
180 notice_lang(service, u, UNKNOWN_COMMAND_HELP, cmd, service);
181 }
182 }
183
184 /*************************************************************************/
185
186 /* Print a help message for the given command. Multiple spaces between
187 * words are compressed to a single space before looking up the command
188 * (this will cause `cmd' to be modified).
189 */
190
191 void help_cmd(const char *service, User *u, Module *id, char *cmd)
192 {
193 Command *c;
194 char *s;
195
196 s = cmd-1;
197 while ((s = strpbrk(s+1, " \t")) != NULL) {
198 char *t = s + strspn(s, " \t");
199 if (t > s+1)
200 memmove(s+1, t, strlen(t)+1);
201 }
202
203 c = lookup_cmd(id, cmd);
204 if (c) {
205 const char *p1 = c->help_param1,
206 *p2 = c->help_param2,
207 *p3 = c->help_param3,
208 *p4 = c->help_param4;
209
210 if (c->helpmsg_all >= 0)
211 notice_help(service, u, c->helpmsg_all, p1, p2, p3, p4);
212
213 if (is_oper(u)) {
214 if (c->helpmsg_oper >= 0)
215 notice_help(service, u, c->helpmsg_oper, p1, p2, p3, p4);
216 else if (c->helpmsg_all < 0)
217 notice_lang(service, u, NO_HELP_AVAILABLE, cmd);
218 } else {
219 if (c->helpmsg_reg >= 0)
220 notice_help(service, u, c->helpmsg_reg, p1, p2, p3, p4);
221 else if (c->helpmsg_all < 0)
222 notice_lang(service, u, NO_HELP_AVAILABLE, cmd);
223 }
224
225 } else {
226
227 notice_lang(service, u, NO_HELP_AVAILABLE, cmd);
228
229 }
230 }
231
232 /*************************************************************************/
233
234 /*
235 * Local variables:
236 * c-file-style: "stroustrup"
237 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
238 * indent-tabs-mode: nil
239 * End:
240 *
241 * vim: expandtab shiftwidth=4:
242 */