- if(!(*table))
- {
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing "
- "registered!\n", f, l, nid);
-#endif
- return NULL;
- }
- CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
- /* Check again inside the lock otherwise we could race against cleanup
- * operations. But don't worry about a fprintf(stderr). */
- if(!int_table_check(table, 0)) goto end;
- tmplate.nid = nid;
- fnd = lh_retrieve(&(*table)->piles, &tmplate);
- if(!fnd) goto end;
- if(fnd->funct && engine_unlocked_init(fnd->funct))
- {
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
- "ENGINE '%s' cached\n", f, l, nid, fnd->funct->id);
-#endif
- ret = fnd->funct;
- goto end;
- }
- if(fnd->uptodate)
- {
- ret = fnd->funct;
- goto end;
- }
-trynext:
- ret = sk_ENGINE_value(fnd->sk, loop++);
- if(!ret)
- {
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no "
- "registered implementations would initialise\n",
- f, l, nid);
-#endif
- goto end;
- }
- /* Try to initialise the ENGINE? */
- if((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT))
- initres = engine_unlocked_init(ret);
- else
- initres = 0;
- if(initres)
- {
- /* Update 'funct' */
- if((fnd->funct != ret) && engine_unlocked_init(ret))
- {
- /* If there was a previous default we release it. */
- if(fnd->funct)
- engine_unlocked_finish(fnd->funct, 0);
- fnd->funct = ret;
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, "
- "setting default to '%s'\n", f, l, nid, ret->id);
-#endif
- }
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
- "newly initialised '%s'\n", f, l, nid, ret->id);
-#endif
- goto end;
- }
- goto trynext;
-end:
- /* If it failed, it is unlikely to succeed again until some future
- * registrations have taken place. In all cases, we cache. */
- if(fnd) fnd->uptodate = 1;
-#ifdef ENGINE_TABLE_DEBUG
- if(ret)
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
- "ENGINE '%s'\n", f, l, nid, ret->id);
- else
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
- "'no matching ENGINE'\n", f, l, nid);
-#endif
- CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
- /* Whatever happened, any failed init()s are not failures in this
- * context, so clear our error state. */
- ERR_clear_error();
- return ret;
- }