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