155714Skris#include <stdio.h> 255714Skris#include <stdlib.h> 355714Skris#include <string.h> 455714Skris 5160814Ssimon#include <openssl/err.h> 655714Skris#include <openssl/lhash.h> 755714Skris#include <openssl/objects.h> 859191Skris#include <openssl/safestack.h> 9109998Smarkm#include <openssl/e_os2.h> 1055714Skris 11109998Smarkm/* Later versions of DEC C has started to add lnkage information to certain 12109998Smarkm * functions, which makes it tricky to use them as values to regular function 13109998Smarkm * pointers. One way is to define a macro that takes care of casting them 14109998Smarkm * correctly. 15109998Smarkm */ 16109998Smarkm#ifdef OPENSSL_SYS_VMS_DECC 17109998Smarkm# define OPENSSL_strcmp (int (*)(const char *,const char *))strcmp 18109998Smarkm#else 19109998Smarkm# define OPENSSL_strcmp strcmp 20109998Smarkm#endif 21109998Smarkm 2255714Skris/* I use the ex_data stuff to manage the identifiers for the obj_name_types 2355714Skris * that applications may define. I only really use the free function field. 2455714Skris */ 25238405SjkimDECLARE_LHASH_OF(OBJ_NAME); 26238405Sjkimstatic LHASH_OF(OBJ_NAME) *names_lh=NULL; 2755714Skrisstatic int names_type_num=OBJ_NAME_TYPE_NUM; 2855714Skris 2959191Skristypedef struct name_funcs_st 3059191Skris { 31109998Smarkm unsigned long (*hash_func)(const char *name); 32109998Smarkm int (*cmp_func)(const char *a,const char *b); 33109998Smarkm void (*free_func)(const char *, int, const char *); 3459191Skris } NAME_FUNCS; 3559191Skris 3659191SkrisDECLARE_STACK_OF(NAME_FUNCS) 3759191SkrisIMPLEMENT_STACK_OF(NAME_FUNCS) 3859191Skris 3959191Skrisstatic STACK_OF(NAME_FUNCS) *name_funcs_stack; 4059191Skris 41109998Smarkm/* The LHASH callbacks now use the raw "void *" prototypes and do per-variable 42109998Smarkm * casting in the functions. This prevents function pointer casting without the 43109998Smarkm * need for macro-generated wrapper functions. */ 4455714Skris 45109998Smarkm/* static unsigned long obj_name_hash(OBJ_NAME *a); */ 46109998Smarkmstatic unsigned long obj_name_hash(const void *a_void); 47109998Smarkm/* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */ 48109998Smarkmstatic int obj_name_cmp(const void *a_void,const void *b_void); 49109998Smarkm 50238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(obj_name, OBJ_NAME) 51238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(obj_name, OBJ_NAME) 52238405Sjkim 5355714Skrisint OBJ_NAME_init(void) 5455714Skris { 5555714Skris if (names_lh != NULL) return(1); 5655714Skris MemCheck_off(); 57238405Sjkim names_lh=lh_OBJ_NAME_new(); 5855714Skris MemCheck_on(); 5955714Skris return(names_lh != NULL); 6055714Skris } 6155714Skris 6268651Skrisint OBJ_NAME_new_index(unsigned long (*hash_func)(const char *), 63109998Smarkm int (*cmp_func)(const char *, const char *), 6468651Skris void (*free_func)(const char *, int, const char *)) 6555714Skris { 6655714Skris int ret; 6755714Skris int i; 6859191Skris NAME_FUNCS *name_funcs; 6955714Skris 7059191Skris if (name_funcs_stack == NULL) 7155714Skris { 7255714Skris MemCheck_off(); 7359191Skris name_funcs_stack=sk_NAME_FUNCS_new_null(); 7455714Skris MemCheck_on(); 7555714Skris } 76246772Sjkim if (name_funcs_stack == NULL) 7755714Skris { 7855714Skris /* ERROR */ 7955714Skris return(0); 8055714Skris } 8155714Skris ret=names_type_num; 8255714Skris names_type_num++; 8359191Skris for (i=sk_NAME_FUNCS_num(name_funcs_stack); i<names_type_num; i++) 8455714Skris { 8555714Skris MemCheck_off(); 8668651Skris name_funcs = OPENSSL_malloc(sizeof(NAME_FUNCS)); 87100936Snectar MemCheck_on(); 88160814Ssimon if (!name_funcs) 89160814Ssimon { 90160814Ssimon OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX,ERR_R_MALLOC_FAILURE); 91160814Ssimon return(0); 92160814Ssimon } 9359191Skris name_funcs->hash_func = lh_strhash; 94109998Smarkm name_funcs->cmp_func = OPENSSL_strcmp; 9559191Skris name_funcs->free_func = 0; /* NULL is often declared to 96109998Smarkm * ((void *)0), which according 97109998Smarkm * to Compaq C is not really 98109998Smarkm * compatible with a function 99109998Smarkm * pointer. -- Richard Levitte*/ 100100936Snectar MemCheck_off(); 10159191Skris sk_NAME_FUNCS_push(name_funcs_stack,name_funcs); 10255714Skris MemCheck_on(); 10355714Skris } 10459191Skris name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret); 10555714Skris if (hash_func != NULL) 10659191Skris name_funcs->hash_func = hash_func; 10755714Skris if (cmp_func != NULL) 10859191Skris name_funcs->cmp_func = cmp_func; 10955714Skris if (free_func != NULL) 11059191Skris name_funcs->free_func = free_func; 11155714Skris return(ret); 11255714Skris } 11355714Skris 114109998Smarkm/* static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) */ 115109998Smarkmstatic int obj_name_cmp(const void *a_void, const void *b_void) 11655714Skris { 11755714Skris int ret; 118160814Ssimon const OBJ_NAME *a = (const OBJ_NAME *)a_void; 119160814Ssimon const OBJ_NAME *b = (const OBJ_NAME *)b_void; 12055714Skris 12155714Skris ret=a->type-b->type; 12255714Skris if (ret == 0) 12355714Skris { 12459191Skris if ((name_funcs_stack != NULL) 12559191Skris && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) 12655714Skris { 127109998Smarkm ret=sk_NAME_FUNCS_value(name_funcs_stack, 128109998Smarkm a->type)->cmp_func(a->name,b->name); 12955714Skris } 13055714Skris else 13155714Skris ret=strcmp(a->name,b->name); 13255714Skris } 13355714Skris return(ret); 13455714Skris } 13555714Skris 136109998Smarkm/* static unsigned long obj_name_hash(OBJ_NAME *a) */ 137109998Smarkmstatic unsigned long obj_name_hash(const void *a_void) 13855714Skris { 13955714Skris unsigned long ret; 140160814Ssimon const OBJ_NAME *a = (const OBJ_NAME *)a_void; 14155714Skris 14259191Skris if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) 14355714Skris { 144109998Smarkm ret=sk_NAME_FUNCS_value(name_funcs_stack, 145109998Smarkm a->type)->hash_func(a->name); 14655714Skris } 14755714Skris else 14855714Skris { 14955714Skris ret=lh_strhash(a->name); 15055714Skris } 15155714Skris ret^=a->type; 15255714Skris return(ret); 15355714Skris } 15455714Skris 15555714Skrisconst char *OBJ_NAME_get(const char *name, int type) 15655714Skris { 15755714Skris OBJ_NAME on,*ret; 15855714Skris int num=0,alias; 15955714Skris 16055714Skris if (name == NULL) return(NULL); 16155714Skris if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL); 16255714Skris 16355714Skris alias=type&OBJ_NAME_ALIAS; 16455714Skris type&= ~OBJ_NAME_ALIAS; 16555714Skris 16655714Skris on.name=name; 16755714Skris on.type=type; 16855714Skris 16955714Skris for (;;) 170109998Smarkm { 171238405Sjkim ret=lh_OBJ_NAME_retrieve(names_lh,&on); 17255714Skris if (ret == NULL) return(NULL); 17355714Skris if ((ret->alias) && !alias) 17455714Skris { 17555714Skris if (++num > 10) return(NULL); 17655714Skris on.name=ret->data; 17755714Skris } 17855714Skris else 17955714Skris { 18055714Skris return(ret->data); 18155714Skris } 18255714Skris } 18355714Skris } 18455714Skris 18555714Skrisint OBJ_NAME_add(const char *name, int type, const char *data) 18655714Skris { 18755714Skris OBJ_NAME *onp,*ret; 18855714Skris int alias; 18955714Skris 19055714Skris if ((names_lh == NULL) && !OBJ_NAME_init()) return(0); 19155714Skris 19255714Skris alias=type&OBJ_NAME_ALIAS; 19355714Skris type&= ~OBJ_NAME_ALIAS; 19455714Skris 19568651Skris onp=(OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME)); 19655714Skris if (onp == NULL) 19755714Skris { 19855714Skris /* ERROR */ 19955714Skris return(0); 20055714Skris } 20155714Skris 20255714Skris onp->name=name; 20355714Skris onp->alias=alias; 20455714Skris onp->type=type; 20555714Skris onp->data=data; 20655714Skris 207238405Sjkim ret=lh_OBJ_NAME_insert(names_lh,onp); 20855714Skris if (ret != NULL) 20955714Skris { 21055714Skris /* free things */ 21159191Skris if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) 21255714Skris { 21359191Skris /* XXX: I'm not sure I understand why the free 21459191Skris * function should get three arguments... 21559191Skris * -- Richard Levitte 21659191Skris */ 217109998Smarkm sk_NAME_FUNCS_value(name_funcs_stack, 218109998Smarkm ret->type)->free_func(ret->name,ret->type,ret->data); 21955714Skris } 22068651Skris OPENSSL_free(ret); 22155714Skris } 22255714Skris else 22355714Skris { 224238405Sjkim if (lh_OBJ_NAME_error(names_lh)) 22555714Skris { 22655714Skris /* ERROR */ 22755714Skris return(0); 22855714Skris } 22955714Skris } 23055714Skris return(1); 23155714Skris } 23255714Skris 23355714Skrisint OBJ_NAME_remove(const char *name, int type) 23455714Skris { 23555714Skris OBJ_NAME on,*ret; 23655714Skris 23755714Skris if (names_lh == NULL) return(0); 23855714Skris 23955714Skris type&= ~OBJ_NAME_ALIAS; 24055714Skris on.name=name; 24155714Skris on.type=type; 242238405Sjkim ret=lh_OBJ_NAME_delete(names_lh,&on); 24355714Skris if (ret != NULL) 24455714Skris { 24555714Skris /* free things */ 24659191Skris if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) 24755714Skris { 24859191Skris /* XXX: I'm not sure I understand why the free 24959191Skris * function should get three arguments... 25059191Skris * -- Richard Levitte 25159191Skris */ 252109998Smarkm sk_NAME_FUNCS_value(name_funcs_stack, 253109998Smarkm ret->type)->free_func(ret->name,ret->type,ret->data); 25455714Skris } 25568651Skris OPENSSL_free(ret); 25655714Skris return(1); 25755714Skris } 25855714Skris else 25955714Skris return(0); 26055714Skris } 26155714Skris 262109998Smarkmstruct doall 263109998Smarkm { 264109998Smarkm int type; 265109998Smarkm void (*fn)(const OBJ_NAME *,void *arg); 266109998Smarkm void *arg; 267109998Smarkm }; 268109998Smarkm 269238405Sjkimstatic void do_all_fn_doall_arg(const OBJ_NAME *name,struct doall *d) 270109998Smarkm { 271109998Smarkm if(name->type == d->type) 272109998Smarkm d->fn(name,d->arg); 273109998Smarkm } 274109998Smarkm 275238405Sjkimstatic IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME, struct doall) 276109998Smarkm 277109998Smarkmvoid OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),void *arg) 278109998Smarkm { 279109998Smarkm struct doall d; 280109998Smarkm 281109998Smarkm d.type=type; 282109998Smarkm d.fn=fn; 283109998Smarkm d.arg=arg; 284109998Smarkm 285238405Sjkim lh_OBJ_NAME_doall_arg(names_lh, LHASH_DOALL_ARG_FN(do_all_fn), 286238405Sjkim struct doall, &d); 287109998Smarkm } 288109998Smarkm 289109998Smarkmstruct doall_sorted 290109998Smarkm { 291109998Smarkm int type; 292109998Smarkm int n; 293109998Smarkm const OBJ_NAME **names; 294109998Smarkm }; 295109998Smarkm 296109998Smarkmstatic void do_all_sorted_fn(const OBJ_NAME *name,void *d_) 297109998Smarkm { 298109998Smarkm struct doall_sorted *d=d_; 299109998Smarkm 300109998Smarkm if(name->type != d->type) 301109998Smarkm return; 302109998Smarkm 303109998Smarkm d->names[d->n++]=name; 304109998Smarkm } 305109998Smarkm 306109998Smarkmstatic int do_all_sorted_cmp(const void *n1_,const void *n2_) 307109998Smarkm { 308109998Smarkm const OBJ_NAME * const *n1=n1_; 309109998Smarkm const OBJ_NAME * const *n2=n2_; 310109998Smarkm 311109998Smarkm return strcmp((*n1)->name,(*n2)->name); 312109998Smarkm } 313109998Smarkm 314109998Smarkmvoid OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg), 315109998Smarkm void *arg) 316109998Smarkm { 317109998Smarkm struct doall_sorted d; 318109998Smarkm int n; 319109998Smarkm 320109998Smarkm d.type=type; 321238405Sjkim d.names=OPENSSL_malloc(lh_OBJ_NAME_num_items(names_lh)*sizeof *d.names); 322109998Smarkm d.n=0; 323109998Smarkm OBJ_NAME_do_all(type,do_all_sorted_fn,&d); 324109998Smarkm 325109998Smarkm qsort((void *)d.names,d.n,sizeof *d.names,do_all_sorted_cmp); 326109998Smarkm 327109998Smarkm for(n=0 ; n < d.n ; ++n) 328109998Smarkm fn(d.names[n],arg); 329109998Smarkm 330109998Smarkm OPENSSL_free((void *)d.names); 331109998Smarkm } 332109998Smarkm 33355714Skrisstatic int free_type; 33455714Skris 335238405Sjkimstatic void names_lh_free_doall(OBJ_NAME *onp) 336238405Sjkim { 337238405Sjkim if (onp == NULL) 338109998Smarkm return; 33955714Skris 340238405Sjkim if (free_type < 0 || free_type == onp->type) 34155714Skris OBJ_NAME_remove(onp->name,onp->type); 34255714Skris } 34355714Skris 344238405Sjkimstatic IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME) 345109998Smarkm 34659191Skrisstatic void name_funcs_free(NAME_FUNCS *ptr) 34759191Skris { 34868651Skris OPENSSL_free(ptr); 34959191Skris } 35059191Skris 35155714Skrisvoid OBJ_NAME_cleanup(int type) 35255714Skris { 35355714Skris unsigned long down_load; 35455714Skris 35555714Skris if (names_lh == NULL) return; 35655714Skris 35755714Skris free_type=type; 358238405Sjkim down_load=lh_OBJ_NAME_down_load(names_lh); 359238405Sjkim lh_OBJ_NAME_down_load(names_lh)=0; 36055714Skris 361238405Sjkim lh_OBJ_NAME_doall(names_lh,LHASH_DOALL_FN(names_lh_free)); 36255714Skris if (type < 0) 36355714Skris { 364238405Sjkim lh_OBJ_NAME_free(names_lh); 36559191Skris sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free); 36655714Skris names_lh=NULL; 36759191Skris name_funcs_stack = NULL; 36855714Skris } 36955714Skris else 370238405Sjkim lh_OBJ_NAME_down_load(names_lh)=down_load; 37155714Skris } 37255714Skris 373