ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/opercmd.c
Revision: 9104
Committed: Wed Jan 1 10:03:28 2020 UTC (5 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 7175 byte(s)
Log Message:
- Bump copyright years everywhere

File Contents

# Content
1 /*
2 * Copyright (c) 2002 Erik Fears
3 * Copyright (c) 2014-2020 ircd-hybrid development team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
18 * USA
19 */
20
21 #include "setup.h"
22
23 #include <string.h>
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <time.h>
27
28 #include "list.h"
29 #include "options.h"
30 #include "irc.h"
31 #include "log.h"
32 #include "main.h"
33 #include "config.h"
34 #include "opercmd.h"
35 #include "scan.h"
36 #include "memory.h"
37 #include "stats.h"
38
39
40 static list_t COMMANDS; /* List of active commands */
41
42
43 /* cmd_check
44 *
45 * Start a manual scan on given IP address/hostname.
46 *
47 * Parameters:
48 * param: Parameters of the command
49 * target: channel command was sent to
50 *
51 */
52 static void
53 cmd_check(char *param, const char *target)
54 {
55 scan_manual(param, target);
56 }
57
58 /* cmd_stat
59 *
60 * Send output of stats to channel.
61 *
62 * Parameters:
63 * param: Parameters of the command
64 * target: channel command was sent to
65 */
66 static void
67 cmd_stats(char *param, const char *target)
68 {
69 stats_output(target);
70 }
71
72 /* cmd_fdstat
73 *
74 * Send output of stats to channel.
75 *
76 * Parameters:
77 * param: Parameters of the command
78 * target: channel command was sent to
79 */
80 static void
81 cmd_fdstat(char *param, const char *target)
82 {
83 fdstats_output(target);
84 }
85
86 /* command_create
87 *
88 * Create a Command struct.
89 *
90 * Parameters:
91 * type: Index in COMMAND_TABLE
92 * param: Parameters to the command (NULL if there are not any)
93 * irc_nick: Nickname of user that initiated the command
94 * target: Target channel (target is ALWAYS a channel)
95 *
96 * Return:
97 * Pointer to new Command
98 */
99 static struct Command *
100 command_create(const struct OperCommandHash *tab, const char *param, const char *irc_nick,
101 const char *target)
102 {
103 struct Command *command = xcalloc(sizeof(*command));
104
105 if (param)
106 command->param = xstrdup(param);
107
108 command->tab = tab;
109 command->irc_nick = xstrdup(irc_nick);
110 command->target = target;
111
112 time(&command->added);
113
114 return command;
115 }
116
117 /* command_free
118 *
119 * Free a command struct
120 *
121 * Parameters:
122 * command: Command struct to free
123 *
124 * Return: NONE
125 */
126 static void
127 command_free(struct Command *command)
128 {
129 if (command->param)
130 xfree(command->param);
131
132 xfree(command->irc_nick);
133 xfree(command);
134 }
135
136 /* command_parse
137 *
138 * Parse a command to hopm (sent to a channel hopm is on). The command is parsed
139 * from the parameters, and if it is a known command it is stored in a queue. A
140 * userhost is performed on the user to check if they are an IRC operator. When
141 * a reply is returned (command_userhost), the command will be executed.
142 *
143 * Parameters:
144 * command: Command sent (including parameters)
145 * target: Channel command was sent to (we only got this far if there was only one recipient)
146 * source_p: Operator (hopefully) that sent the command.
147 *
148 */
149 void
150 command_parse(const char *command, const char *target, const char *source_p)
151 {
152 char *param; /* Parsed parameters */
153 static const struct OperCommandHash COMMAND_TABLE[] =
154 {
155 { .command = "CHECK", .handler = cmd_check },
156 { .command = "SCAN", .handler = cmd_check },
157 { .command = "STATS", .handler = cmd_stats },
158 { .command = "FDSTAT", .handler = cmd_fdstat },
159 { .command = NULL }
160 };
161
162 if (OPT_DEBUG)
163 log_printf("COMMAND -> Parsing command (%s) from %s [%s]",
164 command, source_p, target);
165
166 /* Only allow OptionsItem.command_queue_size commands in the queue */
167 if (LIST_SIZE(&COMMANDS) >= OptionsItem.command_queue_size)
168 return;
169
170 /*
171 * Parameter is the first character in command after the first space.
172 * 'param' will be NULL if:
173 * 1. There was no space
174 * 2. There was a space but it was the last character in command, in which case
175 * param = '\0'
176 */
177
178 /* Skip past the botname/!all */
179 command = strchr(command, ' ');
180
181 /*
182 * There is no command OR there is at least nothing
183 * past that first space.
184 */
185 if (command == NULL || *++command == '\0')
186 return;
187
188 /* Find the parameters */
189 param = strchr(command, ' ');
190
191 if (param)
192 {
193 *param = '\0';
194 param++;
195 }
196
197 log_printf("COMMAND -> parsed [%s] [%s]", command, param ? param : "");
198
199 /* Lookup the command in the table */
200 for (const struct OperCommandHash *tab = COMMAND_TABLE; tab->command; ++tab)
201 {
202 if (strcasecmp(command, tab->command) == 0)
203 {
204 /* Queue this command */
205 struct Command *cmd = command_create(tab, param, source_p, target);
206
207 list_add(cmd, &cmd->node, &COMMANDS);
208 break;
209 }
210 }
211
212 irc_send("USERHOST %s", source_p);
213 }
214
215 /* command_timer
216 *
217 * Perform ~1 second actions.
218 *
219 * Parameters: NONE
220 *
221 * Return: NONE
222 *
223 */
224 void
225 command_timer(void)
226 {
227 static unsigned int interval;
228 node_t *node, *node_next;
229 time_t present;
230
231 /* Only perform command removal every OptionsItem.command_interval seconds */
232 if (interval++ < OptionsItem.command_interval)
233 return;
234 else
235 interval = 0;
236
237 time(&present);
238
239 LIST_FOREACH_SAFE(node, node_next, COMMANDS.head)
240 {
241 struct Command *command = node->data;
242
243 if ((present - command->added) > OptionsItem.command_timeout)
244 {
245 list_remove(&command->node, &COMMANDS);
246 command_free(command); /* Cleanup the command */
247 }
248 else /* Since the queue is in order, it's also ordered by time, no nodes after this will be timed out */
249 return;
250 }
251 }
252
253 /* command_userhost
254 *
255 * A 302 reply was received. The reply is parsed to check if the
256 * user was an operator. If so any commands they had queued are
257 * executed.
258 *
259 * Parameters:
260 * reply: Reply to USERHOST (ex: :grifferz*=+goats@pc-62-30-219-54-pb.blueyonder.co.uk)
261 *
262 * Return: NONE
263 *
264 */
265 void
266 command_userhost(const char *reply)
267 {
268 node_t *node, *node_next;
269 char *tmp;
270 int oper = 0;
271
272 tmp = strchr(reply, '=');
273
274 /* They quit, ignore it */
275 if (tmp == NULL)
276 return;
277
278 /* Operators have a * flag in a USERHOST reply */
279 if (*(tmp - 1) == '*')
280 oper = 1;
281
282 /* Null terminate it so tmp = the oper's nick */
283 if (oper)
284 *(--tmp) = '\0';
285 else
286 *(tmp) = '\0';
287
288 /* Find any queued commands that match this user */
289 LIST_FOREACH_SAFE(node, node_next, COMMANDS.head)
290 {
291 struct Command *command = node->data;
292
293 if (strcmp(command->irc_nick, reply) == 0)
294 {
295 if (oper)
296 command->tab->handler(command->param, command->target);
297
298 list_remove(&command->node, &COMMANDS);
299 command_free(command); /* Cleanup the command */
300 }
301 }
302 }

Properties

Name Value
svn:eol-style native
svn:keywords Id