1 /*
2  * Copyright (C) 2001		faster	(lqx@cic.tsinghua.edu.cn)
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  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18 #include "common/setup_before.h"
19 #include "setup.h"
20 
21 #include <stdio.h>
22 #ifdef STDC_HEADERS
23 # include <stdlib.h>
24 #else
25 # ifdef HAVE_MALLOC_H
26 #  include <malloc.h>
27 # endif
28 #endif
29 #ifdef HAVE_STRING_H
30 # include <string.h>
31 #else
32 # ifdef HAVE_STRINGS_H
33 #  include <strings.h>
34 # endif
35 # ifdef HAVE_MEMORY_H
36 #  include <memory.h>
37 # endif
38 #endif
39 #include "compat/strcasecmp.h"
40 #include <ctype.h>
41 #ifdef HAVE_LIMITS_H
42 # include <limits.h>
43 #endif
44 
45 #include "charlock.h"
46 #include "common/introtate.h"
47 #include "common/xalloc.h"
48 #include "common/setup_after.h"
49 
50 /* FIXME: for simplification, no multiple realm support now */
51 
52 /* local functions */
53 static int cl_insert_to_gsq_list(unsigned int gsid, t_charlockinfo *pcl);
54 static int cl_delete_from_gsq_list(t_charlockinfo *pcl);
55 static unsigned int string_hash(char const *string);
56 
57 
58 /* variables */
59 static unsigned int		clitbl_len = 0;
60 static unsigned int		gsqtbl_len = 0;
61 static t_charlockinfo		* * clitbl = NULL;
62 static t_charlockinfo		* * gsqtbl = NULL;
63 
64 
cl_init(unsigned int tbllen,unsigned int maxgs)65 int cl_init(unsigned int tbllen, unsigned int maxgs)
66 {
67 	if (!tbllen || !maxgs) return -1;
68 	cl_destroy();
69 
70 	clitbl = (t_charlockinfo**)xmalloc(tbllen*sizeof(t_charlockinfo**));
71 	gsqtbl = (t_charlockinfo**)xmalloc(maxgs*sizeof(t_charlockinfo**));
72 	memset(clitbl, 0, tbllen*sizeof(t_charlockinfo**));
73 	memset(gsqtbl, 0, maxgs*sizeof(t_charlockinfo**));
74 	clitbl_len = tbllen;
75 	gsqtbl_len = maxgs;
76 	return 0;
77 }
78 
79 
cl_destroy(void)80 int cl_destroy(void)
81 {
82 	unsigned int	i;
83 	t_charlockinfo	* ptl, * ptmp;
84 
85 	if (clitbl) {
86 		for (i=0; i<clitbl_len; i++) {
87 			ptl=clitbl[i];
88 			while (ptl) {
89 				ptmp=ptl;
90 				ptl=ptl->next;
91 				xfree(ptmp);
92 			}
93 		}
94 		xfree(clitbl);
95 	}
96 	if (gsqtbl) xfree(gsqtbl);
97 	clitbl = gsqtbl = NULL;
98 	clitbl_len = gsqtbl_len = 0;
99 	return 0;
100 }
101 
102 
cl_query_charlock_status(unsigned char * charname,unsigned char * realmname,unsigned int * gsid)103 int cl_query_charlock_status(unsigned char *charname,
104 			unsigned char *realmname, unsigned int *gsid)
105 {
106 	t_charlockinfo	*pcl;
107 	unsigned int	hashval;
108 
109 	if (!charname || !realmname) return -1;
110 	if (!clitbl_len || !gsqtbl) return -1;
111 	if (strlen(charname)>=MAX_CHARNAME_LEN) return -1;
112 
113 	hashval = string_hash(charname) % clitbl_len;
114 	pcl = clitbl[hashval];
115 	while(pcl)
116 	{
117 		if (strcasecmp(pcl->charname, charname) == 0) {
118 			*gsid = pcl->gsid;
119 			return 1;	/* found the char, it is locked */
120 		}
121 		pcl = pcl->next;
122 	}
123 	return 0;	/* not found, it is unlocked */
124 }
125 
126 
cl_lock_char(unsigned char * charname,unsigned char * realmname,unsigned int gsid)127 int cl_lock_char(unsigned char *charname,
128 			unsigned char *realmname, unsigned int gsid)
129 {
130 	t_charlockinfo	*pcl, *ptmp;
131 	unsigned int	hashval;
132 
133 	if (!charname || !realmname) return -1;
134 	if (!clitbl_len || !gsqtbl) return -1;
135 	if (strlen(charname)>=MAX_CHARNAME_LEN) return -1;
136 
137 	hashval = string_hash(charname) % clitbl_len;
138 	pcl = clitbl[hashval];
139 	ptmp = NULL;
140 	while(pcl)
141 	{
142 		if (strcasecmp(pcl->charname, charname) == 0)
143 			return 0;	/* found the char is already locked */
144 		ptmp = pcl;
145 		pcl = pcl->next;
146 	}
147 
148 	/* not found, locked it */
149 	pcl = (t_charlockinfo*)xmalloc(sizeof(t_charlockinfo));
150 	memset(pcl, 0, sizeof(t_charlockinfo));
151 	strncpy(pcl->charname, charname, MAX_CHARNAME_LEN-1);
152 	strncpy(pcl->realmname, realmname, MAX_REALMNAME_LEN-1);
153 	pcl->gsid = gsid;
154 
155 	/* add to hash table link list */
156 	if (ptmp) ptmp->next = pcl;
157 	else clitbl[hashval] = pcl;
158 	/* add to gs specified link list */
159 	cl_insert_to_gsq_list(gsid, pcl);
160 
161 	return 0;
162 }
163 
164 
cl_unlock_char(unsigned char * charname,unsigned char * realmname,unsigned int gsid)165 int cl_unlock_char(unsigned char *charname, unsigned char *realmname, unsigned int gsid)
166 {
167 	t_charlockinfo	*pcl, *ptmp;
168 	unsigned int	hashval;
169 
170 	if (!charname || !realmname) return -1;
171 	if (!clitbl_len || !gsqtbl) return 0;
172 	if (strlen(charname)>=MAX_CHARNAME_LEN) return -1;
173 
174 	hashval = string_hash(charname) % clitbl_len;
175 	pcl = clitbl[hashval];
176 	ptmp = NULL;
177 	while(pcl)
178 	{
179 		if ((strcasecmp(pcl->charname, charname) == 0) && (pcl->gsid==gsid)) {
180 			cl_delete_from_gsq_list(pcl);
181 			if (ptmp) ptmp->next = pcl->next;
182 			else clitbl[hashval] = pcl->next;
183 			xfree(pcl);
184 			return 0;
185 		}
186 		ptmp = pcl;
187 		pcl = pcl->next;
188 	}
189 	return 0;
190 }
191 
192 
cl_unlock_all_char_by_gsid(unsigned int gsid)193 int cl_unlock_all_char_by_gsid(unsigned int gsid)
194 {
195 	unsigned int	index_pos;
196 	t_charlockinfo	*pcl, *pnext;
197 
198 	index_pos = gsid % gsqtbl_len;
199 	pcl = gsqtbl[index_pos];
200 	while(pcl)
201 	{
202 		pnext = pcl->gsqnext;
203 		cl_unlock_char(pcl->charname, pcl->realmname, gsid);
204 		pcl = pnext;
205 	}
206 	return 0;
207 }
208 
209 
cl_insert_to_gsq_list(unsigned int gsid,t_charlockinfo * pcl)210 static int cl_insert_to_gsq_list(unsigned int gsid, t_charlockinfo *pcl)
211 {
212 	unsigned int	index_pos;
213 	t_charlockinfo	*ptmp;
214 
215 	if (!pcl) return -1;
216 
217 	index_pos = gsid % gsqtbl_len;
218 	ptmp = gsqtbl[index_pos];
219 	gsqtbl[index_pos] = pcl;
220 	if (ptmp) {
221 		pcl->gsqnext = ptmp;
222 		ptmp->gsqprev = pcl;
223 	}
224 	return 0;
225 }
226 
227 
cl_delete_from_gsq_list(t_charlockinfo * pcl)228 static int cl_delete_from_gsq_list(t_charlockinfo *pcl)
229 {
230 	unsigned int	index_pos;
231 	t_charlockinfo	*pprev, *pnext;
232 
233 	if (!pcl) return -1;
234 
235 	index_pos = (pcl->gsid) % gsqtbl_len;
236 	pprev = pcl->gsqprev;
237 	pnext = pcl->gsqnext;
238 	if (pprev) pprev->gsqnext = pnext;
239 	else gsqtbl[index_pos] = pnext;
240 	if (pnext) pnext->gsqprev = pprev;
241 
242 	return 0;
243 }
244 
245 
string_hash(char const * string)246 static unsigned int string_hash(char const *string)
247 {
248 	unsigned int	i;
249 	unsigned int	pos;
250 	unsigned int	hash;
251 	unsigned int	ch;
252 
253 	if (!string) return 0;
254 
255 	for (hash=0,pos=0,i=0; i<strlen(string); i++)
256 	{
257 		if (isascii((int)string[i]))
258 			ch = (unsigned int)(unsigned char)tolower((int)string[i]);
259 		else
260 			ch = (unsigned int)(unsigned char)string[i];
261 		hash ^= ROTL(ch,pos,sizeof(unsigned int)*CHAR_BIT);
262 		pos += CHAR_BIT-1;
263 	}
264 
265 	return hash;
266 }
267 
268