proc_parameter_file( struct para_data_s *para, const char *fname,
                     struct output_control_s *outctrl, int card )
{
  struct para_data_s *r;
  const char *s1, *s2, *s3;
  size_t n;
  char *p;
  int is_default = 0;
  int have_user_id = 0;
  int err, algo;

  /* Check that we have all required parameters. */
  r = get_parameter( para, pKEYTYPE );
  if(r)
    {
      algo = get_parameter_algo (para, pKEYTYPE, &is_default);
      if (openpgp_pk_test_algo2 (algo, PUBKEY_USAGE_SIG))
	{
	  log_error ("%s:%d: invalid algorithm\n", fname, r->lnr );
	  return -1;
	}
    }
  else
    {
      log_error ("%s: no Key-Type specified\n",fname);
      return -1;
    }

  err = parse_parameter_usage (fname, para, pKEYUSAGE);
  if (!err)
    {
      /* Default to algo capabilities if key-usage is not provided and
         no default algorithm has been requested.  */
      r = xmalloc_clear(sizeof(*r));
      r->key = pKEYUSAGE;
      r->u.usage = (is_default
                    ? (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG)
                    : openpgp_pk_algo_usage(algo));
      append_to_parameter (para, r);
    }
  else if (err == -1)
    return -1;
  else
    {
      r = get_parameter (para, pKEYUSAGE);
      if (r && (r->u.usage & ~openpgp_pk_algo_usage (algo)))
        {
          log_error ("%s:%d: specified Key-Usage not allowed for algo %d\n",
                     fname, r->lnr, algo);
          return -1;
        }
    }

  is_default = 0;
  r = get_parameter( para, pSUBKEYTYPE );
  if(r)
    {
      algo = get_parameter_algo (para, pSUBKEYTYPE, &is_default);
      if (openpgp_pk_test_algo (algo))
	{
	  log_error ("%s:%d: invalid algorithm\n", fname, r->lnr );
	  return -1;
	}

      err = parse_parameter_usage (fname, para, pSUBKEYUSAGE);
      if (!err)
	{
	  /* Default to algo capabilities if subkey-usage is not
	     provided */
	  r = xmalloc_clear (sizeof(*r));
	  r->key = pSUBKEYUSAGE;
	  r->u.usage = (is_default
                        ? PUBKEY_USAGE_ENC
                        : openpgp_pk_algo_usage (algo));
          append_to_parameter (para, r);
	}
      else if (err == -1)
	return -1;
      else
        {
          r = get_parameter (para, pSUBKEYUSAGE);
          if (r && (r->u.usage & ~openpgp_pk_algo_usage (algo)))
            {
              log_error ("%s:%d: specified Subkey-Usage not allowed"
                         " for algo %d\n", fname, r->lnr, algo);
              return -1;
            }
        }
    }


  if( get_parameter_value( para, pUSERID ) )
    have_user_id=1;
  else
    {
      /* create the formatted user ID */
      s1 = get_parameter_value( para, pNAMEREAL );
      s2 = get_parameter_value( para, pNAMECOMMENT );
      s3 = get_parameter_value( para, pNAMEEMAIL );
      if( s1 || s2 || s3 )
	{
	  n = (s1?strlen(s1):0) + (s2?strlen(s2):0) + (s3?strlen(s3):0);
	  r = xmalloc_clear( sizeof *r + n + 20 );
	  r->key = pUSERID;
	  p = r->u.value;
	  if( s1 )
	    p = stpcpy(p, s1 );
	  if( s2 )
	    p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")");
	  if( s3 )
	    p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">");
          append_to_parameter (para, r);
	  have_user_id=1;
	}
    }

  if(!have_user_id)
    {
      log_error("%s: no User-ID specified\n",fname);
      return -1;
    }

  /* Set preferences, if any. */
  keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ), 0);

  /* Set keyserver, if any. */
  s1=get_parameter_value( para, pKEYSERVER );
  if(s1)
    {
      struct keyserver_spec *spec;

      spec = parse_keyserver_uri (s1, 1);
      if(spec)
	{
	  free_keyserver_spec(spec);
	  opt.def_keyserver_url=s1;
	}
      else
	{
	  log_error("%s:%d: invalid keyserver url\n", fname, r->lnr );
	  return -1;
	}
    }

  /* Set revoker, if any. */
  if (parse_revocation_key (fname, para, pREVOKER))
    return -1;


  /* Make KEYCREATIONDATE from Creation-Date.  */
  r = get_parameter (para, pCREATIONDATE);
  if (r && *r->u.value)
    {
      u32 seconds;

      seconds = parse_creation_string (r->u.value);
      if (!seconds)
	{
	  log_error ("%s:%d: invalid creation date\n", fname, r->lnr );
	  return -1;
	}
      r->u.creation = seconds;
      r->key = pKEYCREATIONDATE;  /* Change that entry. */
    }

  /* Make KEYEXPIRE from Expire-Date.  */
  r = get_parameter( para, pEXPIREDATE );
  if( r && *r->u.value )
    {
      u32 seconds;

      seconds = parse_expire_string( r->u.value );
      if( seconds == (u32)-1 )
	{
	  log_error("%s:%d: invalid expire date\n", fname, r->lnr );
	  return -1;
	}
      r->u.expire = seconds;
      r->key = pKEYEXPIRE;  /* change hat entry */
      /* also set it for the subkey */
      r = xmalloc_clear( sizeof *r + 20 );
      r->key = pSUBKEYEXPIRE;
      r->u.expire = seconds;
      append_to_parameter (para, r);
    }

  do_generate_keypair( para, outctrl, card );
  return 0;
}