key_byname (GETKEY_CTX *retctx, strlist_t namelist,
	    PKT_public_key *pk,
	    int want_secret, int include_unusable,
	    KBNODE * ret_kb, KEYDB_HANDLE * ret_kdbhd)
{
  int rc = 0;
  int n;
  strlist_t r;
  GETKEY_CTX ctx;
  KBNODE help_kb = NULL;

  if (retctx)
    {
      /* Reset the returned context in case of error.  */
      assert (!ret_kdbhd); /* Not allowed because the handle is stored
			      in the context.  */
      *retctx = NULL;
    }
  if (ret_kdbhd)
    *ret_kdbhd = NULL;

  if (!namelist)
    {
      ctx = xmalloc_clear (sizeof *ctx);
      ctx->nitems = 1;
      ctx->items[0].mode = KEYDB_SEARCH_MODE_FIRST;
      if (!include_unusable)
	ctx->items[0].skipfnc = skip_unusable;
    }
  else
    {
      /* Build the search context.  */
      for (n = 0, r = namelist; r; r = r->next)
	n++;

      ctx = xmalloc_clear (sizeof *ctx + (n - 1) * sizeof ctx->items);
      ctx->nitems = n;

      for (n = 0, r = namelist; r; r = r->next, n++)
	{
	  gpg_error_t err;

	  err = classify_user_id (r->d, &ctx->items[n], 1);

	  if (ctx->items[n].exact)
	    ctx->exact = 1;
	  if (err)
	    {
	      xfree (ctx);
	      return gpg_err_code (err); /* FIXME: remove gpg_err_code.  */
	    }
	  if (!include_unusable
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_SHORT_KID
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_LONG_KID
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_FPR16
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_FPR20
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_FPR)
	    ctx->items[n].skipfnc = skip_unusable;
	}
    }

  ctx->want_secret = want_secret;
  ctx->kr_handle = keydb_new ();
  if (!ret_kb)
    ret_kb = &help_kb;

  if (pk)
    {
      ctx->req_algo = pk->req_algo;
      ctx->req_usage = pk->req_usage;
    }

  rc = lookup (ctx, ret_kb, want_secret);
  if (!rc && pk)
    {
      pk_from_block (ctx, pk, *ret_kb);
    }

  release_kbnode (help_kb);

  if (retctx) /* Caller wants the context.  */
    *retctx = ctx;
  else
    {
      if (ret_kdbhd)
	{
	  *ret_kdbhd = ctx->kr_handle;
	  ctx->kr_handle = NULL;
	}
      get_pubkey_end (ctx);
    }

  return rc;
}
key_byname (GETKEY_CTX *retctx, strlist_t namelist,
	    PKT_public_key *pk,
	    int want_secret, int include_unusable,
	    KBNODE * ret_kb, KEYDB_HANDLE * ret_kdbhd)
{
  int rc = 0;
  int n;
  strlist_t r;
  GETKEY_CTX ctx;
  KBNODE help_kb = NULL;

  if (retctx)
    {
       
      assert (!ret_kdbhd);  
      *retctx = NULL;
    }
  if (ret_kdbhd)
    *ret_kdbhd = NULL;

  if (!namelist)
    {
      ctx = xmalloc_clear (sizeof *ctx);
      ctx->nitems = 1;
      ctx->items[0].mode = KEYDB_SEARCH_MODE_FIRST;
      if (!include_unusable)
	ctx->items[0].skipfnc = skip_unusable;
    }
  else
    {
       
      for (n = 0, r = namelist; r; r = r->next)
	n++;

      ctx = xmalloc_clear (sizeof *ctx + (n - 1) * sizeof ctx->items);
      ctx->nitems = n;

      for (n = 0, r = namelist; r; r = r->next, n++)
	{
	  gpg_error_t err;

	  err = classify_user_id (r->d, &ctx->items[n], 1);

	  if (ctx->items[n].exact)
	    ctx->exact = 1;
	  if (err)
	    {
	      xfree (ctx);
	      return gpg_err_code (err);  
	    }
	  if (!include_unusable
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_SHORT_KID
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_LONG_KID
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_FPR16
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_FPR20
	      && ctx->items[n].mode != KEYDB_SEARCH_MODE_FPR)
	    ctx->items[n].skipfnc = skip_unusable;
	}
    }

  ctx->want_secret = want_secret;
  ctx->kr_handle = keydb_new ();
  if (!ret_kb)
    ret_kb = &help_kb;

  if (pk)
    {
      ctx->req_algo = pk->req_algo;
      ctx->req_usage = pk->req_usage;
    }

  rc = lookup (ctx, ret_kb, want_secret);
  if (!rc && pk)
    {
      pk_from_block (ctx, pk, *ret_kb);
    }

  release_kbnode (help_kb);

  if (retctx)  
    *retctx = ctx;
  else
    {
      if (ret_kdbhd)
	{
	  *ret_kdbhd = ctx->kr_handle;
	  ctx->kr_handle = NULL;
	}
      get_pubkey_end (ctx);
    }

  return rc;
}