1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 
5 #include <openssl/lhash.h>
6 #include <openssl/objects.h>
7 
8 /* I use the ex_data stuff to manage the identifiers for the obj_name_types
9  * that applications may define.  I only really use the free function field.
10  */
11 static LHASH *names_lh=NULL;
12 static int names_type_num=OBJ_NAME_TYPE_NUM;
13 static STACK *names_cmp=NULL;
14 static STACK *names_hash=NULL;
15 static STACK *names_free=NULL;
16 
17 static unsigned long obj_name_hash(OBJ_NAME *a);
18 static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b);
19 
20 int OBJ_NAME_init(void)
21 	{
22 	if (names_lh != NULL) return(1);
23 	MemCheck_off();
24 	names_lh=lh_new(obj_name_hash,obj_name_cmp);
25 	MemCheck_on();
26 	return(names_lh != NULL);
27 	}
28 
29 int OBJ_NAME_new_index(unsigned long (*hash_func)(), int (*cmp_func)(),
30 	     void (*free_func)())
31 	{
32 	int ret;
33 	int i;
34 
35 	if (names_free == NULL)
36 		{
37 		MemCheck_off();
38 		names_hash=sk_new_null();
39 		names_cmp=sk_new_null();
40 		names_free=sk_new_null();
41 		MemCheck_on();
42 		}
43 	if ((names_free == NULL) || (names_hash == NULL) || (names_cmp == NULL))
44 		{
45 		/* ERROR */
46 		return(0);
47 		}
48 	ret=names_type_num;
49 	names_type_num++;
50 	for (i=sk_num(names_free); i<names_type_num; i++)
51 		{
52 		MemCheck_off();
53 		sk_push(names_hash,(char *)strcmp);
54 		sk_push(names_cmp,(char *)lh_strhash);
55 		sk_push(names_free,NULL);
56 		MemCheck_on();
57 		}
58 	if (hash_func != NULL)
59 		sk_set(names_hash,ret,(char *)hash_func);
60 	if (cmp_func != NULL)
61 		sk_set(names_cmp,ret,(char *)cmp_func);
62 	if (free_func != NULL)
63 		sk_set(names_free,ret,(char *)free_func);
64 	return(ret);
65 	}
66 
67 static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b)
68 	{
69 	int ret;
70 	int (*cmp)();
71 
72 	ret=a->type-b->type;
73 	if (ret == 0)
74 		{
75 		if ((names_cmp != NULL) && (sk_num(names_cmp) > a->type))
76 			{
77 			cmp=(int (*)())sk_value(names_cmp,a->type);
78 			ret=cmp(a->name,b->name);
79 			}
80 		else
81 			ret=strcmp(a->name,b->name);
82 		}
83 	return(ret);
84 	}
85 
86 static unsigned long obj_name_hash(OBJ_NAME *a)
87 	{
88 	unsigned long ret;
89 	unsigned long (*hash)();
90 
91 	if ((names_hash != NULL) && (sk_num(names_hash) > a->type))
92 		{
93 		hash=(unsigned long (*)())sk_value(names_hash,a->type);
94 		ret=hash(a->name);
95 		}
96 	else
97 		{
98 		ret=lh_strhash(a->name);
99 		}
100 	ret^=a->type;
101 	return(ret);
102 	}
103 
104 const char *OBJ_NAME_get(const char *name, int type)
105 	{
106 	OBJ_NAME on,*ret;
107 	int num=0,alias;
108 
109 	if (name == NULL) return(NULL);
110 	if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
111 
112 	alias=type&OBJ_NAME_ALIAS;
113 	type&= ~OBJ_NAME_ALIAS;
114 
115 	on.name=name;
116 	on.type=type;
117 
118 	for (;;)
119 		{
120 		ret=(OBJ_NAME *)lh_retrieve(names_lh,(char *)&on);
121 		if (ret == NULL) return(NULL);
122 		if ((ret->alias) && !alias)
123 			{
124 			if (++num > 10) return(NULL);
125 			on.name=ret->data;
126 			}
127 		else
128 			{
129 			return(ret->data);
130 			}
131 		}
132 	}
133 
134 int OBJ_NAME_add(const char *name, int type, const char *data)
135 	{
136 	void (*f)();
137 	OBJ_NAME *onp,*ret;
138 	int alias;
139 
140 	if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
141 
142 	alias=type&OBJ_NAME_ALIAS;
143 	type&= ~OBJ_NAME_ALIAS;
144 
145 	onp=(OBJ_NAME *)Malloc(sizeof(OBJ_NAME));
146 	if (onp == NULL)
147 		{
148 		/* ERROR */
149 		return(0);
150 		}
151 
152 	onp->name=name;
153 	onp->alias=alias;
154 	onp->type=type;
155 	onp->data=data;
156 
157 	ret=(OBJ_NAME *)lh_insert(names_lh,(char *)onp);
158 	if (ret != NULL)
159 		{
160 		/* free things */
161 		if ((names_free != NULL) && (sk_num(names_free) > ret->type))
162 			{
163 			f=(void (*)())sk_value(names_free,ret->type);
164 			f(ret->name,ret->type,ret->data);
165 			}
166 		Free((char *)ret);
167 		}
168 	else
169 		{
170 		if (lh_error(names_lh))
171 			{
172 			/* ERROR */
173 			return(0);
174 			}
175 		}
176 	return(1);
177 	}
178 
179 int OBJ_NAME_remove(const char *name, int type)
180 	{
181 	OBJ_NAME on,*ret;
182 	void (*f)();
183 
184 	if (names_lh == NULL) return(0);
185 
186 	type&= ~OBJ_NAME_ALIAS;
187 	on.name=name;
188 	on.type=type;
189 	ret=(OBJ_NAME *)lh_delete(names_lh,(char *)&on);
190 	if (ret != NULL)
191 		{
192 		/* free things */
193 		if ((names_free != NULL) && (sk_num(names_free) > type))
194 			{
195 			f=(void (*)())sk_value(names_free,type);
196 			f(ret->name,ret->type,ret->data);
197 			}
198 		Free((char *)ret);
199 		return(1);
200 		}
201 	else
202 		return(0);
203 	}
204 
205 static int free_type;
206 
207 static void names_lh_free(OBJ_NAME *onp, int type)
208 {
209 	if(onp == NULL)
210 	    return;
211 
212 	if ((free_type < 0) || (free_type == onp->type))
213 		{
214 		OBJ_NAME_remove(onp->name,onp->type);
215 		}
216 	}
217 
218 void OBJ_NAME_cleanup(int type)
219 	{
220 	unsigned long down_load;
221 
222 	if (names_lh == NULL) return;
223 
224 	free_type=type;
225 	down_load=names_lh->down_load;
226 	names_lh->down_load=0;
227 
228 	lh_doall(names_lh,names_lh_free);
229 	if (type < 0)
230 		{
231 		lh_free(names_lh);
232 		sk_free(names_hash);
233 		sk_free(names_cmp);
234 		sk_free(names_free);
235 		names_lh=NULL;
236 		names_hash=NULL;
237 		names_cmp=NULL;
238 		names_free=NULL;
239 		}
240 	else
241 		names_lh->down_load=down_load;
242 	}
243 
244