ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/commands.c
Revision: 1171
Committed: Fri Aug 12 20:00:46 2011 UTC (12 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 6785 byte(s)
Log Message:
- Import ircservices-5.1.24. Don't ever think about modifying anything in this
  folder!
  Since Andrew Church has discontinued his services project in April 2011, the
  ircd-hybrid team has been given permissions to officially continue and
  maintain the already mentioned project.
  The name of this project will be changed for the reason being that the current
  name "IRC Services" is way too generic these days.

  Remember: Don't ever modify anything in here. This folder is kept for reference.

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 */