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