ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/opercmd.c
Revision: 5114
Committed: Wed Dec 24 22:12:05 2014 UTC (9 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 8091 byte(s)
Log Message:
- Style corrections

File Contents

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