1 /* $Id: commands.c 448 2010-08-22 09:20:48Z tsaviran $
2  * -------------------------------------------------------
3  * Copyright (C) 2003-2005 Tommi Saviranta <wnd@iki.fi>
4  *	(C) 2002 Lee Hardy <lee@leeh.co.uk>
5  * -------------------------------------------------------
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16 
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif /* ifdef HAVE_CONFIG_H */
20 
21 #include "commands.h"
22 #include "common.h"
23 
24 
25 
26 static struct commandhash *cmd_hash[MAX_CMD];
27 static int command_hash(const char *p);
28 void command_add(const char *p, int cmdvalue);
29 
30 
31 
32 /* The struct for the command hash table. */
33 struct commandhash {
34 	const char		*cmd;
35 	int			cmdvalue;
36 	struct commandhash	*next;
37 };
38 
39 
40 
41 /* The struct for the table below. */
42 struct commandaddstruct {
43 	char	*cmd;
44 	int	mask;
45 };
46 
47 
48 
49 /*
50  * The table of commands that we need to add at startup, and their relevant
51  * bitmasks, as defined in commands.h.
52  */
53 static struct commandaddstruct cmd_add_table[] =
54 {
55 	/* command,		bitmask,	*/
56 	{"PING",		CMD_PING,	},
57 	{"PONG",		CMD_PONG,	},
58 	{"MODE",		CMD_MODE,	},
59 	{"NICK",		CMD_NICK,	},
60 	{"NOTICE",		CMD_NOTICE,	},
61 	{"KICK",		CMD_KICK,	},
62 	{"JOIN",		CMD_JOIN,	},
63 	{"PART",		CMD_PART,	},
64 	{"TOPIC",		CMD_TOPIC,	},
65 	{"KILL",		CMD_KILL,	},
66 	{"PRIVMSG",		CMD_PRIVMSG,	},
67 	{"QUIT",		CMD_QUIT,	},
68 	{NULL,			CMD_NONE,	}
69 };
70 
71 
72 
73 /*
74  * Hashes a command to a value.
75  */
76 static int
command_hash(const char * p)77 command_hash(const char *p)
78 {
79 	int	hash_val = 0;
80 
81 	while (*p) {
82 		hash_val += ((int) (*p) & 0xDF);
83 		p++;
84 	}
85 
86 	return (hash_val % MAX_CMD);
87 } /* static int command_hash(const char *p) */
88 
89 
90 
91 /*
92  * Searches for a command in the command hash table.
93  */
94 int
command_find(char * p)95 command_find(char *p)
96 {
97 	struct commandhash	*ptr;
98 	int			cmdindex;
99 
100 	cmdindex = command_hash(p);
101 
102 	for (ptr = cmd_hash[cmdindex]; ptr; ptr = ptr->next) {
103 		if (xstrcasecmp(p, ptr->cmd) == 0) {
104 			return ptr->cmdvalue;
105 		}
106 	}
107 
108 	return 0;
109 } /* int command_find(char *p) */
110 
111 
112 
113 /*
114  * Adds a command to the command hash table.
115  */
116 void
command_add(const char * cmd,int cmdvalue)117 command_add(const char *cmd, int cmdvalue)
118 {
119 	struct commandhash	*ptr;
120 	struct commandhash	*temp_ptr;
121 	struct commandhash	*last_ptr = NULL;
122 	int			cmdindex;
123 
124 	cmdindex = command_hash(cmd);
125 
126 	/* command exists */
127 	for (temp_ptr = cmd_hash[cmdindex]; temp_ptr;
128 			temp_ptr = temp_ptr->next) {
129 		if (xstrcasecmp(cmd, temp_ptr->cmd) == 0) {
130 			return;
131 		}
132 
133 		last_ptr = temp_ptr;
134 	}
135 
136 	ptr = (struct commandhash *) xcalloc(1, sizeof(struct commandhash));
137 
138 	ptr->cmd = cmd;
139 	ptr->cmdvalue = cmdvalue;
140 
141 	if (last_ptr) {
142 		last_ptr->next = ptr;
143 	} else {
144 		cmd_hash[cmdindex] = ptr;
145 	}
146 } /* void command_add(const char *cmd, int cmdvalue) */
147 
148 
149 
150 /*
151  * Walks the commandsadd table and adds all the entries.
152  */
153 void
command_setup(void)154 command_setup(void)
155 {
156 	int	i;
157 
158 	for (i = 0; i < MAX_CMD; i++) {
159 		cmd_hash[i] = NULL;
160 	}
161 
162 	for (i = 0; cmd_add_table[i].cmd; i++) {
163 		command_add(cmd_add_table[i].cmd, cmd_add_table[i].mask);
164 	}
165 } /* void command_setup(void) */
166 
167 
168 
169 /*
170  * Free memore allocated by command-hash.
171  */
172 void
command_free(void)173 command_free(void)
174 {
175 	int	i;
176 	struct commandhash	*ptr;
177 	struct commandhash	*next = NULL;
178 
179 	for (i = 0; i < MAX_CMD; i++) {
180 		for (ptr = cmd_hash[i]; ptr != NULL; ptr = next) {
181 			next = ptr->next;
182 			xfree(ptr);
183 		}
184 	}
185 } /* void command_free(void) */
186